实现仅深度传递的最少步骤

Minimum steps to implement depth-only pass

我有一个现有的 OpenGL ES 3.1 应用程序,它使用颜色和 depth/stencil 附件将场景渲染到 FBO。它使用常用的绘图方法(glBindBuffer、glDrawArrays、glBlend*、glStencil* 等)。我现在的任务是创建一个仅深度通道,用与主通道相同的值填充深度附件。

我的问题是:实现此目标并避免 GPU 执行多余工作(不必要的着色器调用等)所需的最少步骤数是多少?停用颜色附件是否足够,还是我还必须设置空着色器、禁用混合等?

我假设你在主通道运行之前需要这个,否则你只会保持主通道深度。

预检

  1. 创建专门的缓冲区,其中只包含计算位置所需的网格数据(从所有非位置数据中解交错)。
  2. 创建专门的顶点着色器(仅计算输出位置)。
  3. Link 具有最简单有效片段着色器的程序。

渲染

  1. 使用专门的缓冲区和着色器渲染仅深度通道,屏蔽所有颜色写入。
  2. 使用完整的缓冲区和着色器渲染主通道。

选项

在上面的步骤 (2) 中,加载仅深度通道深度结果作为主要通道的起始深度可能会有所帮助。这将为您提供更好的 early-zs 测试准确性,但代价是深度值的回读。大多数移动 GPU 都移除了隐藏表面,因此这并不总是净收益 - 这取决于您的内容、目标 GPU 以及您的前后绘制顺序有多好。

您可能希望为主绘制使用专门的缓冲区(位置数据在一个缓冲区中交错,非位置数据在一秒钟内交错),因为如果图元是,许多 GPU 会优化非位置计算剔除。

专用缓冲区和优化的着色器也可用于阴影贴图和其他此类仅深度技术。