Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何渲染大量相似对象?_C++_Opengl - Fatal编程技术网

C++ 如何渲染大量相似对象?

C++ 如何渲染大量相似对象?,c++,opengl,C++,Opengl,我有大量的物体(至少10000个粒子),比如三角形、正方形、圆形或球体。实际上,现在我有一个对象,我渲染了很多次。看起来是这样的: for (int i=0; i<totalParticleCount; i++) { drawObject->pos = hState[i].pos; drawObject->draw(vp); } 我发现我的渲染过程太慢了。如何提高渲染性能?如何有效地使用opengl渲染类似对象?通常,对于任何类型的优化问题,首先要确定的是瓶颈

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

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

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

通常,对于任何类型的优化问题,首先要确定的是瓶颈在哪里。如果瓶颈是着色器的复杂性,那么CPU端的优化是无用的。然而,正如您提到的10000个draw调用,这是相当过分的,我将假设您是CPU受限的

所以首要任务是减少抽签电话的数量。 目前,您似乎通过10000次绘制调用实现了10000个粒子

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

你描述了一个稍微复杂一点的场景;三角形、正方形和圆圈都可以在一个单索引的三角形列表中分批排列,尽管也许你应该考虑把你的圆圈作为纹理四边形来代替三角形。 球体有点不同,因为它是一个相对复杂的高多边形对象。如果它真的不能被模拟成一个广告牌,那么你最好研究一下实例化技术,一次画出所有的球体

  • 分解着色器绑定和解除绑定。绑定着色器一次,绘制使用该着色器的所有内容,然后解除绑定。按着色器对对象进行分组。如果您有一个更复杂的材质系统,您将希望同时绘制具有相同材质属性的所有对象(例如,纹理和照明组件等制服)。进行此操作时,请保持顶点属性处于绑定状态,并仅在完成后将其禁用。所有这些都可以最大限度地减少OpenGL调用的次数

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

  • 如果你要画同样的东西很多次,考虑

  • 如果你要画很多东西很多次,把它们分成类似类型的批次

  • 如果你想制作一个粒子系统,那就考虑制作一个粒子系统。粒子属性(如位置和速度)存储在纹理中,然后片段着色器在每次绘制调用时更新这些属性一次。更新后,一长串索引((u,v)坐标)作为顶点数据传入,用于索引粒子纹理以检索数据。然后,每个粒子在几何体着色器中变成三角形或四边形,最后渲染到屏幕上


  • 粒子系统听起来不错,但我的模型更复杂。我的模型是流体,我使用CUDA来更新粒子的状态。我可以将所有形状打包到一个VBO中。在这种情况下,我可以为每个形状设置模型矩阵吗?或者VBO的每个顶点都与系统中心有相对位置?选项1和3-4看起来像我要找的选项。我的着色器非常简单。例如,这是顶点着色器:
    void main()。我认为批处理可以帮助我解决问题。
    
    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);
    }