OpenGL VAO VBO 着色器混乱
OpenGL VAO VBO shaders confusion
我正在编写一个渲染器,正处于选择处理 vao/vbo/shader 管理的最终方法的时刻。在网络上,我发现关于实际推荐内容的信息相互矛盾。
目前思路如下:
-一个VBO连续存储所有网格。
-Per "shader mapping" 创建一个 VAO 来存储特定的指针映射到 VBO。 ("shader mapping",在具有相同输入的不同着色器中保持一致)
然后按 "shader mapping" 对实体进行排序并使用主 VBO 中的偏移进行渲染,从而最大限度地减少着色器和 VAO 开关。类似于:
for(shaders by mapping)
bindVAO(); //set pointers
for(shader)
for(entity using shader)
entity.setUniforms();
drawArrays(entity.offset, entity.size);
因为这将包括大量的重构,所以我想问一下这个解决方案是否是最优的。
我还想知道是否可以在单个 VBO 中使用多种交错格式。
重复使用具有不同着色器的 VAO 是一种很好的做法。
但是,与切换着色器相比,切换 VBO 和 VAO 通常 非常便宜。这意味着在您的情况下,瓶颈可能无论如何都会切换着色器。
出于同样的原因,将所有网格放在同一个 VBO 中可能有点矫枉过正(但只要您不需要更新它就不会造成伤害)。
此外,根据您正在渲染的内容,按深度/混合状态或按深度(通常从前到后)对绘制调用进行排序可能是比按着色器对它们进行排序更好的解决方案。但这需要仔细衡量。 (有关排序的更多信息 here)。
编辑:为了回答您的第二个问题,可以将不同类型的顶点放在同一个 VBO 中,尽管我从未尝试过。这很棘手,因为您需要注意顶点对齐。例如,当调用 glDrawArrays(mode, first, count)
时,您需要计算 first
以便 first * sizeof(YourCurrentVertexType)
等于您将数据放入 VBO 的偏移量。无论如何,这样做可能不是一个好主意。有些司机可能不喜欢它,就像我上面说的那样,它可能不会产生明显的差异。
我正在编写一个渲染器,正处于选择处理 vao/vbo/shader 管理的最终方法的时刻。在网络上,我发现关于实际推荐内容的信息相互矛盾。 目前思路如下:
-一个VBO连续存储所有网格。
-Per "shader mapping" 创建一个 VAO 来存储特定的指针映射到 VBO。 ("shader mapping",在具有相同输入的不同着色器中保持一致)
然后按 "shader mapping" 对实体进行排序并使用主 VBO 中的偏移进行渲染,从而最大限度地减少着色器和 VAO 开关。类似于:
for(shaders by mapping)
bindVAO(); //set pointers
for(shader)
for(entity using shader)
entity.setUniforms();
drawArrays(entity.offset, entity.size);
因为这将包括大量的重构,所以我想问一下这个解决方案是否是最优的。 我还想知道是否可以在单个 VBO 中使用多种交错格式。
重复使用具有不同着色器的 VAO 是一种很好的做法。
但是,与切换着色器相比,切换 VBO 和 VAO 通常 非常便宜。这意味着在您的情况下,瓶颈可能无论如何都会切换着色器。
出于同样的原因,将所有网格放在同一个 VBO 中可能有点矫枉过正(但只要您不需要更新它就不会造成伤害)。
此外,根据您正在渲染的内容,按深度/混合状态或按深度(通常从前到后)对绘制调用进行排序可能是比按着色器对它们进行排序更好的解决方案。但这需要仔细衡量。 (有关排序的更多信息 here)。
编辑:为了回答您的第二个问题,可以将不同类型的顶点放在同一个 VBO 中,尽管我从未尝试过。这很棘手,因为您需要注意顶点对齐。例如,当调用 glDrawArrays(mode, first, count)
时,您需要计算 first
以便 first * sizeof(YourCurrentVertexType)
等于您将数据放入 VBO 的偏移量。无论如何,这样做可能不是一个好主意。有些司机可能不喜欢它,就像我上面说的那样,它可能不会产生明显的差异。