Jump to content
  • Advertisement
Sign in to follow this  
CBell

Adding Textures Question

This topic is 3653 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have some images saved on my computer that I would like to use as textures. I've looked at the red book examples for adding textures, but all of them generate the textures in the code. How would I add a texture that is already saved on my computer? Also, can I use any image file as a texture? Or am I limited to certain files?

Share this post


Link to post
Share on other sites
Advertisement
Would I just do an fopen and open the image file I want, and then fread it into memory?

If so, that might be a pain, cause I've got a lot of textures I want to use. But oh well.

Share this post


Link to post
Share on other sites
Pretty much. You'd make your life a lot easier by using an image library, though. For example, corona:

// load corona image from file called "picture.jpg", in format RGBA8
corona::Image *img = corona::OpenImage("picture.jpg", corona::PF_R8G8B8A8);
// grab pixel data
unsigned char *pixels = img->getPixels();

// build texture out of pixels, which will be in specified pixel format

// delete image from system memory, as it is on the GPU now
delete img; // (yes, corona::Image::operator delete() is overloaded)

This would be the general way to do it.

Then you'd just load whichever images you want using the same generic method. And, yes, any image file can be used as a texture so long you can read it (the example I used, corona, can load most common formats like JPEG, PNG, TGA, BMP, etc.)

Share this post


Link to post
Share on other sites
Cool, I'll look into that. Right now I'm just trying to do it so that I can get an idea of what's going on. I'm having a little trouble, though. I'm kind of following the example here:

http://www.nullterminator.net/gltexture.html

Pretty much all I've done is change the BYTE data type to an unsigned char, and moved the function he wrote to init. Here's what I have:

void init()
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glGenTextures(9, textures);

unsigned char * data;
FILE * file;

// open texture data
file = fopen( "Sun1.jpg", "rb" );
if ( file == NULL ) cerr << "Error, Could not read Texture";

// allocate buffer
int width = 512;
int height = 256;
data = (unsigned char*) malloc( (unsigned char) (width * height * 3) );

// read texture data
fread( data, width * height * 3, 1, file );
fclose( file );

glBindTexture(GL_TEXTURE_2D, textures[0]);

// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

// if wrap is true, the texture wraps over at the edges (repeat)
// ... false, the texture ends at the edges (clamp)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );

// build our texture mipmaps
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data );

// free buffer
free( data );

glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
}



My problem is that the program won't appear. It compiles fine, but the program won't show on the screen. If I comment out all the code to read the texture from the file and also comment out gluBuild2DMipmaps(), the program will run fine, but I want the texture to show up, so I'm pretty sure the problem is there somewhere.

Share this post


Link to post
Share on other sites
Well, you're reading in a JPEG. That's not raw data but compressed and encoded data. Look at the file, it should be much smaller than 512 * 256 * 3 = 384KB.

Your texture can not be read correctly and if you add some error handling code like glGetError() you should get a hint on that.

Try an image library or read in some uncompressed image data like a .bmp (note that there's a header though, so filesize = sizeof(header) + sizeof(data)).

Edit: Just an excerpt from the link above: "For the sake of simplicity, I'll use an example RAW texture file. This is essentially just the raw image data stored in a binary file." This means he's only reading uncompressed data without any header.

Share this post


Link to post
Share on other sites
I found NeHe's IPicture code that can use .jpgs and whatnot, but I use OS X and the code he wrote is designed for Windows. How, or what, would I do to make it work in OS X/Linux?

Share this post


Link to post
Share on other sites
You need to write some code to be able to read in the texture file into memory first. Once you do that, then you can create your texture in OpenGL. I have a video tutorial on my website showing all the steps required to load and display TGA images.

Share this post


Link to post
Share on other sites
For a beginner, I would use SDL and SDL_image library in order to load your images. When you become more experienced you can move on to using the separate libraries themselves that are wrapped by SDL.Also, for something to chew on and think about, its little known fact that Opengl has trouble with any texture that isnt to the power of 2, for example, 2x2,4x4 8x8,16x16,etc. While Opengl can support non power of 2 textures, it is preferred and rendering is much faster.

Share this post


Link to post
Share on other sites
O.K. I've tried using NeHe's Lesson: 24 for loading .tga's to use a textures. This is the code for that:

typedef struct
{
GLubyte *imageData;
GLuint bpp;
GLuint width;
GLuint height;
GLuint texID;
} TextureImage;

TextureImage textures[9];

bool LoadTGA(TextureImage *texture, char *filename)
{
GLubyte TGAheader[12] = {0,0,2,0,0,0,0,0,0,0,0,0};
GLubyte TGAcompare[12];
GLubyte header[6];
GLuint bytesPerPixel;
GLuint imageSize;
GLuint temp;
GLuint type = GL_RGBA;

FILE *file = fopen(filename, "rb");

if(file==NULL || fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare) ||
memcmp(TGAheader, TGAcompare, sizeof(TGAheader))!=0 ||
fread(header, 1, sizeof(header), file)!=sizeof(header))
{
if (file == NULL)
{
return false;
}else
{
fclose(file);
return false;
}
}

texture->width = header[1]*256 + header[0];
texture->height = header[3]*256 + header[2];

if(texture->width <= 0 || texture->height <=0 || (header[4]!=24 && header[4]!=32))
{
fclose(file);
return false;
}

texture->bpp = header[4];
bytesPerPixel = texture->bpp/8;
imageSize = texture->width*texture->height*bytesPerPixel;

texture->imageData = (GLubyte *)malloc(imageSize);

if(texture->imageData == NULL || fread(texture->imageData, 1, imageSize, file)!=imageSize)
{
if(texture->imageData!=NULL)
free(texture->imageData);
fclose(file);
return false;
}

//Swaps Red and Blue bits of TGA file so OpenGL can proberly read it
for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)
{
temp=texture->imageData;
texture->imageData = texture->imageData[i+2];
texture->imageData[i+2] = temp;
}

fclose(file);

//Finally build the texture
glGenTextures(1, &texture[0].texID);

glBindTexture(GL_TEXTURE_2D, texture[0].texID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );

if(texture[0].bpp == 24)
type = GL_RGB;

// build our texture mipmaps
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, texture[0].width, texture[0].height, type, GL_UNSIGNED_BYTE, texture[0].imageData);
//glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData);

return true;
}


Since I don't have any .tga's, I've converted a couple .jpg's that I have to 32 bit .tga's, but when the code compares TGAheader with TGAcompare they end up being different.

I've done some testing, and header[4] does equal 32, but later on when it calls malloc(imageSize) and does the fread(texture->imageData, 1, imageSize, file), the fread does not equal imageSize.

For the .tga I tried it with, imageSize = 393216 bytes which = 384 kb, right? Well the file size of the .tga according to my computer is 380 kb. Any idea as to what's going wrong?

Share this post


Link to post
Share on other sites
Well, if the dimensions of the .tga are still 512 * 256 you'd endup with an uncompressed image size of 512 KB (512 * 256 * 4 (32-bit = 4 bytes)). So what you have here is a compressed texture.

Typically TGA-Files are runlength encoded, i.e. instead of a single pixel you have a structure of color + number of consecutive pixels of that color.

Also, NeHe seems to use the old .tga format. The new format has a footer that is 26 bytes long and contains the string "TRUEVISION-XFILE." (without the quotes). The new format means that there might be additional data right after the image data, so the file would look like this:

//header
//imagedata
//extradata
TRUEVISION-XFILE.

Have a look at wotsit.org for a description of the TGA format.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!