[ Main Page ]

SDL_imageをOpenGLのTextureで利用する

OpenGL(GL/GLU/GLUT)自体は、殆んどの画像フォーマットをサポートしていないので、 Textureの読込みは骨が折れます。そこで、 OpenGLとSDLの連携 を参考にして、SDLで様々な画像をTextureとして読み込む例を挙げてみます。

TextureImage.h

#ifndef TEXTUREIMAGE_H
#define TEXTUREIMAGE_H

#include <iostream>
#include <GL/glut.h>
#include <SDL/SDL_image.h>
#include <vector>
#include <map>
#include <string>

typedef struct{
  std::string filename;
  GLuint textureID;
  int width;
  int height;
} TextureInfo;

class TextureImage
{
  private:
  std::map<std::string, TextureInfo> Textures;
  public:
  int loadImage(char * filename);
  TextureInfo * getTexture(char * filename);
};

#endif
      

TextureImage.cpp

#include "TextureImage.h"
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

int TextureImage::loadImage(char *filename)
{
  SDL_Surface *Image = NULL;
  SDL_Surface *tmpImage;
  GLuint texID = 0;
  TextureInfo texture;

  if(Image = IMG_Load(filename))
  {
    tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, 32, 
        0x000000ff, 
        0x0000ff00, 
        0x00ff0000, 
        0xff000000);
    Image = SDL_ConvertSurface(Image, tmpImage->format, SDL_SWSURFACE);
    SDL_FreeSurface(tmpImage);

    glGenTextures(1, &texID);
    glBindTexture(GL_TEXTURE_2D, texID);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    // これだと規定のサイズの画像しか読み込めない
    /* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Image->w, Image->h, 0,
        GL_RGBA, GL_UNSIGNED_BYTE, Image->pixels); */

    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, Image->w, Image->h,
        GL_RGBA, GL_UNSIGNED_BYTE, Image->pixels);

    SDL_FreeSurface(Image);

    texture.filename = filename;
    texture.textureID = texID;
    texture.width = Image->w;
    texture.height = Image->h;
    Textures.insert(std::pair<std::string, TextureInfo>(filename, texture));
    return 0;
  }
  return -1;
}

TextureInfo * TextureImage::getTexture(char *filename)
{
  std::map<std::string, TextureInfo>::iterator i = Textures.find(filename);
  if(i != Textures.end())
    {
      return &(i->second);
    }
  if(loadImage(filename) == 0)
    {
      return getTexture(filename);
    }
  return NULL;
}
      

glTexImage2Dの代わりにgluBuild2DMipmapsを使えば、画像Pixelサイズに 左右されずに詠みこめる筈です。もっとも、最近のOpenGLでは、 その問題は解消されたようですが。あとは、以下のようにすれば 一応Textureは使える筈です。

#include "TextureImage.h"
...
TextureImage *texture;
...
texture = new TextureImage();
...
void display(void)
{
  TextureInfo * tex;

  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  glRotated(1.1, 0.0, 1.0, 0.0);

  glEnable(GL_LINE_SMOOTH);  
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_TEXTURE_2D);
  if((tex = texture->getTexture("sample.gif")) == NULL)
    exit(-1);
  glBindTexture(GL_TEXTURE_2D, tex->textureID);
  glBegin(GL_POLYGON);
  glTexCoord2f(0, 1);
  glVertex2f(0, 0);
  glTexCoord2f(0, 0);
  glVertex2f(0, tex->height/100);
  glTexCoord2f(1, 0);
  glVertex2f(tex->width/100, tex->height/100);
  glTexCoord2f(1, 1);
  glVertex2f(tex->width/100, 0);
  glEnd();
  glDisable(GL_TEXTURE_2D);

  glEnable(GL_TEXTURE_2D);
  // エラーチェックなし
  glBindTexture(GL_TEXTURE_2D, texture->getTexture("tiles.png")->textureID);
  glBegin(GL_POLYGON);
  glTexCoord2f(0 , 0); glVertex3f(-4.9 ,1,3);
  glTexCoord2f(0 , 1); glVertex3f(-4.9 ,1,-3);
  glTexCoord2f(1 , 1); glVertex3f(3.9 , 1,-3);
  glTexCoord2f(1 , 0); glVertex3f(3.9 , 1,3);
  glEnd();
  glDisable(GL_TEXTURE_2D);
  ...
  glutSwapBuffers();
}
...
      

-lSDL -lSDL_imageをリンクすればいい筈です。

There is no hunting like the hunting of man, and those who have hunted
armed men long enough and liked it, never care for anything else thereafter.
		-- Ernest Hemingway

 <WebDragon>  y'all should spell it in uppercase it being an acronym and
              all
  <reaction>  Yes, but we're *lazy*!
           *  WebDragon *so* noticed ;)
       <dkr>  WebDragon: people that use CamelCase have no right to
              criticize about capitalization. :)
 <WebDragon>  dkr: I hate underscores
           *  dkr contemplates a source code filter that does lets you use
              spaces in var names by switch them to underscores at compile
              time
 <preaction>  black magic
       <mst>  dkr: source filters are evil.
       <mst>  dkr: in a bad way.
       <mst>  dkr: hacking the compiler is much more fun, and evil in a
              useful way :)
       <mst>  WebDragon: recommended perl style is $var_name
       <mst>  WebDragon: it's also more readable than $varName or $VarName
       <mst>  WebDragon: I'd recommend trying it for at least a month
       <mst>  WebDragon: also note that it'll make life easier because
              you'll be consistent with the rest of perl code
 <WebDragon>  mst: I was thinking more along the lines of filenames and
              irc nicknames than perl variables
       <mst>  WebDragon: ah. fair enough :)
           *  WebDragon doesn't use camelcase for perlvars
       <mst>  WebDragon: then I shall cease complaining :)
      <avar>  ${"Insert a descriptive essay about the variable here"}
 <WebDragon>  rofl
   <rindolf>  avar: that won't work with 'use strict 'refs''
 <WebDragon>  avar: I've seen things like that in RL and had recurring
              nightmares about them when I saw similar and sometimes worse
              things on thedailywtf.com
       <mst>  rindolf: ${main::}{"Insert a descriptive essay about the
              variable here"} would :)
       <mst>  rindolf: or you could just use %_ :)
       <dkr>  my boss still occasionally uses vars like $x. still trying
              to beat that behavior out of him
           *  WebDragon only uses x|y|z for cartesian coordinate math
 <WebDragon>  which, since I hardly ever do any of that, means the obvious

    -- What's in a variable name?
    -- #perl, Freenode


Powered by UNIX fortune(6)
[ Main Page ]