我有大量的物体(至少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渲染类似的对象?
答案 0 :(得分:2)
将着色器绑定和解除绑定。将着色器绑定一次,绘制使用该着色器的所有内容,然后解除绑定。按着色器对对象进行分组。如果你有一个更复杂的材料系统,你会想要同时绘制具有相同材料属性的所有东西(例如纹理和照明组件等制服)。当你进入它时,保持顶点属性绑定,只有在你完成时才关闭它们。所有这些都可以最大限度地减少您执行的OpenGL调用次数。
如果可以,请将几何体打包成尺寸最佳的VBO(应根据GPU而有所不同)。我怀疑你可以将所有形状按顺序打包到一个缓冲区中,然后使用偏移量来选择要绘制的形状。这将为您节省VBO开关。
如果您要多次抽取相同的内容,请考虑instanced rendering
如果您要多次抽取很多东西,请将它们分成类似的批次。
如果您正在尝试制作粒子系统,请考虑制作GPU particle system。粒子属性(如位置和速度)存储在纹理中,然后片段着色器会在每次绘制调用时更新这些属性。更新后,将一长串索引((u,v)坐标)作为顶点数据传入,用于索引粒子纹理以检索数据。然后在几何着色器中将每个粒子转换为三角形或四边形,最后渲染到屏幕上。
答案 1 :(得分:1)
通常有任何类型的优化问题,首先要确定的是瓶颈所在。如果瓶颈是着色器的复杂性,那么在CPU端进行优化是没有用的。但是,当你提到10000个过度调用的调用时,我只是假设你受CPU限制。
因此,首要任务是减少绘制调用次数。 目前,您似乎通过10000次绘制调用实现了10000个粒子。
通常,当我进行粒子系统时,我的所有粒子都呈现为面向屏幕的四边形(广告牌),并使用单个纹理图集应用纹理,我的目标是在一次绘制调用中渲染所有10000个粒子。
您描述了一个稍微复杂的场景;三角形,正方形和圆形都可以在一个索引三角形列表中一起批处理,尽管您可能应该考虑将圆形实现为纹理四边形而不是许多三角形。
球体有点不同,因为它是一个相对复杂的高多边形对象。如果它真的不能被模拟为广告牌,那么也许你最好去实验技术来同时绘制你的所有领域。