games101-13-Ray_Tracing1

Whitted光线追踪如何处理全局光照

​ 光栅化不适合处理全局的效果。如软阴影、磨砂材质、间接光照(光反射多次后到达相机)。在之前的光栅化处理中,只考虑光的一次反射,从光源到达着色点再到达相机。光栅化渲染快,常用于实时渲染(每秒超过30帧)

假设:

(1)光线沿着直线传播

(2)光线和光线不会发生碰撞

(3)光线路径可逆,即从A发出的到B的光线,一定也可以从B发出到A(中途可发生反射和折射)

​ 从人眼或摄像机向近投影平面上的每一个像素点发射一条光线,判断与场景物体的交点。一条光线可能会与不止一个物体相交,但是考虑遮挡关系,只去找最近的交点(相当于进行了深度测试)。

image-20230512140740839

​ 由于要计算每一个片元的值,因此需要以相机为起点,向每一个像素都发射一条光线。在view空间下进行计算,需要将屏幕的像素中心坐标,变到view空间下。(相机在原点看向-z轴)

​ view空间变到屏幕空间的过程:透视视锥体(宽高比=屏幕宽高比)压缩成正交长方体,将正交长方体压缩到[-1,1]的正方体。z值用于深度测试,将[-1,1]的xy拉伸到屏幕的[0,w]和[0,h]。

​ 逆变换:将屏幕上的像素中心坐标先变换到[0-1],再变换到[-1,1](注意opengcv的y轴朝下,这一步需要将y轴变换朝上)。将[-1,1]拉伸到与屏幕相同的宽高比,但是xy(或者说平面宽高)具体是多少由可视角度和距相机的距离决定。得到view空间下近平面上的坐标(近平面大小)。屏幕上每一个像素点与view空间下近平面上每一个点一一对应。也就是以相机为起点,向近平面像素的对应点都发射一条光线,判断与场景物体的交点。

​ 不进行优化的找最近交点的方式:对于一根光线,遍历场景中的每一个物体对象。对于每一个对象,如果是网格对象,将光线与网格对象的每一个三角形求交,记录最近的三角形(距离、交点重心坐标和三角形索引等)。如果是类似球的隐式几何体,直接带入求解。遍历物体对象时,如果光线与物体有交点,还得确保比上一个对象的交点更近。最后记录最近的物体对象及三角形信息。

image-20230512140905212

​ 还是针对一根光线:接着连接该交点和光源,只要判断这条连线之间是否有物体存在就可以知道该交点是否在阴影之中。新的光线,光源起点为着色点,光线方向为光源-着色点。对新的光线类似于从相机发射的光线那样进行光线追踪。判断是否有更近的交点。如果该点不在阴影中,知道该点的法线(三角形可以用两条边叉乘再归一化,球体就是着色点-球心再归一化)、相机位置和光源位置,可以利用blinn-phong计算出该点对应的像素值。遍历所有近投影平面上的像素就能得到一张完整的图像。此时效果与局部光照模型是一样的,只考虑了光一次反射,计算得到的是硬阴影。(相当于光线直接打在物体上,由于是漫反射,一定有一根光线会进入相机)

​ 上一个例子中光线第一个与圆球物体相交,假设该圆球是一个镜面球,那么便会发生镜面反射。如果是玻璃球,除了镜面反射之外,也存在折射,同时反射与折射出去的光线可能与场景中的物体再次碰撞,发生第二次折射与反射。下图以两个光线,以两次折射或反射的部分光线为例。(全局光照重点是考虑间接光照,及光的多次反射/折射)

image-20230512141359281

​ 此时每一个像素的颜色贡献来自直接光照,反射方向间接光,折射方向间接光(如果有折射的话)。下一步将这些所有交点(上图中4个交点)与光源连接,计算这些所有点的局部光照模型的结果(被遮挡就不用计算),将其按照光线能量权重累加(光在传播过程中会有损失,如果不添加权值最后会发生曝光),最终得到近投影平面上该像素点的颜色。这是一个全局光照模型,不仅仅考虑了直接光源的贡献,还考虑各种折射与反射光线的贡献。

​ 具体做法是,求出镜面反射的光线(或折射光线),此时这条光线不一定指向光源。因此对该光纤进行递归处理(与上述单单追踪不同)。如果该光线碰到的是镜面物体,则继续反射递归;碰到的是透明物体继续反射+折射递归。递归的此处有最大限制,不能无限递归。如果在有限递归次数内,相交到漫反射物体,不再继续反射和折射,进行光照计算。为了防止结果过亮,每次反射/折射都有损失。菲涅尔项得到反射率为k,折射率为1-k。

image-20230512141440915

​ 上图中的光线分成三种类别,相机到物体为primary ray;中间反射和折射的蓝线为secondary ray;最后交点与光源的连线为shadow ray,因为要考虑遮挡。

如何判断光线与物体的交点

光线与隐式几何求交

​ 通过光源位置O和光线方向d定义一条光线(光线是射线):

image-20230512142046886

​ 光线与球求交,t值对应的点需要满足两个表达式:

image-20230512142416606

​ 光线与球求交可能会没有交点、有一个交点或者有两个交点。在有两个交点的情况下,取更小的t值。(并且保证更小的t必须是实数且为非负数)

image-20230512142454099

​ 对于光线与隐式表面的交点,只要将光线方程代入求解 t 即可:

image-20230512150218495
光线与显示几何求交

​ 对于显示表面,最重要的是判断光线如何与三角形求交(只考虑0/1个交点)。如下图可以将该光线与所有三角形面求交,找到最小的t值。对于多个像素(多条光线)都与所有面计算,计算量相当大。总计算量为像素数(一个像素一个光线)✖三角形面。

image-20230512150709077

​ 判断光线与三角形所在平面是否有交点,如果有交点再判断该点是否在三角形内部。

​ 首先通过一个点和法线定义一个平面。如果任意一点和该点的连线与法线垂直,则说明该点在平面上。将p和n用xyz定义,展开后如右式。

image-20230512151503743

​ 得到参数 t 之后,可以计算出交点,并且再去计算出重心坐标就能判断该交点是否在三角形内。

image-20230512152052037

​ 如下方法直接判断光线在三角形内部是否有交点。假设该点在三角形内,则可以通过重心坐标表示。通过如下方法解出t,b1,b2。如果t,b1,b2,1-b1-b2都是非负数,则该点在三角形内部(注意要判断4项,x是叉乘,.是点乘)。

image-20230512152025494

光线与包围盒求交

​ 使用包围盒加速光线与物体求交。三维空间常用的包围盒是AABB包围盒,即一个长方体。包围盒是由3个对面形成的交集。以二维为例,计算出光线进入两个对面的时间,和光线出两个对面的时间。将第一幅图和第二幅图的线段做交集。

image-20230512154907983

​ 对于三维场景来说,光线进入一个盒子,就说明三个对面都要满足光线已经进入(对所有的进入时间tmin取最大值);光线离开一个盒子,只要满足光线离开任意一个对面(对所有的离开时间tmax取最小值)。如果进入时间小于离开时间,光线一定会在盒子中停留一段时间,即有交点。

image-20230512155903819

​ 使用AABB便于计算,之前计算光线与任意平面求交计算很复杂。

image-20230512162803617

​ 如果光线离开盒子的时间<0,说明盒子在光线背后。如果离开盒子的时间≥0,但是进入盒子的时间<0,说明光线起点在盒子内部。如果离开时间<进入时间,则没有交点。当且仅当进入时间小于离开时间,且离开时间≥0,光线与盒子有交点。(不考虑平行,光源在盒子内部也算有交点)

image-20230512164222503 image-20230512164312676
image-20230512165258572
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码

请我喝杯咖啡吧~

支付宝
微信