我尝试理解 struct VkPipelineRasterizationStateCreateInfo 的每个成员,但其与深度偏差相关的成员让我感到困惑,尤其是深度偏差坡度因子。 我从 https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPipelineRasterizationStateCreateInfo.html 找到了有关它的描述,它说,
depthBiasSlopeFactor 是应用于片段斜率的标量因子 深度偏差计算
我对此声明有两个疑问。
首先,片段的斜率是多少?更准确地说,什么属性的斜率?碎片颜色?深度值?
其次,深度偏差计算是如何进行的?是不是像Clamp(original-深度+bias)这样的形式?
微软对D3D11有很好的解释;它应该或多或少与 Vulkan 处理它的方式相同。 https://learn.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias(GitHub版本)
像素的斜率是指该像素所在多边形的斜率。因此这不适用于点和线。
无符号标准化格式的确切方程是
Bias = (float) depthBiasConstantFactor * r + depthBiasSlopeFactor * MaxDepthSlope;
[W]这里 r 是转换为 float32 的深度缓冲区格式中大于 0 的最小可表示值。
MaxDepthSlope
大约是
max(abs(dZ / dX), abs(dz / dy))
D3D 11.3 规格。如果您不熟悉微积分,这基本上是选择 Z 相对于 X 的斜率绝对值的最大值,以及 Z 相对于 Y 的斜率绝对值的最大值。导数可让您查看变化函数的斜率,对于始终是平面的三角形而言,就是它的斜率。
如果您使用浮点深度缓冲区格式,那么方程式会更复杂一些
Bias = (float) depthBiasConstantFactor * pow(exp(max_z_in_primitive) - r, 2)
+ depthBiasSlopeFactor * MaxDepthSlope;
[W]这里r是浮点表示中尾数位数(不包括隐藏位);例如,23 代表 float32。
深度偏置适用于阴影贴图,其中阴影将具有与其所在表面相同的深度值。在平坦的表面上,这应该工作得相当好,但如果您只是简单地偏置深度值,则更复杂的表面可能会产生一些伪影,因此添加与斜率成比例的量可以减轻这些伪影。
基于阴影缓冲区的阴影的伪影之一是阴影痤疮,或者由于着色器中的深度计算与阴影缓冲区中同一表面的深度之间的微小差异而导致的表面阴影本身。缓解这种情况的一种方法是在渲染阴影缓冲区时使用 [depthBiasConstantFactor] 和 [depthBiasSlopeFactor]。这个想法是在渲染阴影缓冲区时将表面推出足够远,以便比较结果(阴影缓冲区 z 和着色器 z 之间)在整个表面上保持一致,并避免局部自阴影。
但是,当以极锐角查看多边形导致偏差方程生成非常大的 z 值时,使用 [深度偏差常数因子] 和 [深度偏差坡度因子] 可能会引入新的渲染问题。这实际上将多边形推离阴影贴图中的原始表面非常远。帮助缓解这一特定问题的一种方法是使用 [depthBiasClamp],它提供计算的 z 偏差大小的上限(正或负)。