I don't know what's wrong here, everything is working fine except normals.
When I use vertex array, model looks perfect but when I switch to VBO, model looks worse because of vertex normals. I spent a lot of time to fix it but do not know what's wrong. VBO generation seems perfect. but still do not know.
any idea?
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
void InitVBO(){
glGenBuffers(1, &vboNormID);
glBindBuffer(GL_ARRAY_BUFFER, vboNormID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLpoint)*nb_Vertices, NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLpoint)*nb_Vertices, VertNormals);
glNormalPointer(GL_FLOAT, sizeof(GLpoint), BUFFER_OFFSET(12));
glGenBuffers(1, &vboVertID);
glBindBuffer(GL_ARRAY_BUFFER, vboVertID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLpoint)*nb_Vertices, NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLpoint)*nb_Vertices, p_VERTICES);
glVertexPointer(3, GL_FLOAT, sizeof(GLpoint), BUFFER_OFFSET(0));
glGenBuffers(1, &indexVBOID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLFace)*nb_Faces, NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLFace)*nb_Faces, p_indices);
//glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLFace)*nb_Faces, p_indices, GL_DYNAMIC_DRAW);}
Rendering code is followed. VBO + Vertex Array
Vertex array is working perfect. I can see the perfect shape of model with vertex normals, but with VBO there is some issue with vertex normals. I think I am doing something wrong with BUFFER_OFFSET(12).
void RenderTringularModel(GLvoid){
if(VertNormals && !MESH_SMOOTH)
{
glBindBuffer(GL_ARRAY_BUFFER, vboNormID);
glBindBuffer(GL_ARRAY_BUFFER, vboVertID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);
glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(GLpoint), BUFFER_OFFSET(12));
glVertexPointer(3, GL_FLOAT, sizeof(GLpoint), BUFFER_OFFSET(0));
glDrawElements(GL_TRIANGLES, nb_Faces*3, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glPopClientAttrib();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
else
{
//glShadeModel (GL_FLAT);
glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(GLpoint), p_VERTICES);
glNormalPointer(GL_FLOAT, sizeof(GLpoint), VertNormals);
glDrawElements(GL_TRIANGLES, 3*nb_Faces, GL_UNSIGNED_INT, p_indices);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glPopClientAttrib();
}
}
UPDATE 1:
I think you are talking about InitVBO.. I was wrong at that point. How about this...But it is also not working.. actually the issue it.. in many ways i tried to bind the vertex normals in InitVBO().. but result comes the same every time.
glGenBuffers(1, &vboVertID);
glBindBuffer(GL_ARRAY_BUFFER, vboVertID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLpoint)*nb_Vertices, NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLpoint)*nb_Vertices, p_VERTICES);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(GLpoint)*nb_Vertices, sizeof(GLpoint)*nb_Vertices, VertNormals);
glVertexPointer(3, GL_FLOAT, sizeof(GLpoint), BUFFER_OFFSET(0));
glNormalPointer(GL_FLOAT, sizeof(GLpoint), BUFFER_OFFSET(12));
Update 2:
Ok ... i don't bind the vertex normals (vboNormID). I am discarding it. is it ok now ? Now it should work.. Actually i have done everything in that way.. to bind the vertex normals with vboVertID and with vboNormID etc etc.. but not every single mathod is working.. give me any suggestion by analyzing this code.
void RenderTringularModel(GLvoid){
if(VertNormals && !MESH_SMOOTH)
{
glBindBuffer(GL_ARRAY_BUFFER, vboVertID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);
glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(GLpoint), BUFFER_OFFSET(12));
glVertexPointer(3, GL_FLOAT, sizeof(GLpoint), BUFFER_OFFSET(0));
glDrawElements(GL_TRIANGLES, nb_Faces*3, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
Update 3:
I don't know who told me to use BUFFER_OFFSET()... just crap.. I have fixed it now, now working fine without this stupid BUFFER_OFFSET()..
Now the fixed code it really simple as follows:
void InitVBO(){
glGenBuffers(1, &vboVertID);
glBindBuffer(GL_ARRAY_BUFFER, vboVertID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLpoint)*nb_Vertices, p_VERTICES, GL_DYNAMIC_DRAW);
glGenBuffers(1, &vboNormID);
glBindBuffer(GL_ARRAY_BUFFER, vboNormID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLpoint)*nb_Vertices, VertNormals, GL_DYNAMIC_DRAW);
glGenBuffers(1, &indexVBOID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLFace)*nb_Faces, p_indices, GL_DYNAMIC_DRAW);}
void RenderTringularModel(GLpoint *P, GLpoint *Vn, GLFace *T, int nbF){
glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vboVertID);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboNormID);
glNormalPointer(GL_FLOAT, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);
glDrawElements(GL_TRIANGLES, nb_Faces*3, GL_UNSIGNED_INT, 0);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopClientAttrib();}
Now guys kindly guide me how can I update these buffers in real-time. I mean to say I need to update the whole data in real-time, normals, vertices, triangles.
for example: after subdivision of triangles, i would need to update the triangles buffer with vertices and normals too.. and another thing is, during cutting simulation of model, i need to update the vertices position and normals, so i would need to update the buffer at that point too.. so tell what do i do for this kind of issue ? how can i make it up ? do i need to delete the buffers and regenerate again ? if yes then how ?
Related
I am trying to create two separate objects to be rendered at the same time, a cube and a sphere. The issue is once I add the code for the sphere, the cube
is missing some faces etc.
Here is my code:
glGenBuffers(1, &g_VBO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*g_numberOfVertices[0], g_pMeshVertices[0], GL_DYNAMIC_DRAW);
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 3 * g_numberOfFaces[0], g_pMeshIndices[0], GL_DYNAMIC_DRAW);
glGenVertexArrays(1, &g_VAO);
glBindVertexArray(g_VAO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));
glEnableVertexAttribArray(positionIndex);
glEnableVertexAttribArray(normalIndex);
/////////////////////////////////////////ORN///////////////////////////////////////////////
glGenBuffers(1, &ornVBO);
glBindBuffer(GL_ARRAY_BUFFER, ornVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*g_numberOfVertices[1], g_pMeshVertices[1], GL_DYNAMIC_DRAW);
glGenBuffers(1, &ornIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ornIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 3 * g_numberOfFaces[1], g_pMeshIndices[1], GL_DYNAMIC_DRAW);
glGenVertexArrays(1, &ornVAO);
glBindVertexArray(ornVAO);
glBindBuffer(GL_ARRAY_BUFFER, ornVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ornIBO);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));
glEnableVertexAttribArray(positionIndex);
glEnableVertexAttribArray(normalIndex);
So it renders the sphere fine, but then all the cubes have missing triangle faces. I think I have narrowed it down to being an issue with the IBO side but I can't quite figure it out.
Here is the image: https://puu.sh/vLBSm/1617b5d996.png
Next to and behind the sphere and the cube are other cubes ignore those, they have the same issue but are purposefully there. I just can't work out how to display both properly. and Im sure it has something to do with this:
glGenBuffers(1, &ornIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ornIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 3 * g_numberOfFaces[1], g_pMeshIndices[1], GL_DYNAMIC_DRAW);
glGenVertexArrays(1, &ornVAO);
In the ORN code, you are overwritting the index buffer binding of the first VAO.
At this point:
glGenBuffers(1, &ornIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ornIBO);
g_VAO is still active, so the index buffer binding is replaced by ornIBO. To solve that you should unbind g_VAO before starting the ORN code:
glBindVertexArray(g_VAO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));
glEnableVertexAttribArray(positionIndex);
glEnableVertexAttribArray(normalIndex);
//Unbind!!
glBindVertexArray(0);
UPDATE: Upon further investigation, it seems to be switching the program that causes the 2nd object to not be drawn. I don't know why. Both objects use essentially the same GLSL.
I have a hunch I'm not using buffers right. I have a cube and a prism defined. If I comment out the prism's draw call, the cube draws. otherwise only the prism draws. What am I missing here
Draw Code:
glUseProgram(cubeProgram);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[0]);
glVertexAttribPointer(cVPos, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(cVPos);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[1]);
glVertexAttribPointer(cNormID, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(cNormID);
glDrawArrays(GL_TRIANGLES, 0, 36);
glUseProgram(priProgram);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[2]);
glVertexAttribPointer(pVPos, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(pVPos);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[3]);
glVertexAttribPointer(pNormID, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(pNormID);
glDrawArrays(GL_TRIANGLES, 0, 64);
VBO Creation:
glGenBuffers(4, vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVerts), cubeVerts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeNorms), cubeNorms, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(priVerts), priVerts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[3]);
glBufferData(GL_ARRAY_BUFFER, sizeof(priNorms), priNorms, GL_STATIC_DRAW);
Let me know if there's more code needed.
So it was my GLSL causing the problem. I was calling a function to set variables for the shader and one of them seems to have unset. I recalled the function after drawing the first object and they both draw. Hooray!
Whenever I try to draw a mesh using glDrawElements, my program gets no errors, but it doesn't draw anything. I'm pretty sure that the issue is with glDrawElements since if I comment glDrawElements out and replace it with glDrawArrays, it works perfectly. So, my question is, can anyone help me figure out why this is happening?
Also glGetError returns no errors
#include "Mesh.h"
Mesh::Mesh(glm::vec2* vertices, glm::vec2* texCoords, GLushort* elements, int size)
{
m_size = size;
m_vertices = vertices;
m_elements = elements;
movementVector = glm::vec2(0.0f, 0.0f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, size * sizeof(float), vertices, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glGenBuffers(1, &tex_vbo);
glBindBuffer(GL_ARRAY_BUFFER, tex_vbo);
glBufferData(GL_ARRAY_BUFFER, size * sizeof(float), texCoords, GL_STATIC_DRAW);
// note: I assume that vertex positions are location 0
int dimensions = 2; // 2d data for texture coords
glVertexAttribPointer(1, dimensions, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray (1); // don't forget this!
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &vbo);
}
void Mesh::Draw()
{
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
//glDrawArrays(GL_TRIANGLES, 0, 8);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL);
glDisableVertexAttribArray(0);
}
Here's a link to the code handling drawing objects to the screen, also, I have tested my shaders, they are fully functional and unless drawing via glDrawElements requires changes to the shaders as well, then there is nothing that is causing this with them.
So I've implemented a really quick VBO just to see if its worth switching from display lists. I've ran into a bit of trouble though when I try to put in texture coordinates. It crashes with EXC_BAD_ACCESS with glDrawArrays. Im pretty sure its the way Im rendering the VBO's, specifically in the order that Im doing it, but I've tried just about everything and haven't been able to get it to work properly. Here is my code:
//create a vertex buffer object for the particles to use
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//create the data, this is really sloppy
float QuadVertextData[] = {0,0,0,1,0,0,1,1,0,0,1,0};
float QuadTextureData[] = {0,1,1,1,1,0,0,0};
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3, &QuadVertextData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//generate another buffer for the texcoords
glGenBuffers(1, &VBOT);
glBindBuffer(GL_ARRAY_BUFFER, VBOT);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2, &QuadTextureData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
The rendering code:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBOT);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
From what I've seen on the internet, Im not doing anything wrong.
I'm familiar with IBO, VBO and VAO, while passing vertices, uvs and normals in one buffer. Though there are cases, when it's a little bit difficult to combine them in one buffer.
Therefore I came up with this piece of code:
glGenBuffers(2, &iboID[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertInd.size() * sizeof(unsigned int), &vertInd[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, uvInd.size() * sizeof(unsigned int), &uvInd[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glGenBuffers(2, &vboID[0]);
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]);
glBufferData(GL_ARRAY_BUFFER, tempV.size() * sizeof(glm::vec3), &tempV[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vboID[1]);
glBufferData(GL_ARRAY_BUFFER, tempUV.size() * sizeof(glm::vec2), &tempUV[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenVertexArrays(1, &vaoID[0]);
glBindVertexArray(vaoID[0]);
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]);
glVertexAttribPointer(_shader->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(_shader->attrib("vert"));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID[0]);
outputError();
glBindBuffer(GL_ARRAY_BUFFER, vboID[1]);
glVertexAttribPointer(_shader->attrib("vertTexCoord"), 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(_shader->attrib("vertTexCoord"));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID[1]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
So my question is : Is this the right way of doing this? (because at the moment I see nothing drawn to the screen)
You are trying to specify different element arrays (in separate IBOs), each for a vertex attribute. This is not going to work. Defining separate VBOs for each attribute is fine, but the GL can only have one element array, indexing all the currently enabled attribute arrays at the same time.