快速跳转:
光栅化:已知三角形在屏幕上的二维坐标,找出哪些像素被三角形覆盖。物体 找 像素点
光线追踪:从相机出发,对每个像素发射射线去探测物体,判断这个像素被谁覆盖。像素点 找 物体
不同于光在波动学中的定义,对于图形学中的光线简化(并不是很正确、很物理)的定义:
(1)光沿直线传播
(2)光线之间不会相互影响、碰撞
(3)光本该从光源出发照射到物体反射进入人眼,但图形学中反着来,眼睛发射光线。
Whitted-Style光追,实际上只考虑了直接光照,即直接从光源照射到物体,然后物体反射光进入人眼。它并未考虑间接光照的影响,即别的物体反射的光打到另一个物体上再进入人眼。所以它不能很好的模拟全局光照的效果。
算法过程(眼睛发射光)
(1)通过摄像机对每一个像素发出一道射线(View Ray)
(2)射中物体,把该点直接连接到光源(Shadow Ray),判断是否在阴影中(没被挡住就不在阴影内)
(3)计算着色(Blinn Phong model)
光追算法其实很好理解,摄像机(眼睛)到某像素两点一线发出射线,击中一个或多个点后,取最近一个,连到光源,若没被阻挡则不在阴影内,被阻挡则在阴影内。之后对每一个像素做一遍这个操作,有几百万个像素就要射出几百万根,所以对并行计算性能要求特别高。
如图看透明球,不仅能看到透明球,还能看到球后面的物体,这不就是光线击中球后,还进行了折射最后击中后面的地面,那交点有多个 每个交点都进行着色计算,然后按照一定的权重加到像素上
光线命名区分
定义光线:光源点、方向。t时刻光线的位置 = 光源点坐标 + t * 方向向量
球体方程
注意这个跟平常的定义不太一样(x-x0)2+(y-y0)2+(z-z0)2=R2;但其实是另一种表示而已,比如p其实就是球面上任意一点(x,y,z),c就是圆心(x0,y0,z0) 这俩相减得到一个向量,再平方(自己跟自己点积)得到的是一个标量,这个量就是R2;所以下面这个方程表示的就是位于圆心在c半径为R的球表面上的任意一点。
射线与球面相交与p点(已知:球心c,半径R,光源o,射线方向d),求解p点坐标
求解过程就是解方程组
(1) o + td = p
(2) (p - c)2 - R2 = 0
把(1)带入(2)得到关于t的 一元二次方程 解之即得t,交点是p = o+td,(注意:根t必须为实数才有意义,即△ ≥ 0)
解出来的是t,交点p = o + td
通过光线和三角形求交可以实现
求交方法:遍历物体每个三角形,判断与光线是否相交
(1)光线-平面求交(三角形属于平面)
(2)计算交点是否在三角形内(3次叉乘)
那么如何定义一个平面呢?
(p - p')·N = 0,只有p在该平面内,(p-p’)点乘N才为0,垂直嘛。打开括号,其中p' · N 为已知常量d,另一部分只有p的坐标未知p · N = ax + by + cz。Möller-Trumbore射线-三角形求交算法
AABB(轴对齐),如何快速求交点(以与x轴对齐的面为例)?
光线方程:
p
=
o
⃗
+
t
⋅
d
⃗
\large p=\vec{o}+t·\vec{d}
p=o
+t⋅d
与x轴对齐的面:
x
=
x
0
\large x=x_0
x=x0
两者求交的方式很简单,明确目的:求 t
仅看光线方程的x轴分量,公式可以变成
p
x
=
o
x
+
t
⋅
d
x
\large p_x=o_x+t·d_x
px=ox+t⋅dx,三个已知量,t很容易得出
o
x
\large o_x
ox:光线起点的x分量
d
x
\large d_x
dx:光线的方向的x分量
p
x
\large p_x
px:目标平面的x值
稍微整理一下
2D中的轴对齐盒子的求交
(1)首先第一幅图是跟X0,X1两个无限大的平面求交点,得到两个相交时间tmin、tmax
(2)然后跟y0、y1面求交点得到另一对时间tmin、tmax
(3)实际上这两次求交分别得到了两个线段,再对两个线段求个交集 即得到最后一张图的跟盒子的实际交点了
空间被划分为规则的、大小相等的单元格或体素。这些单元格可以是二维的(在2D图形中使用)或三维的(在3D图形中使用)。每个单元格都可以通过其在网格内的位置来标识,通常使用整数坐标表示。适用场景:物体均匀分布在场景的各个位置
格子数量经验公式:格子数 = 对象数量 x 27
做光线 - 物体相交计算,首先光线跟格子求交,如果遇到"内部有物体的"格子则需要做光线-物体求交,判断光线是否跟该物体相交,从而可以找到光线跟所有物体的交点。
整个算法的流程大概如下:
物体分布在大部分情况下还是非均匀的,自然空间分割也该在物体少的地方格子少一些,物体分布密集的地方格子多一些。依然是以2D为例
其中,KD-Tree需要掌握
KD-Tree 预处理
KD-Tree
求交逻辑
光线进入一个节点,判断其是否为叶子结点,
递归,直到遍历完所有的相交的叶子结点为止。
KD-Tree的缺陷:判定物体和包围盒的交集、物体是否属于某包围盒、同一物体可能存放于多个包围盒的问题,这些问题导致KD-Tree并不受欢迎。很难去建立一个很好的KD-Tree
不划分空间,而是划分物体 (目前最常用的求交加速划分策略)
根节点依然是最外层大包围盒
BVH数据的存储结构
逐步对物体进行分区:所有物体分成两组,对两组物体分别求一个包围盒(xyz的最值作为包围盒边界)
递归,对每个包围盒内部物体重复(1)中步骤,直到包围盒中的物体足够少
BVH方法的包围盒有相交,但应当尽可能减少相交区域
几种节点划分的策略
遍历BVH的算法
遍历每个盒子的算法跟KD-Tree遍历的算法没有区别,两者只是划分盒子的角度不同
递归
因篇幅问题不能全部显示,请点此查看更多更全内容