OpenGL VAO VBO 着色器混乱

Ter*_*ris 4 c++ opengl glsl vbo vao

我正在编写一个渲染器,现在正在选择处理 vao/vbo/着色器管理的最终方法。在网上,我发现关于实际推荐内容的信息非常矛盾。目前想法如下:

-一个VBO连续存储所有网格。

-每个“着色器映射”创建一个 VAO 以将特定指针映射存储到 VBO 中。(“着色器映射”,在具有相同输入的不同着色器中保持一致)

然后通过“着色器映射”对实体进行排序,并使用主 VBO 中的偏移量进行渲染,从而最大限度地减少着色器和 VAO 开关。就像是:

for(shaders by mapping)
    bindVAO(); //set pointers
    for(shader)
        for(entity using shader)
            entity.setUniforms();
            drawArrays(entity.offset, entity.size);
Run Code Online (Sandbox Code Playgroud)

由于这将包括大量的重构,我想问这个解决方案是否是最佳的。我还想知道是否可以在单个 VBO 中拥有多种交错格式。

Jer*_*rem 5

将 VAO 与不同的着色器重复使用是一种很好的做法。

然而,与切换着色器相比,切换 VBO 和 VAO通常非常便宜。这意味着在您的情况下,瓶颈可能是切换着色器。

出于同样的原因,将所有网格物体放在同一个 VBO 中可能有点过分(但只要您不需要更新它,它就不会造成伤害)。

此外,根据您要渲染的内容,按深度/混合状态或按深度(通常从前到后)对绘制调用进行排序可能是比按着色器进行排序更好的解决方案。但这需要仔细衡量。(有关排序的更多信息请参见此处)。

编辑:为了回答你的第二个问题,也许可以将不同类型的顶点放在同一个VBO中,尽管我从未尝试过。这很棘手,因为您需要小心顶点对齐。glDrawArrays(mode, first, count)例如,在调用时,您需要计算first该值,使其first * sizeof(YourCurrentVertexType)等于您将数据放入 VBO 中的偏移量。无论如何,这样做可能不是一个好主意。有些司机可能不喜欢它,就像我上面所说的那样,它可能不会产生明显的变化。