6
votes

I'm a bit new to OpenGL and I've been having a problem with using textures. The texture seems to load fine, but when I run the program, the texture displays shifted a couple pixels to the left, with the section cut off by the shift appearing on the right side. I don't know if the problem here is in the my TGA loader or if it's the way I'm applying the texture to the quad.

Here is the loader:

#include "texture.h"
#include <iostream>

GLubyte uncompressedheader[12] = {0,0, 2,0,0,0,0,0,0,0,0,0};
GLubyte compressedheader[12]   = {0,0,10,0,0,0,0,0,0,0,0,0};


TGA::TGA()
{

}

//Private loading function called by LoadTGA.  Loads uncompressed TGA files
//Returns: TRUE on success, FALSE on failure
bool TGA::LoadCompressedTGA(char *filename,ifstream &texturestream)
{
 return false;
}

bool TGA::LoadUncompressedTGA(char *filename,ifstream &texturestream)
{
 cout << "G position status:" << texturestream.tellg() << endl;
 texturestream.read((char*)header, sizeof(header));     //read 6 bytes into the file to get the tga header
 width  = (GLuint)header[1] * 256 + (GLuint)header[0];    //read and calculate width and save
 height = (GLuint)header[3] * 256 + (GLuint)header[2];    //read and calculate height and save
 bpp    = (GLuint)header[4];           //read bpp and save

 cout << bpp << endl;

 if((width <= 0) || (height <= 0) || ((bpp != 24) && (bpp !=32))) //check to make sure the height, width, and bpp are valid
 {
  return false;
 }
 if(bpp == 24)         
 {
  type = GL_RGB;
 }
 else
 {
  type = GL_RGBA;
 }
 imagesize = ((bpp/8) * width * height);          //determine size in bytes of the image
 cout << imagesize << endl;
 imagedata = new GLubyte[imagesize];           //allocate memory for our imagedata variable

 texturestream.read((char*)imagedata,imagesize);        //read according the the size of the image and save into imagedata 

 for(GLuint cswap = 0; cswap < (GLuint)imagesize; cswap += (bpp/8))         //loop through and reverse the tga's BGR format to RGB
 {
  imagedata[cswap] ^= imagedata[cswap+2] ^=                    //1st Byte XOR 3rd Byte XOR 1st Byte XOR 3rd Byte
     imagedata[cswap] ^= imagedata[cswap+2];
 }

 texturestream.close();              //close ifstream because we're done with it
 cout << "image loaded" << endl;

 glGenTextures(1, &texID);             // Generate OpenGL texture IDs
 glBindTexture(GL_TEXTURE_2D, texID);          // Bind Our Texture
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);   // Linear Filtered
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexImage2D(GL_TEXTURE_2D, 0, type, width, height, 0, type, GL_UNSIGNED_BYTE, imagedata);



    delete imagedata;
 return true;
}

//Public loading function for TGA images.  Opens TGA file and determines 
//its type, if any, then loads it and calls the appropriate function.
//Returns: TRUE on success, FALSE on failure

bool TGA::loadTGA(char *filename)
{
 cout << width << endl;
 ifstream texturestream;
 texturestream.open(filename,ios::binary);
 texturestream.read((char*)header,sizeof(header));     //read 6 bytes into the file, its the header.                //if it matches the uncompressed header's first 6 bytes, load it as uncompressed
 LoadUncompressedTGA(filename,texturestream); 
 return true;
}

GLubyte* TGA::getImageData()
{
 return imagedata;
}

GLuint& TGA::getTexID()
{
 return texID;
}

And here's the quad:

void Square::show()
{     

 glEnable(GL_TEXTURE_2D);
 glBindTexture(GL_TEXTURE_2D, texture.texID);


    //Move to offset
    glTranslatef( x, y, 0 );

 //Start quad
    glBegin( GL_QUADS );

 //Set color to white
 glColor4f( 1.0, 1.0, 1.0, 1.0 );

 //Draw square
 glTexCoord2f(0.0f, 0.0f);  glVertex3f( 0,            0,             0 );
 glTexCoord2f(1.0f, 0.0f);  glVertex3f( SQUARE_WIDTH, 0,             0 );
 glTexCoord2f(1.0f, 1.0f);  glVertex3f( SQUARE_WIDTH, SQUARE_HEIGHT, 0 );
 glTexCoord2f(0.0f, 1.0f);  glVertex3f( 0,            SQUARE_HEIGHT, 0 );

    //End quad   
    glEnd();

    //Reset
 glLoadIdentity();
}
2

2 Answers

3
votes

A screenshot would be very helpful.
My first guess is that your rows are not 4 byte aligned. If so, change unpack alignment to 1 byte with glPixelStorei(GL_UNPACK_ALIGNMENT, 1); before calling glTexImage2D().

3
votes

You want to set the texture parameter so that the texture scales to fit the quad. You do that with the following lines of code:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

These will have textures scale linearly up or down to fit the quad.

You should probably also clamp the texture with the following calls:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);