对于多个对象(大约 200 个对象,其中 15 个一次可见,每个对象都有自己的顶点和索引缓冲区),我对使用 VAO(顶点数组对象)有些困惑。下面是我的渲染功能
- (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;
}
}
这工作得很好。在 OpenGLES Analyzer 中分析了我的代码后,它显示使用 VAO 可以从中受益,因为 glVertexAttribPointer 调用是多余的(对所有人都一样)。但我只是不知道是否可以将它们与不同的顶点缓冲区对象一起使用。我在互联网上找到的大多数示例仅将它们与一个 VBO 或两个 VBO 一起使用,其中第二个 VBO 定义了不同的属性,而不是我的情况相同的属性。我尝试绑定我为我的对象生成的每个顶点缓冲区索引使用单个 VAO,但它没有按如下方式工作
-(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);
}
这是我的渲染方式
- (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;
}
}
在我的第二次尝试中,我尝试仅指定 VAO 的布局,对顶点和法线使用 glVertexAttribPointer()(而不是指定 VBO 和 IBO id),并像我在没有 VAO 时所做的那样进行渲染(上面的第一个渲染代码),但是现在我没有使用 glVertexAttribPointer() 指定顶点布局,因为我已经向 VAO 提到了它(实际上这是使用 VAO 的全部意义)。这两种方法都给了我相同大小的对象让我觉得 VAO 正在为我的所有对象复制几何图形。我的所有对象都具有相同的几何形状但高度不同。现在我有一个选择是拥有一个顶点和索引缓冲区对象,我可以沿高度缩放并根据需要定位对象。我仍然想知道 VAO 到底有什么,没有什么,以及是否有办法让它发挥作用。