Reputation: 43
I have some confusion using VAO (vertex array object) for multiple objects (around 200 objects, 15 of them visible at a time, each having its own vertex and index buffer). Below is my rendering function
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.50f, 0.50f, 0.50f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[super drawLines];
for(int i=0; i< self.numberofBars; i++) //numberofBars
{
// Render the object
[self.barShaderProg use];
iVBarNode *temp = [theBars objectAtIndex:i];
_modelViewProjectionMatrix = GLKMatrix4Multiply(ProjectionView, modelMatrix);
_modelViewProjectionMatrix = GLKMatrix4Multiply(_modelViewProjectionMatrix, temp.modelMatrix);
GLKMatrix4 modeltotalMatrix = GLKMatrix4Multiply(modelMatrix, temp.modelMatrix);
GLKMatrix4 modelViewMatrix = GLKMatrix4Multiply(ViewMatrix, modeltotalMatrix);
_normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0,_normalMatrix.m);//
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEW_MATRIX], 1, 0, modelViewMatrix.m);
glUniform4f(uniforms[COLOR_VECTOR], temp.barColor.r, temp.barColor.g, temp.barColor.b, temp.barColor.a);
//bind corresponding buffer before drawing
glBindBuffer(GL_ARRAY_BUFFER, [temp getVertexID]);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(12));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, [temp getIndexID]);
glDrawElements(GL_TRIANGLES, [temp.bar getIndicesSize], GL_UNSIGNED_SHORT, (void*)0);
}
if(self.translation>0)
{
self.paused = NO;
}
else{
self.paused = YES;
}
}
This works perfectly fine. After analysing my code in the OpenGLES Analyser it showed to use VAO to benefit from them as the glVertexAttribPointer calls were reduntant (same for all). But I just cannot figure out if its possible to use them with different vertex buffer objects. Most of the examples, I found on the internet, use them with just one VBO or two VBOs where the second VBO defines a different attribute rather than the same attribute which is my case.I tried binding every vertex buffer index i generate for my object with a single VAO but it did not work as below
-(void) configureVertexArrayObject
{
// Create and bind the vertex array object.
glGenVertexArraysOES(1,&vertexArrayObject);
glBindVertexArrayOES(vertexArrayObject);
for(int i=0;i<self.numberofBars;i++)
{
iVBarNode *myNode = [theBars objectAtIndex:i];
glBindBuffer(GL_ARRAY_BUFFER, [myNode getVertexID]);
// Configure the attributes in the VAO
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(12));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, [myNode getIndexID]);
}
// Bind back to the default state.
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArrayOES(0);
}
here is how I render
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.50f, 0.50f, 0.50f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[super drawLines];
glBindVertexArrayOES(vertexArrayObject);
for(int i=0; i< self.numberofBars; i++) //numberofBars
{
// Render the object
[self.barShaderProg use];
iVBarNode *temp = [theBars objectAtIndex:i];
_modelViewProjectionMatrix = GLKMatrix4Multiply(ProjectionView, modelMatrix);
_modelViewProjectionMatrix = GLKMatrix4Multiply(_modelViewProjectionMatrix, temp.modelMatrix);
GLKMatrix4 modeltotalMatrix = GLKMatrix4Multiply(modelMatrix, temp.modelMatrix);
GLKMatrix4 modelViewMatrix = GLKMatrix4Multiply(ViewMatrix, modeltotalMatrix);
_normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0,_normalMatrix.m);//
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEW_MATRIX], 1, 0, modelViewMatrix.m);
glUniform4f(uniforms[COLOR_VECTOR], temp.barColor.r, temp.barColor.g, temp.barColor.b, temp.barColor.a);
//all buffer associated with VAO now
glDrawElements(GL_TRIANGLES, [temp.bar getIndicesSize], GL_UNSIGNED_SHORT, (void*)0);
}
glBindVertexArrayOES(0);
if(self.translation>0)
{
self.paused = NO;
}
else{
self.paused = YES;
}
}
In my second attempt, I tried specifying just the layout to the VAO, using glVertexAttribPointer() for vertices and normals (and not specifying the VBO and IBO ids), and render as I was doing without VAO (first render code above), but now I was not specifying the vertex layout using glVertexAttribPointer() as I already mention it to the VAO (in fact this was the whole point of using a VAO). Both of these approaches gave me equal sized objects making me think that somehow VAO is duplicating geometry for all of my objects. My all objects have the same geometry but different height . Now one option I have is to have a single vertex and index buffer object and I can scale along height and position the objects based on what I need. Still I would like to know what actually does a VAO hold and what it does not and if there is a way I can make it work.
Upvotes: 2
Views: 5577
Reputation: 473174
After analysing my code in the OpenGLES Analyser it showed to use VAO to benefit from them as the glVertexAttribPointer calls were reduntant (same for all).
Unless your glBindBuffer
call is binding the same buffer each time, I find this reasoning dubious.
You'd get more out of it by packing all of your objects into the same buffer, and thus doing the bind+glVertexAttribPointer calls once when you draw. Since all your objects have the same vertex format, there doesn't seem to be a reason why you can't just do that. You'll have to adjust your vertex indices to pick the right locations in the now larger buffer, but that's not too difficult.
Upvotes: 3