2012-11-13 66 views
4

所以我需要編輯這個問題。正如其中一條評論所述,我更改爲使用緩衝區的渲染方法。但是,幾何不能正確繪製。如果我使用相同的緩衝區並手動繪製頂點,它看起來很好(儘管沒有紋理,但有些東西與它混淆了)。我也嘗試構建一個只有頂點信息的緩衝區,但這根本沒有幫助。VBO:繪圖不正確。手動繪製作品

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和索引因此具有相同的長度。

也許我搞砸了初始化?

+0

使用頂點緩衝區! : -/ –

+0

真的不能幫助我理解glTexCoordPointer,它與glDrawElements一起使用.... – GreenJack

+0

這是正確的,但如果您使用最先進的技術,則更容易幫助您。 –

回答

1

因此錯誤是下面(我只是複製我以前的註釋說明了解決方案):

好吧,我已經找到了錯誤。顯然,我使用GLubyte作爲索引,在我的情況下,我有超過255個頂點。更改爲GLuint已解決該問題。但是,我的紋理仍未正確繪製到對象上。對象保持灰色。但顏色似乎工作。

.obj加載程序現在可以產生更好的結果,並且可以使用更簡單的模型。我會做一些進一步的測試,如果遇到麻煩,我會回來的。