VBO and Normal Maps

Hello. I’m following a normal mapping example I found online that creates a spinning textured cube and am trying to convert that to drawing it on a quad vbo for a 2d program. I’m using 3d opengl mode to take advantage of the lights and bump mapping but the program itself has no view changes outside of the 2d realm.

I can get a texture to work on my object with the following code.


GLfloat vertices[] = {1,1,1,  -1,1,1,  -1,-1,1,  1,-1,1};
GLubyte indices[] = {0,1,2,3};
GLfloat textureCoords [] = {1.0f,0.0f,  0.0f,0.0f,  0.0f,1.0f,  1.0f,1.0f};
GLfloat normals[] = {0,0,1,  0,0,1,  0,0,1,  0,0,1};

//....

    glActiveTexture(GL_TEXTURE1);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glNormalPointer(GL_FLOAT, 0, normals);
    glTexCoordPointer(2, GL_FLOAT, 0,textureCoords);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glBindTexture(GL_TEXTURE_2D, textureMap);
    glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, indices);
    glPopMatrix();
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);

It works perfectly fine, however my attempts at applying the multi-texture in the example have only resulted in a blank screen.

I can however get the example as a cube to work which is created with glBegin() and glEnd(). Here is the relevant part of the example code. First the textures are setup:


glActiveTexture(GL_TEXTURE0);

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glDisable(GL_TEXTURE_3D_EXT);
    glDisable(GL_TEXTURE_CUBE_MAP_ARB);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_TEXTURE_GEN_S);
    glDisable(GL_TEXTURE_GEN_T);
    glDisable(GL_TEXTURE_GEN_R);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

    glActiveTexture(GL_TEXTURE1);
    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glDisable(GL_TEXTURE_3D_EXT);
    glDisable(GL_TEXTURE_CUBE_MAP_ARB);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_TEXTURE_GEN_S);
    glDisable(GL_TEXTURE_GEN_T);
    glDisable(GL_TEXTURE_GEN_R);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


    glActiveTexture(GL_TEXTURE0);
    glBindTexture (GL_TEXTURE_2D, normalMap);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);      // Perform a Dot3 operation...
    glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_DOT3_RGB_EXT);
    glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);           // between the N (of N.L) which is stored in a normal map texture...
    glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
    glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); // with the L (of N.L) which is stored in the vertex's diffuse color.
    glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);


    glActiveTexture(GL_TEXTURE1);
    glBindTexture (GL_TEXTURE_2D, textureMap);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);  // Modulate...
    glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
    glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT);
    glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);    // the color argument passed down from the previous stage (stage 0) with...
    glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
    glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);    // the texture for this stage with.

Then some code for adding light:


    //
    // Transform the light's position from eye-space to object-space
    //
    vector3f vLightPosES;    // Light position (in eye-space)
    vector3f vLightPosOS;    // Light position (in object-space)
    vector3f vVertToLightOS; // L vector of N.L (in object-space)
    vector3f vVertToLightTS; // L vector of N.L (in tangent-space)
    // Get the light's current position, which is in eye-space.
    float fLightsPosition[4];
    glGetLightfv( GL_LIGHT0, GL_POSITION, fLightsPosition );
    vLightPosES.x = fLightsPosition[0];
    vLightPosES.y = fLightsPosition[1];
    vLightPosES.z = fLightsPosition[2];

    // Transform the light's position from eye-space into object-space
    matrix4x4f modelViewMatrix;
    matrix4x4f modelViewMatrixInverse;
    glGetFloatv(GL_MODELVIEW_MATRIX, &modelViewMatrix.m[0] );
    modelViewMatrixInverse = matrix4x4f::invertMatrix( &modelViewMatrix );
    vLightPosOS = vLightPosES;
    modelViewMatrixInverse.transformPoint( &vLightPosOS );

Finally the cube is drawn:


    vector3f vCurrentVertex;
    glBegin( GL_QUADS );
    for( int i = 0; i < NUM_VERTICES; ++i ) {
        vCurrentVertex.x = g_cubeVertices[i].x;
        vCurrentVertex.y = g_cubeVertices[i].y;
        vCurrentVertex.z = g_cubeVertices[i].z;
        glMultiTexCoord2f( GL_TEXTURE0, g_cubeVertices[i].tu, g_cubeVertices[i].tv );
        glMultiTexCoord2f( GL_TEXTURE1, g_cubeVertices[i].tu, g_cubeVertices[i].tv );
        vVertToLightOS = vLightPosOS - vCurrentVertex;
        vVertToLightOS.normalize();
        matrix4x4f invTangentMatrix( g_vTangents[i].x, g_vBiNormals[i].x, g_vNormals[i].x, 0.0f,
                                     g_vTangents[i].y, g_vBiNormals[i].y, g_vNormals[i].y, 0.0f,
                                     g_vTangents[i].z, g_vBiNormals[i].z, g_vNormals[i].z, 0.0f,
                                     0.0f,             0.0f,              0.0f,            1.0f );
        vVertToLightTS = vVertToLightOS;
        invTangentMatrix.transformVector( &vVertToLightTS );
        vector3f vVertToLightTS_scaledAndBiased = scaleAndBiasVectorAsRGBColor( &vVertToLightTS );

        glColor3f( vVertToLightTS_scaledAndBiased.x,
                   vVertToLightTS_scaledAndBiased.y,
                   vVertToLightTS_scaledAndBiased.z );

        glNormal3f( g_cubeVertices[i].nx, g_cubeVertices[i].ny, g_cubeVertices[i].nz );
        glVertex3f( vCurrentVertex.x, vCurrentVertex.y, vCurrentVertex.z );
    }
    glEnd();

I’ve tried copying the texture setup part of the code and choosing the texture ( glActiveTexture(GL_TEXTURE1); glBindTexture (GL_TEXTURE_2D, textureMap):wink: in my code but it always shows blank.


Also the g_vTangents, g_vBiNormals, and g_vNormals arrays in their code is calculated with a couple functions that convert tangent space for proper lighting (computeTangentsMatricesForEachVertex(); and createTangentSpaceVectors();). Although I understand the theory behind tangent and object space, I don’t yet have a full understanding of the math behind it. I think since I am not planning on having real 3d angles in my code and everything is just going to be a texture put on a quad that is always facing the user I won’t need to calculate that since it will always be the same? Am I correct in this? If so, if anyone has the correct normals(?) I should be plugging in for a simple quad it would be much appreciated as well :).

Thanks!