章节摘要:前两章把"为什么"和"算什么"讲清了,本章回到实验室的钳工台,解决"怎么撞得上"。光线追踪的一切计算最终都压到一个原子操作上:给定一条射线与一件几何,问它们相交吗、撞在哪、法线朝哪。本章两节分别是这台操作的数学面与工程面:3.1 手推三类基元的求交公式——球体用代入法、三角形用 Möller-Trumbore 算法、包围盒用平板法——每个推导都配有数值算例,算一遍就再也不会忘;3.2 讲场景如何组织成光线可查询的形态,以及求交之后那些容易被轻视却决定成败的细节:命中记录里该存什么、法线什么时候要翻向、自交的黑点从哪来、玻璃球为什么要记区间而不是记点。读完本章,你应当能徒手写出正确的求交函数,并识别出初学者实现里八成的数值 bug。
完成本章后,你应当能够:
金句先行:求交函数是全管线调用最频繁的代码,它错一个浮点位,整个画面塌一半——这里的每一行都要像钳工量具一样校准。
3.1 求交手推:球体、三角形与包围盒——三种形状代表三种解法风格。球体是"把射线方程代进曲面方程解一元二次";三角形是"把交点验证问题变成解三元线性方程组",Möller-Trumbore 的妙处在于解方程组的副产品恰好是重心坐标,法线插值与纹理采样的权重白送;包围盒是"不求精确交点,只求'有没有挡路'",平板法的区间思想日后直接长成第 4 章 BVH 遍历的骨架。
3.2 场景表示与命中点处理——求交函数再正确,场景组织不当也白搭。本节上半场讲建模网格与相交网格的分工、实例化如何用"一份原型加多个变换矩阵"让千军万马共享内存;下半场接管原第 3.3 节的内容:命中记录的完整字段设计、面向性判断、法线翻向、区间语义(进点出点对)、以及 epsilon 防自交的工程惯例。
两节是"算得准"与"管得住"的配对:3.1 交付可靠的原子操作,3.2 把原子操作组织成可查询的场景系统,并为命中结果定义数据契约。次序不能颠倒——不懂求交的数值陷阱,就理解不了为什么命中记录需要 tmin 偏移与面向标志;不懂场景组织,第 4 章的加速结构就没有挂靠点。
3.1 求交手推 3.2 场景与命中点 ┌───────────────┐ ┌───────────────┐ │ 球 代入法 │ 原子操作 │ 网格与实例化 │ │ 三角 MT算法 │ ──────→ │ 命中记录契约 │ │ 盒 平板法 │ │ 区间与防自交 │ └───────┬───────┘ └───────┬───────┘ │ 合流:一亿次每秒的调用 │ ▼ ▼ 第 4 章 加速结构:让求交从扫全场变成走树 第 6 章 路径追踪:每次弹跳都消费本章的命中记录
需要的数学:向量叉乘的几何含义(面积与法向)、二元一次与三元一次方程组求解、一元二次方程判别式——都在本章内现推现用,不要求提前熟悉重心坐标。编程上,本章的伪码用最朴素的浮点运算写成,任何语言都能对照实现。
往后的挂靠点:第 4 章的 BVH 遍历把本章的平板法包围盒测试当作唯一的裁剪工具;第 5 章的材质计算完全依赖本章定义的法线与纹理坐标插值;第 6 章迷你路径追踪器的主循环就是"求交加命中处理"的重复调用;第 8 章硬件光追接口的字段设计——实例、基元、重心坐标——与本章 3.2 的命中记录一一对应,届时你会看到本节的结构体直接长在了显卡里。