延迟着色、法线贴图和指向远离光线的自阴影表面

Posted

技术标签:

【中文标题】延迟着色、法线贴图和指向远离光线的自阴影表面【英文标题】:Deferred shading, normal mapping and self-shadowing surfaces pointing away from light 【发布时间】:2011-05-31 01:45:31 【问题描述】:

我遇到了法线贴图和指向远离光线的表面的问题。这些表面根本不应该被照亮,因为它们不面向光线。但是,如果碎片的法线恰好弯曲得足够大,这些表面上的相当多的碎片可能会被点亮。由此引起的伪影清晰可见,例如在一侧直接远离光线的盒子上:该侧的几乎所有碎片都是黑色的(因为它们应该是)但仍然可以看到几个白色碎片(抱歉,屏幕截图目前不可用,但如果你已经做了正常映射之前你应该知道我在说什么)。

我找到了一种在前向渲染器中解决此问题的简单方法:只需将光强度乘以 (4*lightDirection.Z)。推理是你应该将光强度乘以光向量和表面的法线向量的(钳位)点积(如果面朝外,点积将为负,光强度将被钳位为0),并且由于我们在切线空间中进行计算,因此该法线始终为 (0,0,1),因此点积就是 lightDirection.z。乘数 4 只是为了确保光强度不会下降(如果脸没有指向另一边)。

现在我尝试为延迟渲染器实现相同的功能,但很快注意到这种简单的方法不起作用,因为我在世界空间中进行计算。要进行此计算,我需要该片段的真实法线和该片段所在表面的法线。当然,我可以将这些信息存储到纹理中,但是为了完成这个技巧,还要多花 3 个浮点数(如果我要打包它们,则需要 2 个)似乎相当昂贵。

有什么解决方法吗?

谢谢。

【问题讨论】:

【参考方案1】:

在延迟着色中,您将法线存储在视图空间中,所以我认为您只需先将光线方向从世界空间转换到视图空间,然后您可以进行相同的计算。

【讨论】:

啊,我为什么没有想到将它们存储在视图空间中。谢谢!

以上是关于延迟着色、法线贴图和指向远离光线的自阴影表面的主要内容,如果未能解决你的问题,请参考以下文章

切线空间法线贴图 - 着色器完整性检查

为啥我的法线不会在顶点之间插值,从而产生平坦的阴影效果?

Unity对项目性能优化的实现

在片段着色器中使用 textureCube 访问环境贴图失败

使用具有世界空间法线的切线空间法线贴图

Opengl-法线贴图(用来细化表面的表现表现的凹凸)