如何在OpenGL中使用单个绘制调用绘制多个顶点数组?

3

我想模拟一堆球的运动。这些球被呈现为12个顶点,使用GL_TRIANGLE_FAN进行渲染。在我的设计中,每个球对象维护其自己的顶点属性数组。然而,每次调用glDrawElements时,它只会绘制一个Vertex Buffer Object。1000个球需要1000个绘制调用,效率不高。如果我绘制点而不是三角形扇形,则可以按以下方式绘制:

class Ball
{
public:
    GLfloat x, y;
    // ...
}

Ball balls[] = {Ball(100, 100), Ball(80, 120), ...};

void display()
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, sizeof(Ball), 0); // stride

    glDrawArrays(GL_POINTS, 0, vertex_num);
    //...
}

有了stride参数,我可以从球数组中“选择”x、y并跳过其他成员。我想知道当每个对象维护一个顶点属性数组时如何做到同样的事情?或者我应该提取所有顶点属性并将它们组合成单个VBO?但这需要额外的代码来维护它并增加耦合。

1个回答

4
如果所有的对象都(几乎)相同,你应该考虑使用“实例化渲染”或“实例化绘制”(例如glDrawArraysInstanced等)。
如果你的对象大多不同但又大多是动态的,并且具有相同的渲染状态(纹理、着色器等),并且你可以使用OpenGL 4+,那么你应该使用“多次间接绘制”的方法(例如glMultiDrawArraysIndirect等)。请注意,在考虑所有先前的扩展等因素时,版本要求可能有些棘手。
如果你的对象不同但是静态的,那么你应该将它们组合成一个或几个对象并绘制出来。这将需要更多的代码并导致较少的灵活性,你必须确定是否值得获得性能上的好处。
如果以上都不适用(例如:你的对象都不同,非常动态,并且不能使用现代OpenGL),那么你没有简单的方式来提高绘制效率。你可能需要使用ubershaders(实际上很少的shader,可以做到“万能”)、纹理数组(或无绑定纹理)和其他技巧。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接