开发者

Qt Vertex Arrays not working with QImage

I'll begin by apologizing for the length of the question. I believe I've committed some smal开发者_如何转开发l, dumb error, but since I'm entirely unable to find it, I decided to post all relevant code just in case.

I finally got texture loading working using QImage, and am able to render textures in immediate mode. However, vertex arrays don't work, and I'm at a loss as to why. The most obvious things like "Have you enabled vertex arrays and texture coordinate arrays?" are probably not the answer. I'll post the initialization code.

Here's the init function:

    /* general OpenGL initialization function */
    int initGL()
    {

        glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
        glClearColor(0, 0, 0, 1);               // Black Background
        glEnable ( GL_COLOR_MATERIAL );
        glColorMaterial ( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );


        glDisable(GL_DEPTH_TEST);


//ENABLED VERTEX ARRAYS AND TEXTURE COORDINATE ARRAYS       
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_VERTEX_ARRAY);

//ENABLED 2D TEXTURING
        glEnable ( GL_TEXTURE_2D );
        glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );

        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

//seed random
        srand(time(NULL));


        return( TRUE );
    }

I have initialization, resize and draw functions that are called by a QGLWidget (which is itself just a skeleton that calls the real work functions)

The texture loading function:

GLuint LoadGLTextures( const char * name )
 {
     //unformatted QImage
     QImage img;
     //load the image from a .qrc resource
     if(!img.load(":/star.bmp"))
     {
         qWarning("ERROR LOADING IMAGE");
     }

     //an OpenGL formatted QImage
     QImage GL_formatted_image;
     GL_formatted_image = QGLWidget::convertToGLFormat(img);

     //error check
     if(GL_formatted_image.isNull())
         qWarning("IMAGE IS NULL");
     else
         qWarning("IMAGE NOT NULL");


     //texture ID
     GLuint _textures[1];


     //enable texturing
     glEnable(GL_TEXTURE_2D);
     //generate textures
     glGenTextures(1,&_textures[0]);
     //bind the texture
     glBindTexture(GL_TEXTURE_2D,_textures[0]);
     //texture parameters
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glBindTexture(GL_TEXTURE_2D,_textures[0]);
     //generate texture
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GL_formatted_image.width(),
                  GL_formatted_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
                  GL_formatted_image.bits());




     glBindTexture(GL_TEXTURE_2D,_textures[0]);

     //return the texture ID
     return _textures[0];
}

Here's the draw code:

//this does draw

//get the texture ID
    GLuint tex_id = LoadGLTextures(":/star.png");

        glBindTexture(GL_TEXTURE_2D, tex_id); // Actually have an array of images



        glColor3f(1.0f, 0.0f, 0.5f);
        glBegin(GL_QUADS);
            glTexCoord2f(1.0f, 0.0f);glVertex2f(1.0f, 0.0f);
            glTexCoord2f(1.0f, 1.0f);glVertex2f(1.0f, 1.0f);
            glTexCoord2f(0.0f, 1.0f);glVertex2f(0.0f, 1.0f);
            glTexCoord2f(0.0f, 0.0f);glVertex2f(0.0f, 0.0f);
        glEnd();


//this does not draw

        //translations code
        glLoadIdentity();
        glTranslatef(-1.0f, 0.0f, 0.0f);
        //bind the texture
        glBindTexture(GL_TEXTURE_2D, tex_id);
        //set color state
        glColor4f(0.0f, 1.0f, 0.0f, 0.5);

        //vertices to be rendered
        static GLfloat vertices[] =
        {
            1.0f, 0.0f,
            1.0f, 1.0f,
            0.0f, 1.0f,
            0.0f, 0.0f

        };

        static GLshort coord_Data[] =
        {
        1, 0,
        1, 1,
        0, 1,
        0, 0


        };

        //bind the texture
        glBindTexture(GL_TEXTURE_2D, tex_id);
        //pointer to the vertex array
        glVertexPointer(2, GL_FLOAT, 0, vertices);
        //texture coordinate pointer
        glTexCoordPointer(2, GL_SHORT, 0, coord_Data);

        //draw the arrays
        glDrawArrays(GL_QUADS, 0, 4);

Thanks for all help, Dragonwrenn


One possibility is that the problem stems from calling glVertexCoordPointer before calling glTexCoordPointer. Weird things happen when you specify the texture coordinate after the vertex coordinate. I know this is true for drawing a single vertex with a texture coordinate. I'm not sure if it's true with arrays.

A few other things...

Have you tried using QPixMap instead of QImage? I doubt this is the answer to your problem since it sounds like the texture is applied to the first quad properly.

There are two calls to bindTexture.

Have you tried just drawing the vertices (without the texture) in the second part of the code?

Finally, do you get any compiler warnings?


The way you place your OpenGL state manipulations, it is difficult to keep track of things. It's a good idea to set OpenGL state on demand. So

Move this

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_CORRD_ARRAY);

right before

    //bind the texture
    glBindTexture(GL_TEXTURE_2D, tex_id);
    glVertexPointer(2, GL_FLOAT, 0, vertices);
    glTexCoordPointer(2, GL_SHORT, 0, coord_Data);

    //draw the arrays
    glDrawArrays(GL_QUADS, 0, 4);

also you should move the other code from initGL.

Belonging into the texture loader, before supplying the data to glTexImage:

glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );

Belonging to the beginning of the drawing function:

glShadeModel(GL_SMOOTH);
glClearColor(0, 0, 0, 1);
glEnable( GL_COLOR_MATERIAL );
glColorMaterial ( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );

glDisable(GL_DEPTH_TEST);

Following the scheme you should set viewport and projection matrices in the drawing function, too. I'm just telling this, because most of the tutorials do it differently, which tricks people into thinking this was the right way. Technically projection and viewport and on-demand-states as well.

You should not re-load the texture with every draw call. Note that initializing the texture on demand through the drawing handler is a good idea, you should just add some flag to the texture encapsulating class telling, if the referenced texture is already available to OpenGL.

Just for debugging purposes try changing the type of the texture coordinates to floats.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜