2

对于多个对象(大约 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 到底有什么,没有什么,以及是否有办法让它发挥作用。

4

1 回答 1

3

在 OpenGLES 分析器中分析了我的代码后,它显示使用 VAO 可以从中受益,因为 glVertexAttribPointer 调用是多余的(对所有人都一样)。

除非您的glBindBuffer调用每次都绑定相同的缓冲区,否则我认为这种推理是可疑的。

通过将所有对象打包到同一个缓冲区中,您可以从中获得更多收益,从而在绘制时执行一次 bind+glVertexAttribPointer 调用。由于您的所有对象都具有相同的顶点格式,因此您似乎没有理由不能这样做。您必须调整顶点索引以在现在更大的缓冲区中选择正确的位置,但这并不太难。

于 2012-11-14T23:57:16.030 回答