光线追踪的一个优势在于,通过扩展光线传播的理念,我们可以很简单地实现反射和折射,两者在模拟玻璃或镜面材质时会很方便。1979年的一篇论文An Improved Illumination Model for Shaded Display
中,Turner Whitted首先描述了如何扩展Appel的光线追踪算法来进行更高级的渲染。Whitted的理念包含反射和折射的计算。
光学中,反射和折射是很常见的现象。首先介绍一下,我们以一个玻璃球作为例子,同时拥有折射和反射属性。只要我们知道与球交叉的光线的方向,就很容易计算折射和反射。反射和折射方向基于交叉点的法线方向和入射光的方向。为了计算折射方向,我们还需要材质的折射系数。尽管我们之前提过光线以直线前进,我们可以假设折射是光线弯曲了。当光子碰撞到一个不同的介质表面时,它的方向会改变。
类似地,我们必须意识到物体的反射和折射是同时进行的。我们需要对一个表面上的给定点同时计算,但我们如果进行混合?混合不能直接的五五分,混合值区域局主光线和物体法线的角度和折射系数。我们可以通过菲涅尔等式来计算这一点。
回到正题上,我们介绍一下Whitted算法的工作原理。我们从眼睛射出一条主光线到与场景中物体的最近交叉点。如果光线碰撞到一个非漫反射或不透明的物体,我们必须进行额外的工作。为了在该点计算结果颜色,假设一个玻璃球,我们需要计算反射颜色和折射颜色,然后混合。记住,我们会用三步进行,计算反射颜色,计算折射颜色,然后应用到菲涅尔等式中。
- 首先计算反射方向,我们需要交叉点的法线和主光线方向,一旦我们获得了反射方向,我们以该防线射出一条新光线。回到我们的例子,假设反射光线碰撞到了红球,使用Appel的算法,我们通过射出阴影射线到光源来判断有多少光到达了红球的该点上,获取的颜色然后回与光强相乘,返回到玻璃球的表面。
- 现在我们对折射进行相同的工作。注意,因为光线回穿过玻璃球,因此可以称为穿透光线。为了计算穿透方向,我们需要碰撞点的法线、主光线方向和材质的折射系数(玻璃球大概是1.5)。计算了新方向后,折射光线接着与玻璃球的另一面进行交互,这里再次发生折射。只要在表面两侧发生介质变化就会发生折射,进入和出去的光线拥有不同的折射率。假设离开的折射光线与绿球交互,那么我们就可以计算交差点的光照,颜色然后与光强相乘,返回到玻璃球表面。
- 最后,我们计算菲涅尔等式,我们需要玻璃球的折射因数,主光线和碰撞点法线之间的夹角,使用点积,菲尼尔等式回返回两个混合值。
下面是伪代码:
// compute reflection color
color reflectionCol = computeReflectionColor();
// compute refraction color
color refractionCol = computeRefractionColor();
float Kr; // reflection mix value
float Kt; // refraction mix value
fresnel(refractionIndex, normalHit, primaryRayDirection, &Kr, &Kt);
// mix
color glassBallColorAtHit = Kr * refelctionCol + (1-Kr)*refractionCol;
网友评论