如何在边缘没有伪影的情况下从深度重建法线?

Sky*_*yun 3 opengl graphics

最近我正在研究我的 SSAO 实现,对于我的引擎,我想添加对前向和延迟渲染器的支持,因此我选择使用仅深度方法并从深度图重建法线,这是代码:

//Restore view space position with non-linear depth
vec3 viewPos = getPosition(uv, depth, invProjMat);
//Restore view space normal
vec3 normal = normalize(cross(dFdx(viewPos), dFdy(viewPos)));
Run Code Online (Sandbox Code Playgroud)

然后我将这个法线应用到我的 SSAO 实现中,除了边缘之外,它主要取得了相当不错的结果:

在此处输入图片说明

我确定那是因为边缘的不连续法线,但我不知道如何修复它。那么在从深度重建法线时,有什么方法可以避免边缘上的伪影?谢谢。

在此处输入图片说明

Tar*_*ara 7

除了生成法线 gbuffer 之外,没有办法完全摆脱所有工件。但是有一种重建法线的解决方案可以为您提供更好的结果:

我在我的引擎中所做的是,我采取 5 个深度样本进行正常重建。它们的位置就像一个十字架。中心样本是您当前正在渲染的像素,您对该中心样本上方、左侧、右侧和下方的像素进行采样。然后对于正常重建,您只需取相对于中心样本最接近的 Y 样本(中心样本上方或下方的样本)和最接近的 X 样本(中心样本的左侧或右侧)。这在 99% 的情况下摆脱了那些正常的人工制品,但它引入了分支并需要更多的纹理样本。因此,它比仅仅做你已经在做的事情要慢得多。

经典正常重建: 经典正常重建

改进的(交叉模式)法线重建: 改进的(交叉模式)正常重建

使用 SSAO 进行经典法线重建: 使用 SSAO 进行经典正常重建

使用 SSAO 改进(交叉模式)正常重建: 使用 SSAO 改进(交叉模式)正常重建 (原谅我过时的 SSAO 截图)

另请注意,dFdx()dFdy()仅对深度纹理采样 3 次相比,使用和可能总是会导致更多的伪影(因为无法保证dFdx()或返回的值dFdy()是准确的),在您的示例中显然就是这种情况。