Spellwrath实时光线追踪软阴影(二)

share

光线追踪器追踪目标之后,采取以下步骤来追踪阴影:

对于场景中的每个像素(2D),我们从它实际在世界空间中的3D位置处向光源投射射线

如果像素是被遮挡的,存储遮挡值

如果像素没有被遮挡,在缓冲区的存储值为1.0

这非常直观。对于硬阴影而言,这足以对所有被遮挡部分着色。简单地添加一些光线至每个像素中,且缓冲区值小于1.0。

正如之前所说,我们将一些常见的方法与光栅化技术结合来进行实时光线追踪。其中一个行之有效的方法便是延迟渲染。因此,我们所跟踪的每个像素的实际渲染步骤将在光线追踪之后完成:

确定像素是否被遮挡(光线追踪阴影缓冲输入值小于1.0)。如果被遮挡,使用数值2。

确定取样尺寸(光线追踪阴影缓冲区)

理论上,取样尺寸可以告诉我们半影在场景中这个区域的尺寸。因此,我们需要检查某个区域是否有半影。显然,我们需要某些角度的因子,除以该像素的深度值便可以得到。

请注意,这里已经简化了视角转换,即简单的除以Z值。这忽略了一个事实:由于阴影区域距离观察者更近,半影在场景空间的尺寸会更大。当保持因子不变而人为增大取样尺寸来获得此效果时,这一点讲得通。

为简单起见,我们假定观察者正垂直地看着阴影区域,即采样区域每个像素的Z值是相同的。

最大的平方距离从而减少至:

接下来便是简单的网格搜索。寻找最近的亮像素进行比较,并找到最小平方距离的像素。

网格取样的频率及所希望获得的性能取决于我们自己。取样越多则半影会越平滑。

请注意,这个阶段可能会再次需要像素的Z值来创建更精确的阴影,且这不取决于观察者观看的角度。为此,不用预先计算Dmax值,而是在网格搜索时对其进行计算,因为我们不知道Z值能达到的最远点。

此外,还需要把距离内的Z值与最近的光亮入口结合起来。

这是对每个像素进行的额外计算。它不仅加强了准确性,最重要的是,从独立的观察视角而言,可以忽略此计算来加快速度。至少我是这样做的。

现在,我们知道了某个限制区域内被遮挡像素到最近亮像素之间的距离。它实际告诉我们特定点阴影的强度, 其极限位置是:

或者

通过标准光照方法,使用该值来给像素着色。

通过这种方法,在硬阴影之上使用软阴影仅产生很小的性能损失,因为我们对每个像素进行了光线追踪。速度的损失不受对象数量或场景大小的影响,其完全取决于我们希望执行的场景大小和样品密度。

但为什么不模糊阴影边缘来创建希望达到的柔软效果?因为这样便不会获得极致的效果:

总结

使用这种方法,可以在实时光线追踪器中最有效最轻松地实现软阴影。阴影是完全动态的,不需要预先计算。只有额外的帧缓冲区有进一步的内存需求时,才需要将阴影数据从光线追踪器中传输至后期处理系统中。

如果要慢慢过渡到光线追踪实时应用程序中,必须至少要与现代光栅化技术的图形质量相匹配。我认为这方面的工作我们前进的轨道是正确的。

share