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

时间:2016-06-04 06:44:07

标签: 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)));

然后我将这个法线应用到我的SSAO实现上,除了边缘之外,它主要取得了很好的效果:

enter image description here

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

enter image description here

1 个答案:

答案 0 :(得分:2)

除了生成法线gbuffer之外,没有办法完全摆脱所有伪影。但是有一个重建法线的解决方案可以给你带来更好的结果:

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

经典正常重建: classic normal reconstruction

改进(交叉模式)正常重建: improved (cross pattern) normal reconstruction

使用SSAO进行经典正常重建: classic normal reconstruction with SSAO

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

另请注意,使用dFdx()dFdy()可能总会导致更多的工件,而不仅仅是对深度纹理进行三次采样(因为dFdx()无法保证返回的值或dFdy()将是准确的),这在您的示例中显然就是这种情况。