【简介】
光线跟踪是一种真实地显示物体的方法,该方法由Appel在1968年提出。光线跟踪方法沿着到达视点的光线的反方向跟踪,经过屏幕上每一个象素,找出与视线相交的物体表面点P0,并继续跟踪,找出影响P0点光强的所有光源,从而算出P0点上精确的光线强度,在材质编辑中经常用来表现镜面效果。
光线跟踪或 称光迹追踪是计算机图形学的核心算法之一。在算法中,光线从光源被抛射出来,当他们经过物体表面的时候,对他们应用种种符合物理光学定律的变换。最终,光线进入虚拟的摄像机底片中,图片被生成出来。由于该算法是成像系统的完全模拟,所以可以模拟生成十分复杂的图片。
业界公认此算法为Turner Whitted在1980年提出。近日,世界主要国家的图形学学生都要实习此算法。他的一个著名的实现是开源软件。
【自然现象】
在自然界中,光源发出的光线向前传播,最後到达一个妨碍它继续传播的物体表面,我们可以将“光线”看作在同样的路径传输的光子流,在完全真空中,这条光线将是一条直线。但是在现实中,在光路上会受到三个因素的影响:吸收、反射与折射。物体表面可能在一个或者多个方向反射全部或者部分光线,它也可能吸收部分光线,使得反射或者折射的光线强度减弱。如果物体表面是透明的或者半透明的,那么它就会将一部分光线按照不同的方向折射到物体内部,同时吸收部分或者全部光谱或者改变光线的颜色。吸收、反射以及折射的光线都来自于入射光线,而不会超出入射光线的强度。例如,一个物体表面不可能反射 66% 的输入光线,然後再折射 50% 的输入光线,因为这二者相加将会达到 116%。这样,反射或者折射的光线可以到达其它的物体表面,同样,吸收、反射、折射的光线重新根据入射光线进行计算。其中一部分光线通过这样的途径传播到我们的眼睛,我们就能够看到最终的渲染图像及场景。
【光线跟踪算法】
下一个重要的研究突破是 Turner Whitted 于 1979 年做出的。以前的算法从眼睛到场景投射光线,但是并不跟踪这些光线。当光线碰到一个物体表面的时候,可能产生三种新的类型的光线:反射、折射与阴影。光滑的物体表面将光线按照镜像反射的方向反射出去,然後这个光线与场景中的物体相交,最近的相交物体就是反射中看到的物体。在透明物质中传输的光线以类似的方式传播,但是在进入或者离开一种物质的时候会发生折射。为了避免跟踪场景中的所有光线,人们使用阴影光线来测试光线是否可以照射到物体表面。光线照射到物体表面上的某些点上,如果这些点面向光线,那么就跟踪这段交点与光源之间的光线。如果在表面与光源之间是不透明的物体,那么这个表面就位于阴影之中,光线无法照射。这种新层次的光线计算使得光线跟踪图像更加真实。
【光线跟踪的优点】
光线跟踪的流行来源于它比其它渲染方法如扫描线渲染或者光线投射更加能够现实地模拟光线,象反射和阴影这样一些对于其它的算法来说都很难实现的效果,却是光线跟踪算法的一种自然结果。光线跟踪易于实现并且视觉效果很好,所以它通常是图形编程中首次尝试的领域。
【光线跟踪的缺点】
光线跟踪的一个最大的缺点就是性能,扫描线算法以及其它算法利用了数据的一致性从而在像素之间共享计算,但是光线跟踪通常是将每条光线当作独立的光线,每次都要重新计算。但是,这种独立的做法也有一些其它的优点,例如可以使用更多的光线以抗混叠现象,并且在需要的时候可以提高图像质量。尽管它正确地处理了相互反射的现象以及折射等光学效果,但是传统的光线跟踪并不一定是真实效果图像,只有在非常紧似或者完全实现渲染方程的时候才能实现真正的真实效果图像。由于渲染方程描述了每个光束的物理效果,所以实现渲染方程可以得到真正的真实效果,但是,考虑到所需要的计算资源,这通常是无法实现的。于是,所有可以实现的渲染模型都必须是渲染方程的近似,而光线跟踪就不一定是最为可行的方法。包括光子映射在内的一些方法,都是依据光线跟踪实现一部分算法,但是可以得到更好的效果。
【实时光线跟踪】
人们已经进行了许多努力,改进如计算机与视频游戏这些交互式三维图形应用程序中的实时光线跟踪速度。
OpenRT 项目包含一个高度优化的光线跟踪软件内核,并且提供了一套类似于 OpenGL 的 API 用于替代目前交互式三维图形处理中基于rasterization 的实现方法。
一些光线跟踪硬件,如斯坦福大学开发的实验性的光线处理单元,都是设计成加速光线跟踪处理中那些需要大量计算的操作。
自从二十世纪九十年代末开始,一些 demo programmers 爱好者就已经开发了一些光线跟踪的实时三维引擎软件。但是,demos 中的光线跟踪为了实现足够高的帧速经常使用一些不正确的近似甚至是欺骗的手段。[1]
【光学设计中的光线跟踪】
计算机图形学中的光线跟踪的名称与原理源自于二十世纪最初十年就已经开始出现的光学镜头设计中的古老技术。几何光线跟踪用于描述光线通过镜头系统或者光学仪器时的传输特性,并建立系统的成像属性模型。这用于建造前优化光学仪器的设计,例如减少色像差或者其它的光学像差。光线跟踪也用于计算光学系统中的光程差,光程差用于计算光学波前,而光学波前用于计算系统的衍射作用,例如点扩展函数、调制传递函数以及 Strehl ratio。光线跟踪不仅用于摄影领域的镜头设计,也可以用于微波设计甚至是无线电系统这样的较长波长应用,也可以用于紫外线或者X射线光学这样的较短波长领域。
计算机图形学与光学设计领域所用的光线跟踪的基本原理都是类似的,但是光学设计所用的技术通常更加严格,并且能够更加正确地反映光线行为。尤其是光的色散、衍射效应以及光学镀膜的特性在光学镜头设计中都是非常重要的,但是在计算机图形学领域就没有那么重要了。
在计算机出现以前,光线跟踪需要使用三角以及对数表手工计算,许多传统摄影镜头的光学公式都是许多人共同完成优化的,每个人只能处理其中一小部分的计算工作。现在这些计算可以在如来自于 Lambda Research 的 OSLO 或者 TracePro、Code-V 或者 Zemax 这些光学设计软件上完成。一个简单的光线跟踪版本是光线传递矩阵分析,它通常用于激光光学谐振腔的设计。
根据光线跟踪算法的定义,计算景物表面某点P的光强应由3部分组成:
- 反射方向上对其它景物引起的间接光照光强
折射方向上对其它景物引起的间接光照光强。
-
在光线跟踪算法中,涉及 4种光线:
-
q 1 条视线 E ,是由视点 V 与屏幕上的像素点 (x,y) 发出的射线;q 对每一景物表面上的交点 P i 有 3 条光线:
与光源的连线 S i
反射光线 R i
折射光线 T i -
光线跟踪算法构成的光线树
-
-
-
I
-
-
-
理论上,在理想的场景下,光线可以在景物之间进行无限的反射和折射,但是在算法的实际执行过程中不可能进行无穷的光线跟踪,因而需要给出一些跟踪的终止条件。一般可有以下几种终止条件:
q
该光线未碰到任何景物。
该光线碰到了背景。
光线在经过许多次反射和折射以后,光线对于视点的光强贡献小于某个设定值。
光线反射或折射次数(跟踪深度)大于定值。
-
- 示例:
- 选择投影中心以及视图平面上的窗口;
for (图象的每条扫描线) {
for (扫描线上的每个像素pixel) {
确定从投影中心穿过pixel的光线ray;
pixel=RayTracing(ray, 1);
}
}
//计算与景物的交点并计算最近交点的光照值
// depth是光栅树的当前深度
RayColor RayTracing(RayTracing ray , int depth)
{
确定光线与某个景物object的最近交点intersection;
if (命中景物) {
计算交点处景物表面的法向normal;
return RayShading(object,ray, intersection, normal, depth);
}
else
return BACKGROUND_VALUE;
}// RayTracing
//计算景物上一点的光照值,跟踪阴影光线、反射光线和折射光线
RayColor RayShading(
RayObject object, //相交的景物
RayRay ray, //入射光线
RayPoint point, //交点
RayNormal normal, //交点处的法向
int depth) //所处光线树的深度
{
RayColor color; //光线的颜色
RayLay ray rRay,tRay,sRay; //反射、折射、阴影光线
RayColor rColor, tColor; //反射和折射光线颜色
color=环境光项;
for (每个光源) {
sRay=从交点到光源的光线;
if (法向到光源方向的点积为正) {
计算被不透明景物和透明景物遮挡的光的量,并用该值乘漫射项和镜面反射项,然后加到color;
}
}//每个光源
if (depth<maxDepth) { //如果深度太深则返回
if (景物是反射体) {
rRay=从交点向反射方向发射的光线;
rColor= RayTracing(rRay , depth+1);
将rColor与镜面反射系数相乘,并加到color;
} //反射体
if (景物是透明体) {
tRay=从交点向折射方向发射的光线;
if (没有发生全反射) {
tColor=RayTracing(tRay ,depth+1);
将tColor与镜面透射系数相乘,并加到color;
}
} //透明体
} //如果深度太深结束
return color; //返回光线的颜色值
} // RayShading
关键技术
-
-
几何模型通常是由一些多边形、球、二次曲面(包括球面、柱面、圆锤、椭球、抛物面、双曲面等)等基本三维几何构造的,本质上求交算法是几何计算的问题。
-
例如光线与多边形求交分以下两步:
-
先计算多边形所在的平面与光线的交点,再判断交点是否在多边形内部。前者的几何计算中有简单的算法,后者是包容性测试问题
对直线与球、直线与二次曲面等的求交方法在一些几何计算专门著作中均为有一些描述。
在方法上,这些算法可采用代数计算或几何计算方法,视情况而定。
一般情况下,几何计算方法比代数计算方法常少一些计算量
-
-
-
-
基本的光线跟踪算法,每一条射线都要和所有的景物求交,然后再对所得的全部交点进行排序,才能确定可见点。对于复杂环境的场景,这种简单的处理办法效率很低,需要对光线跟踪算法进行加速。
加速技术主要有:
提高求交速度
减少求交次数
减少光线条数
采用广义光线和采用并行算法等等
-
-
1)控制跟踪深度
在光线跟踪基本算法中,结束光线跟踪的条件是光线不与任何景物相交,或已达到预定的最大光线跟踪深度。
对于复杂的场景,没有必要将光线跟踪得很深,可根据光线所穿过区域的性质自适应地改变跟踪深度。
-
2) 包围盒及层次结构
包围盒技术(最小最大拒绝判定)。基本思想是用一些形状简单的包围盒(如长方体、球面等)将复杂景物包围起来,求交的光线首先跟包围盒进行求交测试,若相交,则光线再与包围盒里的景物求交,否则光线与包围盒里所有景物必无交。它是利用形状简单的包围盒与光线求交的速度较快来提高算法的效率的。
简单的包围盒技术效率并不高,一个重要改进是引进层次结构:根据景物的分布情况,将相距较近的景物组成一组局部场景,相邻各组又组成更大的组,这样,将整个景物空间组织成树状的层次结构。
-
3) 空间网格剖分和三维DDA算法
从光线跟踪的效率来看,算法效率不高的主要原因是光线求交的盲目性:
不仅光线与那些与之不相交的景物的求交测试是毫无意义的而且光线与位于第一个交点之后的其他景物求交也是毫无意义的。
如果将景物空间剖分为网格,由于空间的连贯性,被跟踪的光线从起始点出发,就可依次穿越它所经过的空间网格,直至第一个交点。
这种方法称为空间剖分技术,可以利用这种空间相关性来加速光线跟踪。
典型的方法是将直线光栅化的DDA算法推广到三维
通过投影将三维DDA网格跨越过程分解为两个二维DDA过程。
这个算法对于稠密的场景,选取适当的空间剖分分辨率,可以使算法非常有效。
目前,该算法已经广泛地应用于各种商业动画软件中。
-
4) 空间八叉树剖分
空间八叉树算法是一个空间非均匀网格剖分算法
该算法将含有整个场景的空间立方体按三个方向分割成八个子立方体网格,组织成一棵八叉树。若某一子立方体网格中所含的景物面片数大于给定的阈值,则为该子立方体作进一步的剖分。上述剖分过程直至八叉树每一个叶子节点所含面片数均小于给定的阈值为止。
这个算法也是利用了空间连贯性。
-
-
- 选择投影中心以及视图平面上的窗口;