4

所以我需要编辑这个问题。如其中一条评论所述,我更改为使用缓冲区的渲染方法。但是,几何图形未正确绘制。如果我使用相同的缓冲区并手动绘制顶点,它看起来还不错(虽然没有纹理,但有些东西搞砸了)。我也尝试用顶点信息构建一个缓冲区,但这根本没有帮助。

void ModelHandler::DrawModels(){


    //go through each of the models
    for(int i=0;i<Models3D.size();i++){

        //glEnableClientState(GL_VERTEX_ARRAY);
        //glVertexPointer(3, GL_FLOAT, 0, Models3D[i]->object.m_pVertice);


        //now draw all the material groups with their vertices for the model
        for(int j=0;j<Models3D[i]->object.mtlGroups.size();j++){


            //Drawing the vertices manually from the buffer object seems to work
            /*
            for(int lj=0;lj<Models3D[i]->object.mtlGroups[j]->m_vecgroupVerticeIndex.size();lj++){

                int mtlIndex2 = Models3D[i]->object.FindMaterial(Models3D[i]->object.mtlGroups[j]->mtlName);
                bool tOn = false;

                //check if there was a texture for this material
                if(Models3D[i]->object.materials[mtlIndex2]->texturePresent){

                    glEnable(GL_TEXTURE_2D);
                    //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
                    glBindTexture(GL_TEXTURE_2D, Models3D[i]->object.materials[mtlIndex2]->textureIDDiffuse);
                    tOn = true;


                }

                if(tOn){
                    glBegin (GL_QUADS);
                    glTexCoord2f (0.0, 0.0);
                    glVertex3f (0.0+5, 0.0, -2.0f);
                    glTexCoord2f (1.0, 0.0);
                    glVertex3f (1.4f+5, 0.0, -2.0f);
                    glTexCoord2f (1.0, 1.0);
                    glVertex3f (1.4f+5, -1.0, -2.0f);
                    glTexCoord2f (0.0, 1.0);
                    glVertex3f (0.0f+5, -1.0, -2.0f);
                    glEnd ();               
                }



                glBegin(GL_TRIANGLES);

                glColor3f(Models3D[i]->object.mtlGroups[j]->VBO[lj*3].colour[0],Models3D[i]->object.mtlGroups[j]->VBO[lj*3].colour[1],Models3D[i]->object.mtlGroups[j]->VBO[lj*3].colour[2]);
                if(tOn){
                glTexCoord2f (Models3D[i]->object.mtlGroups[j]->VBO[lj*3].tex[0], Models3D[i]->object.mtlGroups[j]->VBO[lj*3].tex[1]);
                }
                glVertex3f(Models3D[i]->object.mtlGroups[j]->VBO[lj*3].location[0], Models3D[i]->object.mtlGroups[j]->VBO[lj*3].location[1], Models3D[i]->object.mtlGroups[j]->VBO[lj*3].location[2]);


                glColor3f(Models3D[i]->object.mtlGroups[j]->VBO[lj*3+1].colour[0],Models3D[i]->object.mtlGroups[j]->VBO[lj*3+1].colour[1],Models3D[i]->object.mtlGroups[j]->VBO[lj*3+1].colour[2]);
                if(tOn){
                glTexCoord2f (Models3D[i]->object.mtlGroups[j]->VBO[lj*3+1].tex[0], Models3D[i]->object.mtlGroups[j]->VBO[lj*3+1].tex[1]);
                }
                glVertex3f(Models3D[i]->object.mtlGroups[j]->VBO[lj*3+1].location[0], Models3D[i]->object.mtlGroups[j]->VBO[lj*3+1].location[1], Models3D[i]->object.mtlGroups[j]->VBO[lj*3+1].location[2]);


                glColor3f(Models3D[i]->object.mtlGroups[j]->VBO[lj*3+2].colour[0],Models3D[i]->object.mtlGroups[j]->VBO[lj*3+2].colour[1],Models3D[i]->object.mtlGroups[j]->VBO[lj*3+2].colour[2]);
                if(tOn){
                glTexCoord2f (Models3D[i]->object.mtlGroups[j]->VBO[lj*3+2].tex[0], Models3D[i]->object.mtlGroups[j]->VBO[lj*3+2].tex[1]);
                }
                glVertex3f(Models3D[i]->object.mtlGroups[j]->VBO[lj*3+2].location[0], Models3D[i]->object.mtlGroups[j]->VBO[lj*3+2].location[1], Models3D[i]->object.mtlGroups[j]->VBO[lj*3+2].location[2]);

                glEnd();


            }
            glDisable(GL_TEXTURE_2D);
            */

            //####
            glBindBuffer(GL_ARRAY_BUFFER, Models3D[i]->object.mtlGroups[j]->vboID);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Models3D[i]->object.mtlGroups[j]->indexvboID);


            /*
            //this could also be used BUT if glDrawElements uses the indices (m_pgroupVerticeIndex), we will need to give the array with all the 
            //vertices to glVertexPointer. That array would be m_pVertice
            //glVertexPointer(3, GL_FLOAT, 5, Models3D[i]->object.mtlGroups[j]->buffer);
            */


            glEnableClientState(GL_COLOR_ARRAY);
            glEnableClientState(GL_NORMAL_ARRAY);
            glEnableClientState(GL_VERTEX_ARRAY);


            //Get the material that belongs to this mtlGroup
            int mtlIndex = Models3D[i]->object.FindMaterial(Models3D[i]->object.mtlGroups[j]->mtlName);


            //check if there was a texture for this material
            if(Models3D[i]->object.materials[mtlIndex]->texturePresent){

                glEnable(GL_TEXTURE_2D);
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
                glBindTexture(GL_TEXTURE_2D, Models3D[i]->object.materials[mtlIndex]->textureIDDiffuse);

                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
                glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(12));
                //glTexCoordPointer(2, GL_FLOAT, 5, Models3D[i]->object.mtlGroups[j]->buffer);
                //glTexCoordPointer(2, GL_FLOAT, 0, Models3D[i]->object.m_pTexture);

            }


            // Resetup our pointers.  This doesn't reinitialise any data, only how we walk through it
            glNormalPointer(GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(20));
            glColorPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(32));
            glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));



            glDrawElements(GL_TRIANGLES, Models3D[i]->object.mtlGroups[j]->m_vecgroupVerticeIndex.size()*3, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));

            //glDrawElements(GL_TRIANGLES, Models3D[i]->object.mtlGroups[j]->m_vecgroupVerticeIndex.size()*3, GL_UNSIGNED_INT,  Models3D[i]->object.mtlGroups[j]->m_pgroupVerticeIndex);


            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_NORMAL_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);

            glDisable(GL_TEXTURE_2D);

        }


    }


}

我的缓冲区包含顶点(顶点结构数组):

struct Vertex {

    GLfloat location[3];
    GLfloat tex[2];
    GLfloat normal[3];
    GLfloat colour[3];
    GLubyte padding[20];        //apparently to get 64 bytes -> improved performance


};

以下是我为每种材料初始化/生成缓冲区的方法:

//This function was implemented based on the tutorial shown at
//http://sdickinson.com/wordpress/?p=122

void CObjLoader::GenerateVBO(){


    for(int mj=0;mj<mtlGroups.size();mj++){

        glGenBuffers(1, &mtlGroups[mj]->vboID);
        //printf("bufferID: %d", mtlGroups[mj]->vboID);

        glBindBuffer(GL_ARRAY_BUFFER, mtlGroups[mj]->vboID); // Bind the buffer (vertex array data)

        // Allocate space.  We could pass the mesh in here (where the NULL is), but it's actually faster to do it as a 
        // seperate step.  We also define it as GL_STATIC_DRAW which means we set the data once, and never 
        // update it.  This is not a strict rule code wise, but gives hints to the driver as to where to store the data
        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * mtlGroups[mj]->m_vecgroupVerticeIndex.size()*3, NULL, GL_STATIC_DRAW);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * mtlGroups[mj]->m_vecgroupVerticeIndex.size()*3, mtlGroups[mj]->VBO); // Actually upload the data

        // Set the pointers to our data.  Except for the normal value (which always has a size of 3), we must pass 
        // the size of the individual component.  ie. A vertex has 3 points (x, y, z), texture coordinates have 2 (u, v) etc.
        // Basically the arguments are (ignore the first one for the normal pointer), Size (many components to 
        // read), Type (what data type is it), Stride (how far to move forward - in bytes - per vertex) and Offset 
        // (where in the buffer to start reading the data - in bytes)

        // Make sure you put glVertexPointer at the end as there is a lot of work that goes on behind the scenes
        // with it, and if it's set at the start, it has to do all that work for each gl*Pointer call, rather than once at
        // the end.
        glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(12));
        glNormalPointer(GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(20));
        glColorPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(32));
        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));

        // When we get here, all the vertex data is effectively on the card

        // Our Index Buffer, same as above, the variable needs to be accessible wherever we draw
        glGenBuffers(1, &mtlGroups[mj]->indexvboID); // Generate buffer
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mtlGroups[mj]->indexvboID); // Bind the element array buffer
        // Upload the index array, this can be done the same way as above (with NULL as the data, then a 
        // glBufferSubData call, but doing it all at once for convenience)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, mtlGroups[mj]->m_vecgroupVerticeIndex.size()*3*sizeof(GLubyte), mtlGroups[mj]->index, GL_STATIC_DRAW);

    }


}

为简单起见,我的索引数组如下所示:0,1,2,3,4,5,...。这意味着我的缓冲区包含一些顶点两次。因此 VBO 和索引具有相同的长度。

也许我在初始化时搞砸了?

4

1 回答 1

1

所以错误如下(我将复制我之前解释解决方案的评论):

好的,我发现了错误。显然,我使用 GLubyte 作为索引,就我而言,我有超过 255 个顶点。更改为 GLuint 已解决该问题。但是,我的纹理仍未正确绘制到对象上。对象保持灰色。但颜色似乎有效。

.obj 加载器现在产生了更好的结果,并且可以使用更简单的模型。我会做一些进一步的测试,如果有问题,我会回来的。

于 2012-11-14T17:14:03.413 回答