1
votes

I am working with textures in OpenGL and have came across a strange issue. Sometimes an image that's loaded in is pushed over to the right slightly. I will supply code and screen shots below.

Image

#include <gl/glew.h>
#include <gl/glut.h>
#include <windows.h>
#include <stdio.h>
#include <SOIL.h>

const int WINDOW_WIDTH = 1024;
const int WINDOW_HEIGHT = 512;

GLuint Tex;
GLuint Tex2;

GLuint LoadTexture( const char * filename, int w, int h )
{
    GLuint texture;
    int width, height;
    unsigned char * data;
    FILE * file;
    file = fopen( filename, "rb" );

    if ( file == NULL ) return 0;
    width = w;
    height = h;
    data = (unsigned char *)malloc( width * height * 3);
    fread( data, width * height * 3, 1, file );
    fclose( file );

    glGenTextures( 1, &texture );
    glBindTexture( GL_TEXTURE_2D, texture );
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE );

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST );

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT );
    gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height,GL_RGB, GL_UNSIGNED_BYTE, data );
    free( data );

    return texture;
}

void Reshape( int width, int height )
{
    glViewport( 0, 0, (GLsizei)width, (GLsizei)height );
    glMatrixMode( GL_PROJECTION );

    glLoadIdentity();
    glOrtho( 0.0f, WINDOW_WIDTH, 0.0f, WINDOW_HEIGHT, 1.0f, 100.0f );

    glMatrixMode( GL_MODELVIEW );
}

void lightInit( void )
{
    GLfloat lightWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    GLfloat lightBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lightWhite );
    glMaterialf( GL_FRONT, GL_SHININESS, 30 );

    glLightfv( GL_LIGHT0, GL_AMBIENT, lightBlack );
    glLightfv( GL_LIGHT0, GL_SPECULAR, lightWhite );
    glLightfv( GL_LIGHT0, GL_DIFFUSE, lightWhite );
    glLightfv( GL_LIGHT0, GL_POSITION, lightPos );

    glEnable( GL_LIGHTING );
    glEnable( GL_LIGHT0 );
    glEnable( GL_COLOR_MATERIAL );
    glEnable( GL_DEPTH_TEST );
}

void drawTexObj()
{
    Tex = LoadTexture( "texture2.bmp", 1024, 512 );
    if( Tex == 0 )
    {
        exit(0);
    }
    glEnable( GL_TEXTURE_2D );
    glPushAttrib( GL_CURRENT_BIT );
    glBegin( GL_QUADS );
        glTexCoord2d( 0.0f, 0.0f );
        glVertex2f( 0.0f, 0.0f );

        glTexCoord2d( 0.0f, 1.0f );
        glVertex2f( 0.0f, 512.0f );

        glTexCoord2d( 1.0f, 1.0f );
        glVertex2f( 1024.0f, 512.0f );

        glTexCoord2d( 1.0f, 0.0f );
        glVertex2f( 1024.0f, 0.0f );
    glEnd();
    glPopAttrib();
    glDisable( GL_TEXTURE_2D );
    glDeleteTextures( (GLsizei)1, &Tex );
}

void drawTexObj2()
{
    Tex2 = LoadTexture( "texture.bmp", 1024, 512 );
    if( Tex2 == 0 )
    {
        exit(0);
    }
    glEnable( GL_TEXTURE_2D );
    glBegin( GL_QUADS );

        glTexCoord2d( 0.0f, 0.0f );
        glVertex2f( 0.0f, 0.0f );

        glTexCoord2d( 0.0f, 1.0f );
        glVertex2f( 0.0f, 256.0f );

        glTexCoord2d( 1.0f, 1.0f );
        glVertex2f( 512.0f, 256.0f );

        glTexCoord2d( 1.0f, 0.0f );
        glVertex2f( 512.0f, 0.0f );

    glEnd();
    glDisable( GL_TEXTURE_2D );
    glDeleteTextures( (GLsizei)1, &Tex2 );
}

void Display()
{
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glLoadIdentity();
    glTranslatef( 0.0f, 0.0f, -1.0f );

    drawTexObj();
    drawTexObj2();

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
    glEnable( GL_DEPTH );

    glutInitWindowPosition( 200, 100 );
    glutInitWindowSize( 1024, 512 );

    glutCreateWindow( "Texturing :D!" );

    //lightInit();

    glutDisplayFunc( Display );
    glutIdleFunc( Display );
    glutReshapeFunc( Reshape );

    glutMainLoop();
}
1
Why #include SOIL if you aren't using it?genpfault
My first intuition says it has something to do with GL_DEPTH and/or GL_REPEATchunkyguy
You are actually loading and deleting the texture every frame? That would be the first thing I would fix.Grimmy
Yeah, I must say that this is not neat code what so ever. It's simply to see if I can get it working. The SOIL include was because, I was slipping in and out of using it. Just a little mistake :-)DavidBittner

1 Answers

2
votes

This looks like an issue with reading the file in the first place. BMP files are not simple neat arrays of pixel bytes, so you can't just read in width*height*3 bytes. You will see the image data in there, (assuming 24 bpp storage), but there is also header information which will push the pixel data over on the display. I'm surprised that the 2nd bitmap looks OK, although this might be coincidence that the header matches the image width.

A better solution would be to use the Gdi to load the images...

GdiplusStartupInput lstartup_input;
GdiplusStartupOutput lstartup_output;
ULONG_PTR   ltoken;

GdiplusStartup(&ltoken, &lstartup_input, &lstartup_output);

Bitmap *lbitmap;
lbitmap = new Bitmap(wszPath);

GdiplusShutdown(ltoken);

RGBQUAD *pBits = (RGBQUAD *) malloc(lbitmap->GetWidth() * lbitmap->GetHeight() * 4 * sizeof(BYTE));
lbitmapdata.Scan0 = pBits;
lbitmapdata.Width = lbitmap->GetWidth();
lbitmapdata.Height = lbitmap->GetHeight();
lbitmapdata.PixelFormat = PixelFormat32bppARGB;
lbitmapdata.Stride = lbitmap->GetWidth()*4;

Rect    lrect(0,0,lbitmap->GetWidth(), lbitmap->GetHeight());
st = lbitmap->LockBits(&lrect, ImageLockModeUserInputBuf | ImageLockModeRead,
    PixelFormat32bppARGB, &lbitmapdata);
ASSERT(st == Ok);
st = lbitmap->UnlockBits(&lbitmapdata); // Unlock straightaway, because we just want to extract the pixel data
ASSERT(st == Ok);

This snipped uses 4 bytes per-pixel, as I use the alpha channel, but from there you should be able to convert it as you need it. Here's a code snippet to convert the BGRA to RGB. (You could change the pixel format for UnlockBits to PixelFormat24bppRGB, but you might still need to swap the colours about - try it and see.)

BYTE *rgbBits = (malloc lbitmap->GetHeight() * lbitmap->GetWidth() * 3);
BYTE *rgbPtr = rgbBits;
pPixel = (RGBQUAD *)m_pBits;
for (li = 0; li < lbitmap->GetHeight() * lbitmap->GetWidth(); li++)
{
    *(rgbPtr++) = pPixel->rgbRed;
    *(rgbPtr++) = pPixel->rgbGreen;
    *(rgbPtr++) = pPixel->rgbBlue;
    pPixel++;
}

(Note that I just pulled this code out of my project, so it might need some cleaning up. Let me know.)