摘要 图像渲染就是一个这样的过程,输入一组物体,输出一个像素矩阵。把这个像素矩阵输送给显卡,显示器上就可以显示出来图像。本篇介绍下这个过程用到的算法,就是光线追踪。
算法介绍
光线追踪的思路就是从视角发出光线,分别经过屏幕上的每个像素,这样的光线经过屏幕后,找到相交的首个#物体位置,这就是该像素对应的物体,然后再从物体相交点到光源投射一条光线,这时候就可以计算像素值。如下图所示:
光线追踪示意图
从图中可以抽象出要计算一个点的像素值,需要以下步骤:
- 产生光线,计算从视角经过像素的每条光线
- 计算光线与物体的相交点
- 计算阴影
产生光线
接下来先看第一个问题,产生光线。 要表示光线,那么就需要了解下正交投影和透视投影。正交投影就是假设光线是从一个方向发出的,这样现实中平行的物体最后的投影也是平行的,而透视投影就是假设光线是从一个点发出的,这样平行的物体就会在远处相交。 如下图所示:
正交投影
透视投影
透视投影对于我们更接近真实情况,比如我们看平行的两条铁轨,这两条铁轨会在远方的一个点处“相交”。 光线可以表示成如下公式:
image.png
e是视点,s是屏幕上一个像素位置。 参考图如下:
image.png
光线与物体相交
接下来就是第二个问题,怎样计算光线和物体的交点。
物体也可以用一个平面方程表示
image.png
对于一个点,如果满足该函数,那么就可以认为该点在物体表面上。问题1将光线表示出来了,那么这儿只需要将光线作为点代入这个平面方程,通过计算参数t就可以知道是否相交,也可以计算出相交点。不过这样的计算量会比较大,而且需要用一个方程表示平面,难度也不小。下面介绍一种方法,可以比较直观的计算出交点。
我们知道在渲染的时候,是按照三角形来的,那么我们也可以把物体表面看成是n个三角形构成的,那么这时候只需要计算光线和三角形的交点就行。 假设目标三角形的三个顶点是a,b,c。这时候求交公式就可以表示为如下:
image.png
等式右边表示的是交点,如果满足如下公式,那么说明点在三角形内,否则就是三角形外。
image.png
,
这时候可以把方程写成矩阵格式,如下:
image.png
这时候按照克莱姆法则,就可以直接计算出解了:
image.png
image.png
这时候交点问题也解决了。
阴影计算
阴影计算的一种基础算法是Blinn-Phong模型,将光照模型分为3部分,漫反射,高光,环境光。
漫反射
光源直射的表面会比光源斜射的部分亮一些,基于该假设就可以认为表面法线和入射光的角度越接近,那么能量越高,参考图如下。
image.png
向量的点乘可以表示两个向量方向的接近程度,那么漫反射公式就可以写成如下:
image.png
高光
如果观察方向正好是入射光的反射方向,那么这时候接收的能量也比较多,而离反射方向越远,接收的能量也会越少。用图表示如下:
image.png
描述观察方向和反射光方向的接近程度可以用观察方向和入射方向的二等分量和表面法线的接近程度来表示。那么这时候就可以得到高光的表示公式:
image.png
环境光
在没有光源的时候,我们还是可以看到物体的,这是因为虽然没有光源,不过周围的物体也会反射一些光,这样的光就是环境光,可以简化成用一个常数表示。
image.png
在有多个光源的时候,漫反射和高光就需要对每个光源单独计算并累加。最终公式如下:
image.png
阴影
可以从交点朝着光源望去,如果可以看到光源,那么该交点不在阴影中,如果看不到光源,那么该交点就在阴影中。如下图所示:
image.png
这时候整个光线追踪的流程可以写成如下形式:
image.png