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

Posted

技术标签:

【中文标题】如何在 OpenGL 中的单个绘制调用上绘制多个顶点数组?【英文标题】:How can I draw multiple vertex array on a single draw call in OpenGL? 【发布时间】:2015-09-15 04:13:35 【问题描述】:

我想模拟一堆球的运动。这些球使用 GL_TRIANGLE_FAN 渲染为 12 个顶点。在我的设计中,每个球对象都维护着一个由自己的顶点属性组成的数组。然而,每次我调用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 参数,我可以从balls 数组中“选择”x、y 并跳过其他成员。我想知道当每个对象都维护一个顶点属性数组时,我怎么能做同样的事情?或者我应该提取所有顶点属性并将它们组合成一个 VBO?但是需要额外的代码来维护,增加了耦合度。

【问题讨论】:

【参考方案1】:

如果所有对象(完全或大部分)相同,则应查看“instanced”渲染或绘图(即glDrawArraysInstanced 等)

如果您的对象大多不同且大多是动态的,但具有相同的渲染状态(纹理、着色器等)并且您可以使用 OpenGL 4+,您应该使用“多重绘制间接”工具(即glMultiDrawArraysIndirect等)请注意,在考虑所有先前的扩展等时,版本要求有点棘手。

如果您的对象不相同而是静态的,您应该将它们组合成一个(或几个)对象并绘制它们。这将需要更多的代码,并且会导致灵活性降低,并且您必须弄清楚它是否值得获得性能优势。

如果以上都不适合(即您的对象都是不同的、非常动态的,并且您不能使用现代 OpenGL),那么您就没有任何简单的方法来提高您的绘图效率。您可能需要使用 ubershaders(实际上,很少有着色器可以做所有事情)、纹理数组(或无绑定纹理)和其他技巧。

【讨论】:

以上是关于如何在 OpenGL 中的单个绘制调用上绘制多个顶点数组?的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 VAO 和 EBO (openGL) 绘制多个对象

如何在OpenGL中绘制单个像素?

在opengl es android中的随机位置绘制多个立方体

绘制三角形带时,啥控制 OpenGL 的行为?

2.绘制简单的几何图形

如何将多个图像绘制到单个画布上?