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.
Related
I'm creating a VBO, populating it with data, then that data is being rendered using the following code:
// Buffer data
glGenBuffers(1, &VBOID);
glBindBuffer(VBOID, GL_ARRAY_BUFFER); // Shouldn't these be the other way around?
glBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, buffer);
// Draw arrays
glBindBuffer(VBOID, GL_ARRAY_BUFFER);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, bufferSize);
glDisableClientState(GL_VERTEX_ARRAY);
However, the openGL reference (https://www.opengl.org/sdk/docs/man/html/glBindBuffer.xhtml) says that the glBindBuffer function takes the target TYPE of buffer, then the buffer ID, not the other way around. When I put them in that way around, nothing draws to the screen, however when they're the 'wrong' way around, it seems to work just fine.
To clarify:
// Should be this
glBindBuffer(GL_ARRAY_BUFFER, VBOID);
// Only this works
glBindBuffer(VBOID, GL_ARRAY_BUFFER);
I feel like this is one of those really dumb issues, but I just can't see where the problem is. Could anyone shed some light on the situation?
Thanks.
It should definitely be written like this:
glBindBuffer(GL_ARRAY_BUFFER, VBOID);
I can't explain why reversing those arguments results in successful drawing. However, there's a few oddities you have in your code that you need to revise:
glVertexPointer(3, GL_FLOAT, 0, buffer);
This is immediate mode code. I don't think it's been deprecated, but the correct way to write this is
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, nullptr);
On top of that, you have two references to setting client state—glEnableClientState(GL_VERTEX_ARRAY); and glDisableClientState(GL_VERTEX_ARRAY);—These are also part of immediate mode, and should be removed.
Finally, the whole thing should be wrapped up inside a Vertex Array Object, like so:
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &VBOID);
glBindBuffer(GL_ARRAY_BUFFER, VBOID);
glBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, nullptr);
glEnableVertexAttribArray(0);
// Draw arrays
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, num_of_vertices); //num_of_vertices is usually the number of floats in the buffer divided by the number of dimensions of the vertex, or 3 in this case, since each vertex is a vec3 object.
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 wanted to implement a simple VBO to see if it was worth switching from display lists for static objects in my scene. So far, I don't think Im doing it anytime soon. So heres my problem: I can render vertices fine, but as soon as I throw in texture coordinates, it crashes. So I do a bit of experimenting and its because I'm binding a texture to the thing. I have NEVER heard of this as being a problem. Literally the exact same code, using display lists works. 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);
and rendering:
glUseProgram(shader);
glBindTexture(GL_TEXTURE_2D, texture);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBOT);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
I really have no idea why this is happening, Doing a texture without a shader crashes it, binding a shader without a texture crashes it. Any help or advice?
In a core opengl profile, you need to use VAOs in order to work with calls such as glDrawArrays and glDrawElements. A VAO (vertex array object) is a list of binding points for VBOs that encapsulates information such as data format and number of components for each VBO that is bound to it. In code it looks something like this.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3, &QuadVertextData, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glGenBuffers(1, &vbot);
glBindBuffer(GL_ARRAY_BUFFER, vbot);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2, &QuadTextureData, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindVertexArray(0);
The 0 and 1 (the first argument to glVertexAttribPointer) specifies the generic vertex attribute index in your shader. The 2 and 3 (the second argument) specify the number of components. Your input should be defined like this in the shader in order to work with this VAO:
layout(location=0) in vec3 position;
layout(location=1) in vec2 textureCoordinates;
Before drawing anything, you just have to use the shader program, bind your texture and bind the VAO:
glUseProgram(shader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(vao);
glDrawArrays(GL_QUADS, 0, 4);
Don't forget to set the texture location of the sampler2D uniform in the shader.
If you want to learn more about switching to the OpenGL core profile, I recommand the tutorials from http://www.opengl-tutorial.org/
I am looking for a way to dynamically edit the data that displays for a vertex buffer object. I have tried glBufferSubData, glMapBuffer, glBufferData, and some others, however had no luck. I have found that the time consuming method is glBindBuffer. I think I am using VBOs right, but I am not completely sure. Heres some sample code of my problem:
verticesId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, verticesId);
glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
normalsId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, normalsId);
glBufferData(GL_ARRAY_BUFFER, normalsBuffer, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
texturesId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, texturesId);
glBufferData(GL_ARRAY_BUFFER, texturesBuffer, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
the verticesBuffer and other variables are the FloatBuffers that have the data in them. Next, I render them this way:
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, verticesId);
glVertexPointer(vertexSize, GL_FLOAT, 0, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, texturesId);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawArrays(GL_QUADS, 0, amountOfVertices);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
Here is how I edit the VBOs:
int position = 0;
///////////////////////////////////////////////////////////////////
glBindBuffer(GL_ARRAY_BUFFER, verticesId);
mapBuffer = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY, null);
verticesBuffer = mapBuffer.order(ByteOrder.nativeOrder()).asFloatBuffer();
verticesBuffer.position(position);
// ... edit some values in the 'vertices' float array ...
verticesBuffer.put(vertices);
verticesBuffer.rewind();
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Is there any way to speed up the glBindBuffer method, or am I doing this wrong? And also, how should I edit the data for the most efficiency.
You can speed up the drawing part by using Vertex Array Objects.
About the uploading part, your code is fine; what you can do is "double buffering": keep a copy of the data, process it using another thread (multiple processor system are frequent nowadays), and then upload with glBufferSubData.
Another option is the use of SIMD assembly, but this depends on your application.
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 ?