光线追踪和光栅化是两个不同的成像方式。
光栅化最大的问题是无法很好的表示全局的效果。
全局效果包括 软阴影(shadow mapping后来被改进成能够支持软阴影,阴影随着离物体越远越来越模糊),glossy反射(类似镜子,但没有镜子那么光滑,打磨的比较光滑的金属),间接光照(光线在到达人眼前会弹射很多次)
光栅化是一种很快的,但是质量较低,近似的渲染方法
光学追踪是种准确的渲染方法,但是非常慢。1帧就需要1万个cpu小时
光栅化通常用来做实时的应用,光学追踪通常被用来离线的应用(电影)
Basic Ray-Tracing Algorithm
光线;
- 光线沿直线传播(现实物理是错的,但计算机图形学离这样假设)
- 光线和光线不会碰撞(现实物理是错的,但计算机图形学离这样假设)
- 光线肯定从光源发出来,打到场景中,在场景中不断反射折射最终进入到人眼(光线的可逆性,可以理解为从人眼发出感知的光线,打到物体上,最终打到光源。即如果光源可以通过某种办法看到相机,则相机也能看到光源,可以形成一条反过来的光路)
光线追踪实际是从眼睛/相机出发,往世界中投射光线,把这些光线在世界中弹来弹去,最终到达光源。
首先做光线的投射:假设往一个虚拟的世界中看,眼前放了一个成像的平面,平面被画成了不同的像素格子。对每个像素可以从摄像机连一条线穿过像素,可以打出一根光线,这跟光线一定会打到场景中的某个位置或者和场景中什么都不相交,如果光线和场景中某一物体相交,说明沿着这个方向看到了某点,然后把这个点与光源做连线(判断点是否对光源也可见,即是否在阴影里),如果不在阴影里,则形成一条有效的光路。可以计算光路上光的能量,进行着色。
光线追踪认为眼睛永远是一个针孔摄像机,即一个点。光源也假设是个点光源。对于光线中的物体,认为光线打上去,会发生完美的反射或折射。
eye ray/camera ray:打出的光线找到场景中最近的物体相交的点
shadow ray:从交点到光源的连线。
通过法线,入射方向,出射方向可以算该点的着色,写入像素
Whitted-Style Ray Tracing
依然是找到最近的相交点,当光打到点上时,有一部分能量会被反射,另一部分能量会被折射进去
从眼睛投射出来的光线打到一个点时,如果是个玻璃材质,这个点应该做一个完美的镜面反射
同时对于玻璃球,可以折射进去,在内部继续传播,打到另外一个点,在折射出来
即在任何一个点,可以继续传播光线,只要正确的算出反射方向,折射方向
由于光线弹射的次数多了,在每一个弹射的点,都会计算着色的值,如上图每一个和光线的交点,都与光源做一条连线。看在这个点上,能否被光源照亮
如果光源可以照亮任何一个弹射的点,就把弹射的点内部算出着色的值,都加到最后着色的像素
eye ray/camera ray又称作primary ray
之后弹射的光线都称为secondary ray
往光源连线为了判定可见性的称为shadow ray
Ray-Surface Intersection
数学上的光线就是一个射线。一个起点,一个方向
点光源o,传播方向d。光线上的任意点r:
o
+
t
d
o+td
o+td,由于只往一个方向,所以
0
≤
t
≤
∞
0{\leq}t{\leq}∞
0≤t≤∞
图形学很少考虑边界,所以是否等于0影响不大
Ray Intersection With Sphere
球上任一点p到球心c的距离,都等于R
t需要为正,并且为实数,即
b
2
≥
4
a
c
b^2{\geq}4ac
b2≥4ac
Ray Intersection With Implicit Surface
光线与隐式表面求交与球求交同理,求t,t需大于0,并且为实数
Ray Intersection With Triangle Mesh
光线与显式表面三角形求交:一个一个三角形判断
对于无洞物体
点在物体内,交点数一定是奇数
点在物体外,交点数一定是偶数
Ray Intersection With Triangle
光线和三角形求交:先求光线和三角形所在平面交点,再判断交点是否在三角形内
Ray Intersection With Plane
平面:可以定义成一个方向(法线)和一个点
平面上任一点p,满足
p
−
p
、
p-p^、
p−p、的向量和法线垂直
Möller Trumbore Algorithm
MT算法:3维向量可以得出3个方程组,解3个未知量
克拉默法则求解线性方程组
Accelerating Ray-Surface Intersection
加速求交(和三角形)
原始方法每次弹射都要和场景里所有三角形求交,找出最近点,非常慢
一千多万个三角形
两千万个三角形
作业
主要注意求人眼所看实际屏幕的大小。
需要先将输出点x,y转换为正交投影的[-1,1],此时打出来的图片是上下颠倒的,说明图片着色输出顺序是反的,所以需要y取反输出,正交投影是按宽高比缩放为[-1,1],所以逆推还原屏幕比 x要乘以imageAspectRatio
人眼为光的方向是 normalize(Vector3f(x, y, -1) - Vector3f(0)),所以近平面z值在-1,此时y是被压缩成[-1,1]的范围,根据fov还原实际屏幕的y值, 实际y/z = tan(fov), z绝对值为1,所以实际屏幕y最大值为tan(fov),1要转化为tan(fov)即乘以scale。
MT算法直接抄公式,注意判定时间t大于0,以及三角形重心坐标符号点在内部的性质
github作业地址