OpenGL 早期深度测试不起作用

OpenGL early depth test not working

这是我的片段着色器:

#version 420 core
#extension GL_ARB_explicit_uniform_location : enable
#extension GL_ARB_shader_storage_buffer_object : require
layout(early_fragment_tests) in;
layout(binding = 4, offset = 0) uniform atomic_uint num_fragments;
// ...
void main(void)
{
    atomicCounterIncrement(num_fragments);
    frag_color = vec4(1.0, 0.0, 0.0, 0.0);

    atomicAdd(...);
}

我的三角形完全覆盖了屏幕。预期的行为是 num_fragments 等于像素数 (640*480 = 307200),它适用于单层三角形。但是,当我在现有三角形后面添加一个三角形时,num_fragments 变为更高的值,就像正在为被遮挡的三角形执行片段着色器。

这是为什么?我认为 early_fragment_tests 指令会阻止这种行为。这不仅仅是一种优化,因为着色器中的原子存储对于未被遮挡的像素应该仅为 运行。

My triangles completely cover the screen. The expected behavior is for num_fragments to be equal to the number of pixels (640*480 = 307200), which it is for a single layer of triangles.

不,这不是预期的行为。

早期深度测试并不神奇。它们不以任何方式保证随机排列的三角形将具有零透支。它们只是强制片段测试在执行片段着色器之前发生。所有这一切都是为了确保测试通过或失败。因此,片段着色器只会对通过的片段执行。

Overdraw 与早期深度测试无关。透支是关于您正在渲染的 三角形 的顺序。如果你渲染它们从前到后排序,那么你会得到零透支。如果你渲染它们从后到前排序,那么你会得到最大可能的透支。

无论片段测试是否发生在片段着色器之前,都会发生这种情况。

This isn't just an optimization, because there are atomic stores in the shader that should only be run for un-occluded pixels.

做到这一点的唯一方法是进行仅深度预传递。您必须将场景渲染到深度缓冲区(没有片段着色器)。然后,当您真正渲染场景时,唯一通过深度测试的片段将是可见的片段。