延迟渲染中的阴影


12

我已经阅读了一些有关延迟渲染的材料,我想我对此有所了解。但是我不明白的是它如何实现阴影。据我所知,G缓冲区不涉及为每个光线创建一个阴影贴图,所以我对于光照通过如何知道每个像素是否被遮挡感到困惑。毕竟,从摄影机的角度可见的给定像素实际上可能从任何给定的光的角度都不可见,并且从摄影机的角度可能看不到遮挡的几何形状,因此在G缓冲区中没有任何内容。

如果开始渲染阴影贴图,则看起来与正向渲染几乎相同-为每个光源渲染场景中的所有几何图形以渲染阴影贴图。

那么延迟渲染如何完成与正向渲染等效的阴影?

Answers:


14

延迟阴影对阴影没有任何特殊作用。您仍然需要正常渲染阴影贴图,然后使用绑定为纹理的适当阴影贴图渲染每个光源。

它仍然比正向渲染更好,因为您无需在主视图中重新绘制场景即可应用照明。绘制阴影贴图通常比在主视图中绘制更多通道便宜得多,因为您无需进行任何像素着色,并且阴影贴图通常包含较少的场景(您可以剔除更多的东西)。

人们有时会为一盏灯(通常是主定向灯)做“延迟阴影”。这样做的主要原因是使用级联阴影贴图或对同一光源使用多个阴影贴图的另一种方法。您可以在G缓冲区中保留一个通道用于阴影遮罩(亮时为白色,暗处为阴影),并将所有级联的阴影贴图应用到此G缓冲区通道中。然后,灯光的着色器将读取阴影蒙版并将其乘以灯光颜色。这很好,因为它可以将阴影与阴影分离,但是您仍在绘制所有相同的阴影贴图。


1
如果您非常聪明,可以尝试在创建GBuffer的过程中使用几何体着色器来“内联”阴影贴图的创建(就像立方体贴图DX10示例所做的那样)。我不确定它是否已经完成,是否可能,或者最终是否会变慢-但这将使阴影贴图的创建更接近于延迟着色,或者使定义取决于您的宗教信仰。
乔纳森·迪金森

6

那么,什么是阴影贴图?阴影贴图是纹理的纹理,谁的纹理像素可以回答一个简单的问题:沿着纹理像素表示的方向,在与光的距离为多少时,光被遮挡了?根据特定的阴影映射算法,使用各种投影纹理化方法生成纹理坐标。

投影纹理只是将对象转换为纹理空间的一种方式(是的,我知道这听起来很倒。但这就是它的工作原理)。阴影映射算法使用几种不同类型的变换。但最终,这些只是从一个空间到另一个空间的转换。

渲染阴影贴图时,可以获取几何图形的顶点,并通过标准渲染管线对其进行变换。但是相机和投影矩阵是针对您的灯光位置和方向而设计的,而不是针对视图位置和方向而设计的。

使用阴影贴图进行正向渲染时,将正常渲染对象,将顶点转换到视图相机空间并通过视图投影矩阵。但是,您还可以通过光相机和投影矩阵变换顶点,将它们作为每个顶点数据传递到片段着色器。它通过投影纹理使用它们来访问阴影纹理。

这是重点。投影纹理访问的设计使其在纹理上的访问位置表示表面上该点(您在片段着色器中渲染的点)与光照之间的方向。因此,它将获取表示要渲染的片段发生遮挡的深度的纹素。

但是这个管道没有什么特别的。您不必将顶点位置转换为阴影纹理并将其传递到片段着色器。您可以将世界空间顶点位置传递给片段着色器,然后使片段着色器将它们转换为阴影纹理的投影空间。当然,您将放弃很多性能,因为您将获得完全相同的纹理坐标。但这在数学上是可行的。

实际上,您可以将视图摄影机空间顶点位置传递给片段着色器。然后可以将它们转换为世界,然后转换为灯光摄影机空间,再转换为投影阴影纹理空间。您可以将所有转换转换为一个矩阵(取决于阴影投影算法)。同样,这将为您提供以前的功能,因此,在进行正向渲染时,没有理由这样做。

但是在延迟渲染中,您已经具有查看相机空间顶点的位置。您必须这样做,否则您将无法进行照明。您要么通过将它们写入缓冲区浪费了很多内存和带宽,要么您很聪明,并使用深度缓冲区和各种数学方法对它们进行了重新计算(我不会在这里进行介绍,但会在网上进行介绍)。

无论哪种方式,您都可以查看相机空间位置。并且,如上所述,我们可以应用矩阵将它们从视图摄影机空间转换为阴影投影纹理空间。所以... 然后访问您的阴影贴图。

问题解决了。


是否可以在延迟渲染中排除每个光源的几何形状(出于优化目的)?
Samaursa,

@Samaursa:“排除每盏灯的几何形状”是什么?从进入阴影贴图?从被点燃?
Nicol Bolas

我看到您回答了有关此问题,谢谢。对于其他人,如果他们想遵循问题/答案:gamedev.stackexchange.com/q/178755/2287
Samaursa
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.