切换 glDepthFunc 后重用顶点着色器输出

Reusing vertex shader outputs after switching glDepthFunc

我试图在将 glDepthFunc 设置为 GL_LESSGL_GREATER 后渲染相同的场景(由大量实例化网格组成),以获得第一个和最后一个整体场景的生命值。着色器程序 运行 在这两种情况下是相同的,两次执行之间的唯一区别是 glDepthFunc 的设置,即:

while (true) {
    glDepthFunc(GL_LESS);
    runShader(buffer1);
    glDepthFunc(GL_GREATER);
    runShader(buffer2);
}

着色器仅由顶点着色器和片段着色器组成。两次着色器程序执行的片段着色器输出肯定不同,但两次执行的顶点着色器输出应该相同。有没有办法让 OpenGL 在第二次着色器程序执行中重用第一个顶点着色器的输出,这样只有片段着色器必须 运行 第二次?

简答:这不可能。

详细回答:不可能直接重用顶点着色器结果。有一些方法可以确保特定的顶点着色器不必 运行 两次,但除非顶点着色器非常重,否则我不希望这些方法中的任何一种比仅渲染场景更快两次。

选项 1:转换反馈
可以使用变换反馈并将顶点着色器的结果写入额外的 VBO。然后两个渲染阶段都可以使用变换缓冲区作为渲染的输入。这种方法在渲染路径中仍然需要一个 pass-through 顶点着色器,并且很可能会导致更差的性能,除非第一个顶点着色器太慢以至于它补偿了变换反馈的额外开销 + 一个额外的渲染调用。

选项 2:原子操作
代替使用深度测试进行常规渲染,可以在片段着色器中使用 atomicMinatomicMax 来计算每个片段的 min/max 深度。该方法需要两个 uint 图像纹理(一个用于最小值,一个用于最大值)并且您必须自己将浮点深度值转换为定点表示 (uint)。同样,在片段着色器中丢失早期深度测试和使用原子操作的额外开销将比只渲染整个场景两次更慢。