Whitted-Style光线追踪

发布时间 2023-03-27 21:54:14作者: 爱莉希雅

前言

​ 本篇将介绍什么是光线追踪,为什么需要光线追踪,实现光线追踪的细节,看完本篇即可跟着教程ray tracing in one weekend用c++实现一个简单的光线追踪器,关于该教程笔者也写了总结rayTracingInOneWeekend - 爱莉希雅 - 博客园 (cnblogs.com)

什么是光线追踪?

​ 光线追踪(Ray tracing)是三维计算机图形学中的特殊渲染算法,跟踪从眼睛发出的光线而不是光源发出的光线,通过这样一项技术生成编排好的场景的数学模型显现出来。这样得到的 结果类似于光线投射与扫描线渲染方法的结果,但是这种方法有更好的光学效果,例如对于 反射与折射有更准确的模拟效果,并且效率非常高,所以当追求高质量的效果时经常使用这种方法

​ Whitted 于 1979 年提出了使用光线跟踪来在计算机上生成图像的方法,这一方法后来也被称为经典光线跟踪方法、递归式光线追踪方法,或 Whitted-style 光线跟踪方法。其主要思想是从视点向成像平面上的像素发射光线,找到与该光线相交的最近物体的交点,如果该点处的表面是散射面,则计算光源直接照射该点产生的颜色;如果该点处表面是镜面或折射面,则继续向反射或折射方向跟踪另一条光线,如此递归下去,直到光线逃逸出场景或达到设定的最大递归深度

​ 效果图
image-20230327152821062

  • 图形学中的光线的性质

    1. 沿直线传播
    2. 光线和光纤间无法碰撞
    3. 光线路径可逆
  • 光线追踪主要遵循第三条性质光线可逆。现实生活中是光线不断散射后进入人眼,而在光线追踪是人眼发出光线
    image-20221225195518753

    根据上图所示,光线追踪过程如下:

    1. Ray Casting:从相机向投影的近平面上的每个像素发射一条光线,判断和场景中的物体的交点(最近的交点).再连接交点和光源,判断该连线间是否有物体,若有说明该交点在阴影中.利用Blinn-Phong模型对该点进行局部光照模型计算,得到该像素的颜色,该颜色就是目前像素点的颜色
    2. Whitted-Style Ray Tracing:可以看出目前和局部光照模型差不多,我们还需考虑全局效果。考虑第一步Ray Casting,该线和物体相交会发生散射,散射的光线和其他物体相交继续散射,将这些交点和光线相连,对这些点都计算颜色,最后将这些颜色全部按照权重累加,最终得到近平面该像素点的颜色

    注意:

    1. 光线追踪是一个递归过程,需要终止条件,如最大散射次数
    2. 光线每次散射都有能量损耗,该损耗由系数因子决定
    3. 若散射后没有与物体相交,则返回背景色
  • 光线追踪伪代码

    for each pixel of the screen
    {
    	Final color = 0;
    	Ray = { starting point, direction }; 
    	Repeat
    	{
    		for each object in the scene 
    		{
    			determine closest ray object/intersection; 
    		}
    		if intersection exists 
    		{
    			for each light inthe scene 
    			{
    				if the light is not in shadow of anotherobject 
    				{
    					addthis light contribution to computed color; 
    				}
    			} 
    		}
    		Final color = Final color + computed color * previous reflectionfactor; 
    		reflection factor = reflection factor * surface reflectionproperty; 
    		increment depth;
    	} until reflection factor is 0 or maximumdepth is reached 
    }
    

为什么需要光线追踪?

​ 可以看出光线追踪是一种全局光照,而光栅化只能实现局部光照,很明显光线追踪得到的效果图更加明亮,质量更高!

光线的表示

​ 将光线看成一条射线,由起点和方向两个属性构成:$r(t) = o + td, 0 \leqslant t \leqslant ∞ \(,其中\)o\(为起点,\)d$为方向
image-20230327133553889

物体和光线求交

光线和隐式曲面求交

​ 在此,我们选球体作为隐式曲面,那么有:

  • 光线:$r(t) = o + td, 0 \leqslant t \leqslant ∞ $
  • 球体:\((p - c)^2 - R^2 = 0\),其中p是光线和球体的交点,c为圆心,R为半径

​ 当这两个方程有实数解时即可解出交点:\((o + td - c)^2 - R^2 = 0\),只有c未知,可以看出这是一个一元二次方程\(a = d·d \\ b = 2(o-c)·d \\ c = (o-c)^2 - R^2\),\(t = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}\)

  1. 若是两个不同的正实数解,说明射线和球体有两个交点
  2. 若是两个负实数解,说明射线的反向延长线上和球体有两个交点
  3. 若都包含虚部,说明没有相交
  4. 若是两个相同的实数解,说明射线和球体相切
  5. 若是一正一负两个解,说明射线起点在球体内,其中一个交点是射线的反向延长线

光线和显式曲面求交

​ 该处的显式曲面具体指的是平面,如三角形面,可以用以下式子表示:
image-20230327135958201

此处虽然不是一个三角形面,但三角形面也处于该平面内,我们只需求出光线和平面的交点,然后判断交点是否在三角形面内即可

​ 过程:

  1. 用点法式定义平面
  2. 将光线带入平面方程,求解交点,再判断是否在三角形内
    image-20230327140237709

但对于该过程可以将将其合为一步——克莱姆法则。如下图所示,求解\(t, b_1, b_2\)后还需判断是否合理——t是否有意义,\(b_1,b_2,b_3\)为负
image-20230327140647333

计算散射方向

反射

​ 假设,目前知道光线\(l\)和物体相交发生反射,如何求反射向量\(r\)

image-20230327143526923

过程如下:

  1. \(r = 2p + l\)
  2. \(p = s + (-l)\)
  3. \(s = N(l·N)\)
  4. \(p = N(l·N) - l\)
  5. \(r = 2N(l·N) - l\)

折射

​ 由折射法则\(\eta · sin \theta = \eta' · sin \theta'\)(\(\theta\)\(\theta'\)分别为入射光线\(R\) 和 折射光线\(R'\) 和法线的夹角)可得折射光线\(R' = sin \theta' = \frac{\eta}{\eta'} · sin \theta\)
image-20221223184117243

目前,有未知的折射光线\(R'\)、未知的法向量\(N'\),为了求\(R'\),我们将\(R'\)拆分后的垂直\(N'\)和平行\(N'\)的向量:

  1. \(R'_{\|} = \frac{\eta}{\eta'}(R + (-R · N) N) = \frac{\eta}{\eta'}(R + cos \theta N) = \frac{\eta}{\eta'}(R + (-R·N) N)\)
  2. \(R'_{\perp} = -\sqrt{1 - |R'_{\|}|^2 }N\)
    image-20221224002236561

reference

GAMES101:现代计算机图形学入门 – 计算机图形学与混合现实在线平台 (games-cn.org)

[Game-Programmer-Study-Notes/README.md at master · QianMo/Game-Programmer-Study-Notes · GitHub](https://github.com/QianMo/Game-Programmer-Study-Notes/blob/master/Content/《Real-Time Rendering 3rd》读书笔记/README.md)