什么是隐藏表面问题以及为什么 z 缓冲区精度甚至很重要?

What is hidden surface problem and why does z buffer precision even matter?

作为 OpenGL(和一般计算机图形学)的初学者,我对以下问题很好奇:

  1. 我知道什么是Z缓冲区,它是一个深度缓冲区,存储的值范围从0到1。但是为什么它的精度很重要?

  2. 什么是隐面问题?

  3. 使用线性Z缓冲区有什么问题?

  4. 为什么我们关心 Z 缓冲区精度?

  1. Z 缓冲区精度

    在 GL 中开发了深度缓冲区,因此精度在视觉上不会随着距离而降低...这意味着如果您渲染跨越 znearzfar 平面的无限平面并使用存储的深度作为颜色,您会看到平面呈现为具有相同视觉宽度的平行条。像这样:

    这在整个场景中提供了或多或少相同的视觉细节。但是,当您开始查看非线性的几何精度和数值统计时,您会发现 <0,1> 范围的大部分非常接近 znear.

    一旦我们的计算机能够处理更大、更详细的场景,这种行为就开始成为一个问题,因为我们突然想在更远的地方看到细节,那里的深度值增量通常大于整个渲染对象本身。 ..

    为了解决这个问题,我们可以使用 (对于动态深度范围大或物体非常大的场景)。

    让我们有 16 位深度缓冲区,这意味着 2^16 个值没有符号,因为我们有符号而不是 2^15 = 32768 可能的值。

    现在对于线性深度,这意味着深度精度(最小 increment/change/delta)是

    dz = (zfar-znear)/2^(bits-1)
    

    例如让znear=0.1zfar=1000然后:

    dz = (1000-0.1)/32768 = 0.03
    

    整个场景。现在,当我们回到非线性深度时,dzznear 附近小得多,但在 zfar 附近大得多,将其用作细节标准是无用的。相反,最好遵守这个:

    zfar/znear < 2^(bits-1)
    
  2. 隐藏表面移除

    它是 Painters 算法的变通方法,在该算法中,离相机较远的对象会被距离较近的对象覆盖。图形中的画家算法称为Z-sorting,它需要按顺序渲染东西。深度缓冲是一种解决方法,您可以在其中存储已渲染内容的深度值,并且仅在您离相机更近时才渲染。这消除了按顺序渲染的需要,同时仍然获得相同的结果。

    但是,如果部门精度太低,则渲染无法可靠地分辨出什么是壁橱,什么是看不到的:

    左边精度好,右边差。如您所见,相同的几何图形在错误的深度精度下呈现不同。

  3. 线性深度问题

    线性深度缓冲区不是 GL 原生的,因此您需要稍微解决 GL 实现。幸运的是,有了 GLSL,它现在非常简单且便宜,既没有精度损失也没有性能影响。有关详细信息,请参阅上面的 link。然而,具有线性深度意味着我们在整个场景中获得了相同的几何精度。因此,对于相同的细节,在接近 znear 个对象的情况下,我们需要更多的深度缓冲区位。这就是为什么线性深度缓冲区更适合具有高动态深度范围的场景,而非线性深度缓冲区表现不佳。因此,大物体的场景从 znearzfar,如地形、大 space 船只、城镇等......

  4. 为什么要关心深度精度?

    避免深度拟合/深度撕裂、错误的几何相交、错误的高级效果等渲染伪像...

    您需要记住,深度缓冲区位宽非常有限。通常的值是 16/24/32,但仅适用于年龄 16/24,大多数硬件都可用。仅在最近几年,我们可以拥有 32 个,在某些卡上甚至可以拥有 64 个,但 IIRC 不再是本机深度缓冲区,需要额外的代码来启用它...

除了线性深度缓冲之外,还有其他方法可以实现场景的高动态深度范围参见: