1.基本原理
1.1为什么我们要引入光线追踪呢?
光栅化不能很好地处理全局效应
比如——(软)阴影
-尤其是当光线反弹不止一次的时候
光栅化的速度很快,但渲染质量相对要差一些。
比如吃鸡就是用的光栅化来渲染。
光线追踪速度很慢,但质量更好一些。
有时候甚至会用10K CPU核心小时来渲染一帧
基于此,一般实时游戏采用光栅化,而离线游戏用光线追踪(事实上,现在的技术几乎快实现实时游戏也可以用光线追踪实现了)
1.2基础光线追踪算法
光线
计算机图形学中关于光线的三个观点
- 光沿直线传播(尽管这是错误的)
- 光线交叉时不会相互“碰撞”(尽管这仍然是错误的)
- 光线从光源传播到眼睛(物理是不变的路径反转)。
光线投射
4. 通过每像素投射一束光线来生成图像
5. 通过向灯光发送光线来检查阴影
针孔相机模型
递归(Whitted-Style)光线追踪
视线沿看到的某一个像素投射出一条光线打到一个点
这个点光线可能是由这个点打过来的
也有可能是球面内部透射过来的
而这些光都是由光源发出来投射的
2.18更新内容:
1.3光线与表面的交点
光线方程:
光线由一个起点和一个方向来定义,于是乎,我们可以把它用类似于极坐标的方式来实现。
举个例子:
光线与⚪的交点:
交点一定在⚪上也一定在光线上。
所以我们可以把r(t)代入p
由此,我们可以有推论(一般情况):光线与隐式曲面的交点
就是代入,好像是高中数学233
可以用于解决这样的图形
光线与三角形网格的交点
为什么要与三角形网格求交点?
•渲染:可见性,阴影,照明……
•几何:内部/外部测试
如何计算?
让我们来分析一下:
•简单的想法:只需与每个三角形相交
•简单,但缓慢(加速?)
•注意:可以有0,1个交点
(忽略多个交点)
光线与三角形相交
三角形在一个平面内那么我们只需要知道光线与平面的交点是否在内部三角形就ok了
这一步上有许多优化方法
和与⚪求交类似的,要先定义平面方程。
平面由一个点和一个法线来定义的
于是平面方程为:
代入:
1.4加速求光线与表面交点算法
光线追踪-性能挑战
简单光线与场景的交点都需要:
•用每个三角形详尽地测试射线相交
•找出最近的命中值(即最小t)
问题:
•Naive algorithm = #pixels⨉# tringles(⨉#bounces)
•非常缓慢!
为了通用性,我们稍后使用术语对象而不是三角形(但并不一定指整个对象)
包围盒
最容易想到的加速算法就是包围盒了吧
避免交叉的快速方法:绑定复杂对象
用一个简单的体积,对象完全包含在卷中
•如果它没有击中包围盒,就不会击中物体
•首先测试包围盒,然后测试对象是否命中
光线与盒子的交点。
理解:盒子是三对平面的交点
具体地说:我们经常使用Axis-Aligned Bounding Box (AABB)(轴对⻬包围盒)
即BB的任何边都是沿着x、y或z轴的
光线与AABB相交
举二维例子;3D也是如此!用平面计算交点
取tmin/tmax区间的交点
若是三个区间存在共同的交集,则光线穿过了包围盒,我们需要往里面进行计算。
For the 3D box, tenter = max{tmin}, texit = min{tmax}
如果texit < 0怎么办?
-盒子在射线的“后面”-没有交叉!
•如果texit >= 0和tenter < 0怎么办?
-射线的原点在盒子里面-有交集!
为啥要轴对称呢,为了方便计算:
2.均匀空间划分(网格)
预处理-建立加速网格
第一步:建立包围盒
第二步:
创建网格
第三步:将每个对象存储在重叠的单元格中
未完待续…