VBO: drawing wrong. Hand drawing work

so i will need to edit this question. As indicated in one of the comments, I changed the rendering method to use buffers. However, the geometry is not drawn correctly. If I use the same buffer and draw the vertices manually, it looks good (no texture, although something went bad). I also tried to build a buffer with only vertex information, but that didn't help.

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); } } } 

My buffer contains vertices (an array of Vertex structures):

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

And this is how I initialize / create buffers for each of the materials:

 //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 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 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); } } 

For simplicity, my index array looks like this: 0, 1, 2, 3, 4, 5, .... This means that my buffer contains some of the vertices twice. Thus, VBO and index have the same length.

Perhaps I am confusing something with initialization?

+4
source share
1 answer

So, the error was as follows (I just copy my previous comments explaining the solution):

Ok, I found a mistake. Apparently, I used GLubyte for indexes, and in my case I have over 255 vertices. Changing to GLuint solved the problem. However, my texture is still not drawn correctly on the object. The subject remains gray. But colors seem to work.

The .obj loader now gives better results and is in order with simpler models. I will do a few more tests, and in case of problems I will return.

+1
source

Source: https://habr.com/ru/post/1445767/


All Articles