Spellwrath实时光线追踪软阴影(二)
光线追踪器追踪目标之后,采取以下步骤来追踪阴影:
对于场景中的每个像素(2D),我们从它实际在世界空间中的3D位置处向光源投射射线
如果像素是被遮挡的,存储遮挡值
如果像素没有被遮挡,在缓冲区的存储值为1.0
这非常直观。对于硬阴影而言,这足以对所有被遮挡部分着色。简单地添加一些光线至每个像素中,且缓冲区值小于1.0。
正如之前所说,我们将一些常见的方法与光栅化技术结合来进行实时光线追踪。其中一个行之有效的方法便是延迟渲染。因此,我们所跟踪的每个像素的实际渲染步骤将在光线追踪之后完成:
确定像素是否被遮挡(光线追踪阴影缓冲输入值小于1.0)。如果被遮挡,使用数值2。
确定取样尺寸(光线追踪阴影缓冲区)
理论上,取样尺寸可以告诉我们半影在场景中这个区域的尺寸。因此,我们需要检查某个区域是否有半影。显然,我们需要某些角度的因子,除以该像素的深度值便可以得到。
请注意,这里已经简化了视角转换,即简单的除以Z值。这忽略了一个事实:由于阴影区域距离观察者更近,半影在场景空间的尺寸会更大。当保持因子不变而人为增大取样尺寸来获得此效果时,这一点讲得通。
为简单起见,我们假定观察者正垂直地看着阴影区域,即采样区域每个像素的Z值是相同的。
最大的平方距离从而减少至:
接下来便是简单的网格搜索。寻找最近的亮像素进行比较,并找到最小平方距离的像素。
网格取样的频率及所希望获得的性能取决于我们自己。取样越多则半影会越平滑。
请注意,这个阶段可能会再次需要像素的Z值来创建更精确的阴影,且这不取决于观察者观看的角度。为此,不用预先计算Dmax值,而是在网格搜索时对其进行计算,因为我们不知道Z值能达到的最远点。
此外,还需要把距离内的Z值与最近的光亮入口结合起来。
这是对每个像素进行的额外计算。它不仅加强了准确性,最重要的是,从独立的观察视角而言,可以忽略此计算来加快速度。至少我是这样做的。
现在,我们知道了某个限制区域内被遮挡像素到最近亮像素之间的距离。它实际告诉我们特定点阴影的强度, 其极限位置是:
或者
通过标准光照方法,使用该值来给像素着色。
通过这种方法,在硬阴影之上使用软阴影仅产生很小的性能损失,因为我们对每个像素进行了光线追踪。速度的损失不受对象数量或场景大小的影响,其完全取决于我们希望执行的场景大小和样品密度。
但为什么不模糊阴影边缘来创建希望达到的柔软效果?因为这样便不会获得极致的效果:
总结
使用这种方法,可以在实时光线追踪器中最有效最轻松地实现软阴影。阴影是完全动态的,不需要预先计算。只有额外的帧缓冲区有进一步的内存需求时,才需要将阴影数据从光线追踪器中传输至后期处理系统中。
如果要慢慢过渡到光线追踪实时应用程序中,必须至少要与现代光栅化技术的图形质量相匹配。我认为这方面的工作我们前进的轨道是正确的。