如何渲染大量类似的对象?

时间:2015-10-16 04:57:44

标签: c++ opengl

我有大量的物体(至少10 000个粒子),如三角形,正方形,圆形或球形。实际上现在我有一个我渲染很多次的对象。它看起来像这样:

for (int i=0; i<totalParticleCount; i++) {
    drawObject->pos = hState[i].pos;
    drawObject->draw(vp);
}

我的Circle对象的绘制函数如下所示,其中变量“vp”是视图矩阵上投影矩阵的乘积:

void Circle::draw(const glm::mat4 &vp) {
    glUseProgram(programId);
    glUniformMatrix4fv(matrixId, 1, GL_FALSE, &(vp * getModelMatrix(pos, scale))[0][0]);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glDrawArrays(GL_TRIANGLE_FAN, 0, vertexNumber);
    glDisableVertexAttribArray(0);
}

我发现我的渲染过程太慢了。如何提高渲染性能?如何有效地使用opengl渲染类似的对象?

2 个答案:

答案 0 :(得分:2)

  1. 将着色器绑定和解除绑定。将着色器绑定一次,绘制使用该着色器的所有内容,然后解除绑定。按着色器对对象进行分组。如果你有一个更复杂的材料系统,你会想要同时绘制具有相同材料属性的所有东西(例如纹理和照明组件等制服)。当你进入它时,保持顶点属性绑定,只有在你完成时才关闭它们。所有这些都可以最大限度地减少您执行的OpenGL调用次数。

  2. 如果可以,请将几何体打包成尺寸最佳的VBO(应根据GPU而有所不同)。我怀疑你可以将所有形状按顺序打包到一个缓冲区中,然后使用偏移量来选择要绘制的形状。这将为您节省VBO开关。

  3. 如果您要多次抽取相同的内容,请考虑instanced rendering

  4. 如果您要多次抽取很多东西,请将它们分成类似的批次。

  5. 如果您正在尝试制作粒子系统,请考虑制作GPU particle system。粒子属性(如位置和速度)存储在纹理中,然后片段着色器会在每次绘制调用时更新这些属性。更新后,将一长串索引((u,v)坐标)作为顶点数据传入,用于索引粒子纹理以检索数据。然后在几何着色器中将每个粒子转换为三角形或四边形,最后渲染到屏幕上。

答案 1 :(得分:1)

通常有任何类型的优化问题,首先要确定的是瓶颈所在。如果瓶颈是着色器的复杂性,那么在CPU端进行优化是没有用的。但是,当你提到10000个过度调用的调用时,我只是假设你受CPU限制。

因此,首要任务是减少绘制调用次数。 目前,您似乎通过10000次绘制调用实现了10000个粒子。

通常,当我进行粒子系统时,我的所有粒子都呈现为面向屏幕的四边形(广告牌),并使用单个纹理图集应用纹理,我的目标是在一次绘制调用中渲染所有10000个粒子。

您描述了一个稍微复杂的场景;三角形,正方形和圆形都可以在一个索引三角形列表中一起批处理,尽管您可能应该考虑将圆形实现为纹理四边形而不是许多三角形。

球体有点不同,因为它是一个相对复杂的高多边形对象。如果它真的不能被模拟为广告牌,那么也许你最好去实验技术来同时绘制你的所有领域。