I've been following some opengl tutorials in C++ (moving from using java, so I know openGL alright, but memory management, pointers, etc I'm a little slow on) from http://www.opengl-tutorial.org, and I'm currently having problems with an error when exiting my application.
I am trying to add a normals vertex attrib array. It seems to work fine during runtime, but when I exit the application, I get this:
"Run-Time Check Failure #2 - Stack around the variable 'normalbuffer' was corrupted."
I of course did some googling, and found that this error was normally related to arrays and index out of bounds errors, but normalbuffer is just a GLuint. As far as I can tell, the code for implementing my normalbuffer is identical to that implementing my vertex positions and my uv texture map.
Here is my initialization code:
// Create Vertex Buffer
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
// Create UV Buffer
GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);
// Create Normals Buffer
GLuint normalbuffer;
glGenBuffers(2, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
And then my looped code (run every frame):
//...
//Load the vertex positions array
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, //Specify which attribute index we are using
3, //Size of the attribute
GL_FLOAT, //Type of attribute
GL_FALSE, //Normalized?
0, //Stride
(void*)0 //Array Buffer Offset
);
//Load the UV positions array
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1, //Specify which attribute index we are using
2, //Size of the attribute
GL_FLOAT, //Type of attribute
GL_FALSE, //Normalized?
0, //Stride
(void*)0 //Array Buffer Offset
);
//Load the normal vectors array
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
2, //Specify which attribute index we are using
3, //Size of the attribute
GL_FLOAT, //Type of attribute
GL_FALSE, //Normalized?
0, //Stride
(void*)0 //Array Buffer Offset
);
//glDrawArrays() happens here
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
//...
This error doesn't seem to happen at all during run time, only when I close the program by hitting the escape key (so I'm not killing the process in VS).
The 1st parameter of glGenBuffers specifies the number of buffer object names to be generated.
You generate 2 objects, but pass the address of the single variable normalbuffer to glGenBuffers.
2 objects are generated and the names of the objects are written to the memory addressed by &normalbuffer and (&normalbuffer) + 1. This causes the stack corruption.
Change the number of objects to be generated:
GLuint normalbuffer;
glGenBuffers(2, &normalbuffer);
glGenBuffers(1, &normalbuffer);
Related
I'm trying to draw a textured cube in OpengL.
At first, I initialize VBO and VAO in the class constructor as follows.
Block::Block(...)
{
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
//glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindVertexArray(VAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 *
sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 *
sizeof(float)));
glEnableVertexAttribArray(2);
}
and in the method called renderBlock(), I render the cube like this
void Block::renderBlock()
{
setMatrix();
shader.use();
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindVertexArray(VAO);
glActiveTexture(GL_TEXTURE0);
shader.setInt("tex", 0);
shader.use();
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
and if I call the block.renderBlock(), the program will crash at glDrawArrays(GL_TRIANGLES, 0, 6);. The error message says that 0xC0000005: Access conflict occurred at read position 0x0000000000000000.. But if I uncomment the //glBindBuffer(GL_ARRAY_BUFFER, VBO); in constructer, the program will run successfully. It's very confusing to me. Why should I bind the VBO before I edit the VAO. Is there any connection between them?Any advice would be greatly appreciated.
You must bind the VBO before calling glVertexAttribPointer. When glVertexAttribPointer is called, the buffer currently bound to the GL_ARRAY_BUFFER target is associated with the specified attribute index and the ID of the buffer object is stored in the state vector of the currently bound VAO. Therefore, the VAO and the VBO must be bound before calling glVertexAttribPointer.
I create my buffers with the following code:
//generate buffers
glGenVertexArrays(1, &VAO);
//glGenBuffers(1, &EBO);
glGenBuffers(1, &VBO_vertices);
glGenBuffers(1, &VBO_colors);
glGenBuffers(1, &VBO_normals);
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
glBindVertexArray(VAO);
// Copy our vertices array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, VBO_vertices);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*vertices.size(), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vTable.size() * sizeof(int), &vTable[0], GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); //size = 3 (X,Y,Z)
glEnableVertexAttribArray(0);
//Buffer for color
glBindBuffer(GL_ARRAY_BUFFER, VBO_colors);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*vertices.size(), &v_color[0], GL_STATIC_DRAW);
// Color attribute
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); //size = 3 (R,G,B)
glEnableVertexAttribArray(1);
//Buffer for normals
glBindBuffer(GL_ARRAY_BUFFER, VBO_normals);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*vertices.size(), &v_normals[0], GL_STATIC_DRAW);
//normal attribute
glVertexAttribPointer((GLuint)2, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); //size = 3 (R,G,B)
glEnableVertexAttribArray(2);
// Unbind the VAO
glBindVertexArray(0);
My data are :
vector<vec3> vertices, v_normals,v_color;
vector<int> vTable;
I have vertices, normals and colors per vertex and an index table with the index vertices of each triangle.
When I try to render this, nothing appears on the window.
glBindVertexArray(VAO); //Bind VAO
glDrawElements(GL_TRIANGLES, vTable.size(), GL_UNSIGNED_INT, &vTable[0]);
glBindVertexArray(0); //Unbind VAO
If I used this:
glDrawArrays(GL_TRIANGLES,0,vTable.size());
It draws something but an incomplete object, like in the link image.
image
Anybody knows what happens? Thanks in advance
Your glDrawElements call is wrong, the last parameter should be a byte offset into your GL_ELEMENT_ARRAY_BUFFER that holds the indices, not pointer to system memory.
glDrawElements(GL_TRIANGLES, vTable.size(), GL_UNSIGNED_INT, 0);
I am working on a simple 3D Engine. I currently have a working setup with multiple VAO's which I can switch between during the render loop, but they all are not using index buffers.
I'm now trying to add a new VAO composed of 4 VBO's: vert position, color, normal and indices.
Everything compiles and runs but the drawing calls to the second VAO (with indexed vertices) do not render. I'm sure there is a problem with my setup somewhere, so I've added this code which includes all the VAO and VBO generations, calls, and uses. Does anything in this code seem wrong, and is this the correct way to set it all up?
VAO1 has 3 buffers: position, color, normals
VAO2 has 3 buffers: position, color, normals and vertex indices
//Initalize vaos and vbos
GLuint vao1, vbo1[3];
GLuint vao2, vbo2[4];
//Generate Vertex arrays:
glGenVertexArrays(1, &vao1);
glGenVertexArrays(1, &vao2);
//Generate Buffers:
glGenBuffers(3, vbo1);
glGenBuffers(4, vbo2);
//Initalize Bufferdata vectors:
vector<GLfloat> VertPosBuffer1Vector;
vector<GLfloat> VertNormalBuffer1Vector;
vector<GLfloat> VertColorBuffer1Vector;
vector<GLfloat> VertPosBuffer2Vector;
vector<GLfloat> VertNormalBuffer2Vector;
vector<GLfloat> VertColorBuffer2Vector;
vector<GLuint> VertIndexBuffer2Vector;
//Fill Buffers:
//(not included but all vectors are filled with data)
//VAO 1
glBindVertexArray(vao1);
//Vertex position buffer:
glBindBuffer(GL_ARRAY_BUFFER, vbo1[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VertPosBuffer1Vector.size(), &VertPosBuffer1Vector[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
//Vertex color buffer:
glBindBuffer(GL_ARRAY_BUFFER, vbo1[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VertColorBuffer1Vector.size(), &VertColorBuffer1Vector[0], GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(1);
//Vertex normal buffer:
glBindBuffer(GL_ARRAY_BUFFER, vbo1[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VertNormalBuffer1Vector.size(), &VertNormalBuffer1Vector[0], GL_STATIC_DRAW);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(2);
//VAO 2
glBindVertexArray(vao2);
//Vertex position buffer:
glBindBuffer(GL_ARRAY_BUFFER, vbo2[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VertPosBuffer2Vector.size(), &VertPosBuffer2Vector[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
//Vertex color buffer:
glBindBuffer(GL_ARRAY_BUFFER, vbo2[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VertColorBuffer2Vector.size(), &VertColorBuffer2Vector[0], GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(1);
//Vertex normal buffer:
glBindBuffer(GL_ARRAY_BUFFER, vbo2[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VertNormalBuffer2Vector.size(), &VertNormalBuffer2Vector[0], GL_STATIC_DRAW);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(2);
//Vertex index buffer:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo2[3]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*VertIndexBuffer2Vector.size(), &VertIndexBuffer2Vector[0], GL_STATIC_DRAW);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(3);
//unbind vao
glBindVertexArray(0);
//bind first vao
glBindVertexArray(vao1);
and
//RENDERLOOP
//render objects from vao1 using:
glDrawArrays(GL_TRIANGLES, start, size);
//switch vao
glBindVertexArray(0);
glBindVertexArray(vao2);
//render objects from vao2 using:
glDrawElements(
GL_TRIANGLES,
start,
GL_UNSIGNED_INT,
(void*)0
);
I have checked that the data in my buffers are correct.
Is it correct that the shader doesn't take in any information of indices? The shader will be the same as if I didn't use an index buffer?
Thank you
The indices are not a vertex attribute. So what you need to do is remove these two lines:
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(3);
I also noticed that you are using the variable "start" as the count argument for glDrawElements. I don't know the values of start and size, but I assume you should use "size" as the second argument in glDrawElements.
I know the glVertexAttribPointer will use the values from the VBO that was bound when it was called. But can you buffer twice onto the same object? Would it replace what was in? Or can you clear a buffer? I don't know if this approach is correct:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); // shared VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(posLoc);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat),(GLvoid*)0);
glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);
glEnableVertexAttribArray(colLoc);
glVertexAttribPointer(colLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat),(GLvoid*)0);
glBindBuffer(GL_ARRAY_VERTEX, 0);
glBindVertexArray(0);
Or if I should be using 2 VBOs for buffering the data. What would happen if you call the glBufferData function twice to the same bound vertex array object? This is the other way I would think of for doing this:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO1); // VBO for vertices
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(posLoc);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat),(GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, VBO2); // VBO for colours
glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);
glEnableVertexAttribArray(colLoc);
glVertexAttribPointer(colLoc, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat),(GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
The top example won't work as the second glBufferData call will overwrite all of the buffer space in the second one. To properly do that, you have to use the stride and pointer arguments properly, so that the data is interleaved. It's easier (and cleaner imo) to just have multiple VBO's, each storing a separate set of data.
So I have some code that creates a buffer and puts some vertices in it:
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(0);
I also bind it to a shader attribute:
glBindAttribLocation(programID, 0, "pos");
And, finally, draw it:
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glDrawArrays(GL_TRIANGLES, 0, 3);
Of course, there is other code, but all of this stuff runs fine (displays a red triangle on the screen)
However, the instant I try to factor this stuff out in a struct, nothing will display (here is one of the methods):
void loadVerts(GLfloat verts[], int indices)
{
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glVertexAttribPointer(indice, indices, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(indice);
indice++;
buffers.push_back(vertexbuffer);
}
I've quadruple checked this code, and I've also traced it to make sure it would match the code above whenever its called. My draw call is almost the same as my original:
void draw()
{
glBindBuffer(GL_ARRAY_BUFFER, buffers.at(0));
glDrawArrays(GL_TRIANGLES, 0, 3);
}
I've also tried making this a class, and adding/changing many parts of the code. buffers and indice are just some vars to keep track of buffers and attribute indexes. buffers is an std::vector<GLuint> FWIW.
The main problem is here:
void loadVerts(GLfloat verts[], int indices)
{
...
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
The type of the verts argument is a pointer to GLfloat. Your function signature is equivalent to:
void loadVerts(GLfloat* verts, int indices)
So sizeof(verts), which is used as the second argument to glBufferData(), is 4 on a 32-bit architecture, 8 on a 64-bit architecture.
You will need to pass the size as an additional argument to this function, and use that value as the second argument to glBufferData().
These statements also look somewhat confusing:
glVertexAttribPointer(indice, indices, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(indice);
I can't tell if there's a real problem, but you have two variables with very similar names that are used very differently. indice needs to be the location of the attribute in your vertex shader, while indices needs to be the number of components in the attribute.