OpenGL渲染函数的顺序

3

我正在使用OpenGL来渲染体素游戏中的块。每个块都有自己的顶点缓冲区,现有的渲染函数(简化版)如下:

foreach (Chunk c in chunks)
{
    glBindBuffer(BufferID.Array, c.handle);
    if (c.dirty)
    {
        glBufferData(BufferID.Array, ... , BufferUsage.StaticDraw);
        c.dirty = false;
    }

    // For position, normal, colour and UV
    glEnableVertexAttribArray(...);
    glVertexAttribPointer(...);

    glUseProgram(shader.Handle);
    glDrawArrays(DrawMode.TriangleStrip, 0, c.vertexBuffer.Length);
}

上述代码可以正常运行,但是在glEnableVertexAttribArray、glVertexAttribPointer和glUseProgram函数中CPU使用率较高。

我可以在循环开始之前调用这些函数吗?还是必须在每次调用glBindBuffer之后调用它们?


这些函数背后的操作是否需要针对每个“块”不同?如果不需要,那么它们为什么首先要在循环中呢?如果需要,那么问题就没有意义了。这些不是随意组合的随机事物;每个函数都有其功能。因此,如果您知道这些函数的作用,您就已经得到了答案。 - Nicol Bolas
地图是不断变化的,并且被分成块,这样我就不必在每次添加/删除/更改颜色时重新计算整个地图。这些函数背后的操作(glEnableVertexAttribArray、glVertexAttribPointer和glUseProgram)对于每个块都是相同的。 - user5932360
1个回答

2
在引入顶点数组对象(VAOs)之前,每当您想要更改内存布局和/或指针时,确实需要重新绑定。然后引入了顶点数组对象,有一段时间人们感到沮丧,因为当时的驱动程序性能仍然有很大的提升空间(截至撰写本文时,这已经是约10年前的事情了 - 时间过得真快)。从那以后,驱动程序得到了很大的改进。
基本上,VAO存储哪些缓冲区绑定到了哪个属性,以及这些绑定的内存布局。 https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object

那么我可以将glEnableVertexAttribArray、glVertexAttribPointer和glUseProgram函数调用移到循环之前吗? - user5932360
1
@MitchellRobinson 是的,每个块都有自己的VAO,它是一组VBO,因此您只需在地图或其他初始化期间对每个块进行一次配置。在渲染中,您只需绑定每个地图块的单个VAO。另外,请查看这个我的简单GLSL体素光线追踪器,它使用3D纹理来代替VAO/VBO几何体,这更适合于体素世界。 - Spektre

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