更新时间:2022-08-25 16:56
要构造一个阴影体,先从光源投射一条射线穿过产生阴影的物体中的每个顶点到某个点(通常在无穷远点)。这些射线一起组成一个体;每个该体中的点都在阴影中,所有在外部的物体被该光源照亮。
实际的阴影体如下计算:
当前的研究和实现方法侧重于使用硬件的模版缓存(stencil buffer)来优化算法以利用硬件加速-参看模版阴影体。
为测试绘制的图像的给定像素是否在阴影中,阴影体本身需要被绘制,但它是绘制到模板缓存,而不是最终的图像中。对于每个阴影体中的前向面,模板缓存中的值是增加的;对于后向面,它是减少的。
一旦所有阴影体中的面被绘制到模版缓存,任何值非零的像素将处于阴影中。
要理解其原因,考虑从像素到屏幕的光线反向回到物体的射线-若它穿入阴影体,它将会穿过一个前向面,所以模版缓存对应像素的值会增加。若它又穿出阴影体(通过一个后向面)该值将会再次减少。
但是如果该像素在阴影中则该值只在它从后面离开阴影体时被减少,所以该值非零。
图1显示了一个包含一个镜头,一个光源,一个阴影产生物体(蓝色圆圈)和三个阴影接受物体(绿色的方块),全部用二维示意。粗黑线表示阴影体的轮廓。从相机(笑脸)投射的线表示视线。
该视线首先击中物体a;在该点它没有达到阴影体的任何面,所以帧缓存会有0值-不在阴影中。在点1阴影体的一个前向面被穿过因而增加了模版缓存中的值。然后我们击中物体b;在该点我们在缓存中有一个值为1,所以该物体在阴影中。沿着视线继续前进,我们会在点2到达阴影体的后向面,因而把模版缓存中的值减少到0。最后我们击中物体c,模版缓存中的值又是0,所以该物体也不在阴影中。
该算法的一个问题在于若相机(眼睛)本身在阴影体中则该方法会失败-视线首先穿过阴影体的后向面,将模版缓存中的值减少1,使得它在到达物体c的时候有非零值,虽然该物体不应该在阴影中。
这个问题的一个解决办法是从无穷远的某点返回到相机。该技术由一些人独立发现,但是由John Carmack推广,并经常被称为Carmack的翻转。