如何防止远距离过度的 SSAO

How to prevent excessive SSAO at a distance

我几乎按照 John Chapman 的教程 here 使用 SSAO,事实上,使用 Sascha Willems Vulkan 示例。 一个区别是片段位置直接保存到 G-Buffer 以及线性深度(因此有 x、y、z 和 w 坐标,w 是线性深度,在 G-Buffer 着色器中计算。深度是这样计算的:

float linearDepth(float depth)
{   
    return (2.0f * ubo.nearPlane * ubo.farPlane) / (ubo.farPlane + ubo.nearPlane - depth * (ubo.farPlane - ubo.nearPlane)); 
}

我的场景通常由一个大而平坦的地板组成,中间有一个模型。总的来说,我的意思是比远剪辑距离大很多。

在高深度值(即在我的示例中的 horizon 处),SSAO 在真正应该 none 的地方产生遮挡 - 除了完全平坦的表面外什么都没有。 除了遮挡之外,还有一些条带。

关于如何防止这些遮挡发生的任何想法?

我在写问题的时候找到了这个解决方案,只因为我的地板是平的才有效。

我在每个内核样本位置查找法线值,并与当前法线进行比较,丢弃点积接近 1 的法线值。这意味着平面不能自遮挡。

非常欢迎任何关于为什么我不应该这样做的评论,或更好的选择! 它适用于我目前的情况,但如果我碰巧在地板上有非平面几何形状,我会寻找不同的解决方案。

vec3 normal = normalize(texture(samplerNormal, newUV).rgb * 2.0 - 1.0);
<snip>
for(int i = 0; i < SSAO_KERNEL_SIZE; i++)
    {
        <snip>
        float sampleDepth = -texture(samplerPositionDepth, offset.xy).w; 
        vec3 sampleNormal = normalize(texture(samplerNormal, offset.xy).rgb * 2.0 - 1.0);   
        if(dot(sampleNormal, normal) > 0.99)
            continue;