I'm using lwjgl 3 as a Java wrapper to OpenGL, and I'm trying to figure out how to render things with Vertex Array Objects. I have not been able to find any examples online that show how to use a VAO that has both shader attributes and uses the element array buffer.
According to this vao tutorial, I need to do something like this:
// Create a new Vertex Array Object in memory and select it (bind)
// A VAO can have up to 16 attributes (VBO's) assigned to it by default
vaoId = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoId);
// Create a new Vertex Buffer Object in memory and select it (bind)
// A VBO is a collection of Vectors which in this case resemble the location of each vertex.
vboId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW);
// Put the VBO in the attributes list at index 0
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
// Deselect (bind to 0) the VBO
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// Deselect (bind to 0) the VAO
GL30.glBindVertexArray(0);
However, I don't understand how to adapt this tutorial to my project, because I am using glVertexAttribPointer
to deal with fields in the shader. These fields have id's that are assigned to them when the shader is compiled. In the above example, they seem to be able to use the default field 0
. However, I checked, for me posAttrib
is in field 0
.
How should I associate a VBO with my VAO?
private int createVao(int shaderProgramId, FloatBuffer vertices, IntBuffer order) {
int floatSize = 4;
int stride = 7 * floatSize;
int vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
int vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
int eboId = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, order, GL_STATIC_DRAW);
int posAttrib = shaderProgramService.getAttribute(shaderProgramId, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, false, stride, 0);
int colAttrib = shaderProgramService.getAttribute(shaderProgramId, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, false, stride, 2 * floatSize);
int texAttrib = shaderProgramService.getAttribute(shaderProgramId, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, false, stride, 5 * floatSize);
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); <==== Removed
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
return vaoId;
}
EDIT: Thanks @RetoKoradi, getting rid of the glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
call improved things. The scene flashed onscreen, but I got a seg-fault on the second frame. After some debugging, the issue was with another object I was trying to render that was not yet using VAO's. I was making calls like this to render the object:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, texturedPoints.getEboId());
glBindBuffer(GL_ARRAY_BUFFER, texturedPoints.getVboId());
glBindTexture(GL_TEXTURE_2D, texturedPoints.getTextureId());
specifyVertexAttributes();
int count = texturedPoints.getCount();
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
Somehow that interfered with subsequent VAO rendering calls that looked like this:
glBindVertexArray(texturedPoints.getVaoId());
glBindTexture(GL_TEXTURE_2D, texturedPoints.getTextureId());
glDrawElements(GL_TRIANGLES, texturedPoints.getCount(), GL_UNSIGNED_INT, 0);
The glDrawElements
call would seg-fault the second time that the main loop went around and called it. After moving everything over to VAO's the problems have gone away.