Skip to main content
GameDev.net gamedev.net
🔒 Locked

Rendering a texture

Started by schupf Jul 23, 2013 at 2:20 PM 2 replies 2k views
Original Post
schupf
schupf

Hello!

I am very new to OpenGL and have a basic problem: I want to render 2 quads each with its own texture.

First I have an init function which loads the texture, generates the texture IDs and uploads the texture:


void initTex(TexObj& texObj, const char* imageFilename) // Images are .xpm files
{
   QImage image = QImage(imageFilename);
    texObj.w = image.width();
    texObj.h = image.height();

    QImage glImage;
    glImage = QGLWidget::convertToGLFormat(image);

    char* data = static_cast<char*>( calloc( texObj.w *  texObj.h, 4) ); 
    memcpy(data, glImage.bits(), texObj.w * texObj.h * 4);

    texObj.data = data
    glGenTextures(1, &texObj.texID);
    glBindTexture(GL_TEXTURE_2D, texObj.texID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texObj.w, texObj.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,  texObj.data);
}

Function initTex is called 2 times (for 2 different textures).

To render the 2 quads I use this function:


static void draw(TexObj& tex, float scale)
{
    glEnable(GL_CULL_FACE);
    glEnable( GL_TEXTURE_2D );
    glFrontFace( GL_CCW );

    glActiveTexture( GL_TEXTURE0 );
    glBindTexture(GL_TEXTURE_2D, tex.texID);

   // glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, tex->w, tex->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex->data );

    glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ;
    glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ;
    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) ; 

    glTranslated( 0.0, 0.0, 0.0 );
    glScalef( scale, scale, 1.0f );
   
      glPolygonMode(GL_FRONT, GL_FILL);
    glBegin(GL_POLYGON);
        glTexCoord2f( 0.0, 0.0 );
        glVertex2d(0.0, 1.0);
        glTexCoord2f( 0.0, -1.0 );
        glVertex2d(0.0, 0.0);
        glTexCoord2f( 1.0, -1.0 );
        glVertex2d(1.0, 0.0);
        glTexCoord2f( 1.0, 0.0 );
        glVertex2d(1.0, 1.0);
    glEnd();

    glDisable( GL_TEXTURE_2D );
    glDisable(GL_CULL_FACE);
}

The problem is: When I let this code run the quads are completely white!

The strange thing: When I comment in the outcommented line (glTexImage2D), the quads are textured! It seems like as if the texture I load into the VRAM in function init() is disappeared and I have to upload it every frame.

Does anyone have an idea what could cause this?

Thanks!

RobTheBloke
RobTheBloke

1. Move the following lines to the end of initTexture (there's no point repeastedly doing this)

glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ;
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ;
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) ;

2. Why are you doing this: texObj.data = data ? Unless it's for a very specific reason (getting heightmap values on the CPU side, as well as the GPU), it's just wasting memory. You can skip everything involving copying the data from the image (the calloc + memcpy), and instead just pass glImage.bits() to glTexImage2D directly.

3. You might find that using glPushMatrix / glPopMatrix surrounding the scaling and drawing of the quad will be useful (stops the transforms leaking into other draw calls).

4. glTranslated( 0.0, 0.0, 0.0 ); << this is pointless.

5.
enabling / disabling texturing and face culling constantly is a bit silly. You'd be better off moving those outside so you can do:

[source]
glEnable(GL_TEXTURE_2D);
glEnable(GL_CULL_FACE);

// draw all textured quads.

glDisable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D);
[/source]

6. glFrontFace( GL_CCW ); This is something you shouldn't need to be calling everytime you draw a single quad. Just once on start up will do fine (and then keep everything with the same winding order).



The problem is: When I let this code run the quads are completely white!

Check the values of tex.texID. Are they the same two values used when generating the texture?



The strange thing: When I comment in the outcommented line (glTexImage2D), the quads are textured! It seems like as if the texture I load into the VRAM in function init() is disappeared and I have to upload it every frame.

Which makes me think that you have either an invalid texture object, or that it's changing it's id somehow. You are initializing the textures AFTER you create the window right? (otherwise the gl context would be invalid, and the texture creation will fail).

So to recap, the rest of your app looks a little like this right?

[source]

TexObj g_tex1;

TexObj g_tex2;

int initGL()
{
// initialize and create GL window

// now textures are created.
initTex(g_tex1, "file1.bmp");
initTex(g_tex2, "file2.bmp");
}

void drawMethod()
{

draw(g_tex1, 1.0f);
draw(g_tex2, 1.0f);
}
[/source]

schupf
schupf

Thanks RobTheBloke for your detailed help! You pushed me in the right direction:)

The problem was: When I uploaded the images with glTexImage2D I had no OpenGL context. I find it very strange that glError() did not tell any error though...

One last question: How is it possible NOT to have a valid context? I mean after I create a context and "activate" it by calling wglMakeCurrent (), isn't the context now active forever? In other words: I thought after calling wglMakeCurrent() I can use OpenGL calls in my code in every function I want. Did I miss something?

Koehler
Koehler

I think the main case where you'd be unable to use a context is due to multithreading. An OpenGL context cannot be active on multiple threads, so in the case where you wanted to call OpenGL functions from different threads, you'd need to either create more than one context and have them share data (with wglShareLists), or have each thread sync and make the context current / not current as needed.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.