约 21 分钟技术学习游戏引擎

Games104学习笔记(5)

GAMES104:渲染中光和材质的数学魔法

第 5 讲|主题:Lighting、Materials and Shaders
视频时长:约 2 小时 08 分 36 秒
说明:本文按本地视频的课件和讲解脉络整理,不是逐字稿;时间点均为近似值。 这一讲我几乎是完全听不懂。

一句话理解

实时渲染的目标不是直接、完整地求解光在场景中的所有传播,而是在有限的帧时间内,围绕光照可见性、积分近似和递归光传输三类困难,组合使用 PBR、阴影贴图、预计算全局光照、光照/反射探针、IBL 与 Shader 管理,得到稳定、可控且足够可信的画面。

本讲学习目标

  • 用渲染方程理解“光、材质、Shader”各自负责什么。
  • 说明实时渲染为何难在可见性、积分与间接光,而不只是“算公式很复杂”。
  • 理解 Blinn-Phong、Shadow Map、Lightmap、Light Probe、IBL 与 PBR 的使用边界。
  • 掌握微表面 BRDF 的 D、F、G 三项分别描述什么。
  • 知道大世界阴影与复杂材质为什么会把问题延伸到级联阴影和 Shader 变体管理。

1. 渲染计算由谁参与

视频开头把渲染问题概括为三位参与者:

参与者 关注的问题 在引擎中的对应物
Lighting(光照) 光从哪里来、如何传播、是否被遮挡 光源、环境光、阴影、全局光照数据
Material(材质) 表面遇到光后如何吸收、散射、反射或透射 材质参数、纹理、BRDF/BSDF 模型
Shader(着色器) 如何在 GPU 上组织大规模并行计算 Vertex/Pixel/Compute Shader、资源绑定与变体

一个有用的分工视角是:光照提供入射能量,材质规定响应规律,Shader 把这套规律变成可执行的 GPU 程序。

2. 渲染方程:所有近似的起点

课程以 Kajiya 的渲染方程为主线:

$L_o(x,\omega_o) = L_e(x,\omega_o) + \int f_r(x,\omega_o,\omega_i)\cdot L_i(x,\omega_i)\cos\theta_i,d\omega_i$

可以先按含义阅读,而不是急于推导:

  • L_o:从点 x 朝观察方向 ω_o 离开的辐亮度,也就是最终进入相机的光。
  • L_e:该点自身发出的光,例如发光材质。
  • L_i:从入射方向 ω_i 到达该点的光。
  • f_r:BRDF,描述表面如何把入射光分配到出射方向。
  • cosθ_i:斜入射的有效投影面积变小。
  • 积分:把半球上所有可能入射方向的贡献加总。

2.1 三个核心挑战

课件将实时求解拆成三个问题:

  1. 可见性:给定一个入射方向,如何知道该方向的光能否抵达当前点?
  2. 积分:半球积分涉及连续方向,怎样以可承受的代价估计它?
  3. 递归:L_i 本身又可能来自其他表面的反射、散射,渲染方程具有递归性。

这三个问题分别推动了不同技术的发展:阴影解决一部分可见性,采样/解析近似解决积分,预计算和实时 GI 技术处理多次弹射或其近似。

2.2 不要把“真实”误解为单一算法

真实感来自一组近似之间的一致性:直接光要有遮挡,材质要有合理能量分配,间接光要补足环境贡献,最终还要满足帧时间与显存预算。某个局部算法再精确,若与其余环节的假设不一致,画面仍会显得不可信。

3. 从简单光源到 Blinn-Phong

3.1 简单光源组合

在较传统的实时光照中,常把光拆为:

  • 主光源:方向光、点光或聚光灯,负责较明确的方向性和高光。
  • 环境光:补足低频、全方向的环境亮度。
  • 附加局部光:只影响局部区域,用于丰富重点对象或室内照明。

这种拆法适合 GPU 的并行计算,但它隐含了一个重要前提:入射光分布被大幅简化了。

3.2 Blinn-Phong 的价值与局限

Blinn-Phong 通过环境光、漫反射和高光等项,提供了直观而廉价的外观控制。它在早期实时渲染里非常重要,但课程明确指出其限制:

  • 不严格能量守恒:反射出的能量可能不受物理约束。
  • 与光线追踪等方法衔接不稳定:当多个反射路径叠加时,误差和噪声更突出。
  • 复杂真实材质难以统一表达:仅靠漫反射颜色与高光指数难以稳定描述金属、粗糙表面等。

因此,PBR 不是“让画面自动变好”的开关,而是用更一致的材质与光照假设,减少不同光照条件下的外观漂移。

4. 阴影:先回答“光能不能到”

4.1 Shadow Map 的基本思路

阴影贴图从光源视角先渲染场景深度。随后在主视角着色时,将当前表面点变换到光源空间,比较它到光源的深度与阴影贴图中记录的最近深度:

  • 当前深度更大:点位于遮挡物之后,通常认为处于阴影中。
  • 深度接近或更小:光可见,允许直接光照贡献。

它把“向光源发射光线”的可见性查询,转换成一次深度纹理查询,因此适合实时 GPU。

4.2 Shadow Map 的两个根本限制

课程特别强调:

  • 分辨率受限于纹理:一张有限大小的 Shadow Map 必须覆盖一定范围,远近区域会发生采样密度失配。
  • 深度精度也受限于纹理/投影:量化与深度比较会导致 acne、peter-panning 等伪影,需要 bias 等策略权衡。

阴影问题不是单纯“提高贴图分辨率”即可解决;覆盖范围、投影方式、过滤方式、稳定性和性能需要一起考虑。

4.3 廉价、鲁棒、易修改

在阴影之后,视频用“Cheap, Robust and Easy Modification”概括游戏渲染的工程目标。这里的意思不是忽视质量,而是:一个可量化、稳定、能被内容团队调参的近似,常比理论上更完整却难以落地的算法更适合引擎。

5. 预计算全局光照:把昂贵问题移到离线阶段

直接光只处理“光源到当前点”的一次可见性;而墙面、地面、天空等互相反射的能量属于间接光。实时计算它通常成本很高,于是课程转向 Pre-computed Global Illumination。

5.1 为什么要预计算

预计算的核心取舍:

  • 在内容制作或烘焙阶段,用较长时间计算复杂光照。
  • 运行时读取压缩后的结果,以很低成本近似间接光。

适用前提是场景中至少有一部分几何、材质或灯光保持稳定;若世界频繁变化,预计算结果会失效或需要额外补偿。

5.2 用球谐函数表示低频间接光

间接光本质上是“球面方向上的函数”。课程以 Fourier Transform 引出球谐函数(Spherical Harmonics, SH):它用一组球面基函数表示方向分布。

关键直觉:

  • 复杂的高频光照分布需要更多系数。
  • 漫反射会把入射光做余弦卷积,高频细节被显著平滑。
  • 因此,对于漫反射间接光,低阶 SH 往往已经足够实用。

这也解释了为何 SH 很适合存环境漫反射,却不擅长保存锐利镜面反射或细碎遮挡。

5.3 卷积与运行时着色

若能把光照分布与材质响应分别编码,运行时就可以通过系数运算完成近似积分。课件给出“Store and Shading with SH”的思路:将少量 SH 系数编码进纹理或探针数据,运行时以简单的 RGB/RGBA 纹理读取完成漫反射着色。

要点不是记住某一种打包格式,而是理解:把高成本半球积分转成少量可查表、可点乘的数据,是实时渲染中常见的降维策略。

6. Lightmap 与 Light Probe:把间接光存在哪里

6.1 Lightmap

Lightmap 将静态几何上的光照结果烘焙到纹理中。使用时,网格需要一套用于烘焙的 UV 展开;多个物体的图块通常会被打包进 atlas。

优点 局限
运行时非常高效 烘焙时间长、内容迭代成本高
可保存丰富的静态场景 GI 细节 主要适用于静态场景与静态光
着色阶段只需采样纹理 占用包体与 GPU 存储,受 UV 与图块分配影响

视频还指出 Lightmap 可与短程、高频效果(如局部细节类补偿)配合,而非独自承担全部光照。

6.2 Light Probe

Light Probe 不把光照绑定到某块表面 UV,而是在空间中放置采样点,存储该位置的环境照明信息。动态物体可从附近探针插值,获得与静态环境较一致的漫反射和环境色。

它的优势是:

  • 运行时高效。
  • 能用于静态环境中的动态物体。
  • 同时可承载漫反射与一定的镜面环境信息。

它的局限也很明确:探针需要预先布置或生成,难以表达极高频的 GI、精确硬阴影,且在复杂遮挡边界附近容易出现泄漏或过度平滑。

6.3 Reflection Probe

反射探针通常存储周围环境的立方体贴图或其预过滤版本,为具有一定粗糙度的镜面反射提供环境来源。可以把它理解为“从某个空间位置看到的环境”,而不是屏幕空间的即时反射。

7. PBR:用微表面统一描述材质

7.1 微表面 BRDF 的结构

课程采用微表面模型理解镜面反射。一个常见写法为:

$f_r = f_{\mathrm{diffuse}} + f_{\mathrm{specular}}$

其中镜面部分通常可概括为:

$f_{\mathrm{specular}} = \frac{D(h)F(v,h)G(l,v,h)}{4(n\cdot l)(n\cdot v)}$

不必执着于符号形式,先记住三个物理/几何含义:

项 名称 回答的问题
D Normal Distribution Function,法线分布函数 有多少微表面朝向半程向量,能把光反射到观察方向?
F Fresnel,菲涅耳项 在这个视角下,有多少能量发生反射而非透射?
G Geometric Attenuation,几何衰减/遮蔽项 微表面之间是否互相遮蔽或掩蔽?

7.2 粗糙度真正控制什么

粗糙度不是“把高光调模糊”的纯美术参数。它改变微表面法线的分布:

  • 粗糙度低:法线更集中,反射峰更尖锐。
  • 粗糙度高:法线分布更分散,镜面能量在更大角域中展开。

因此,粗糙度会同时影响高光宽度、环境反射的模糊程度以及预过滤环境贴图应选择的 mip/层级。

7.3 菲涅耳效应

菲涅耳项说明:观察方向越接近掠射角,表面越倾向反射环境。水面、金属边缘、塑料边缘在斜看时更亮,并非单纯“加一圈边缘光”,而是反射比例随角度变化的自然结果。

7.4 Disney Principled BRDF 的工程价值

课程引用 Disney 的 Principled BRDF 思想:材质参数应优先做到直观、范围合理、边界稳定、组合后仍可信。

对引擎/工具设计的启发是:

  • 参数不要只为公式服务,也要为内容创作者服务。
  • 不同参数的有效范围应该有清晰约束,避免轻易产生不合理结果。
  • 允许材质族覆盖多种外观,但不能把每种特殊材质都硬塞进同一套简单假设。

8. PBR 工作流:Specular-Glossiness 与 Metallic-Roughness

8.1 Specular-Glossiness

在 Specular-Glossiness 工作流中,通常分别保存:

  • Diffuse/Base 颜色。
  • Specular 反射颜色。
  • Glossiness(与粗糙度方向相反的参数)。

它具有较直接的控制力,但参数之间的约束更依赖内容规则,容易产生不符合材料常识的组合。

8.2 Metallic-Roughness

Metallic-Roughness 工作流用金属度与粗糙度组织大多数常见材质:

  • 非金属:以漫反射为主,镜面反射通常由介电材料的基础反射率控制。
  • 金属:漫反射显著减弱,镜面反射颜色更多来自基色。
  • 粗糙度:控制微表面分布及环境反射的预过滤程度。

它的价值在于减少不合理参数组合,使材质库、导入管线和运行时 Shader 更容易保持一致。

8.3 sRGB 与线性空间

课件在工作流图中区分了 sRGB 与 Linear。学习时应牢牢记住:

  • 颜色贴图通常按 sRGB 编码/采样后转换到线性空间参与计算。
  • 粗糙度、金属度、遮罩等“数值数据”通常应按线性值读取。
  • 光照累积、BRDF 计算、混合等应在线性空间完成;最后再进行显示编码。

空间混用会使能量、渐变与材质响应看起来不对,即使公式本身没有写错。

9. IBL:让材质真正反射环境

9.1 IBL 的基本困难

Image-Based Lighting(IBL)把环境图作为来自各个方向的入射光。直接对环境图做半球积分需要大量采样,尤其镜面反射还随粗糙度和视角变化,不能在每个像素实时暴力计算。

9.2 把积分拆成可预计算部分

视频给出常见的拆分思路:

  • Diffuse Irradiance Map:将环境图卷积为低频漫反射辐照度。
  • Pre-filtered Environment Map:按照粗糙度预过滤环境图,为镜面反射提供不同模糊层级。
  • BRDF LUT:预计算部分与视角、粗糙度相关的 BRDF 积分项。

运行时,材质只需根据法线、反射方向、粗糙度和视角,从这些预计算资源中采样并组合。其本质仍然是:用存储和预处理换取帧内时间。

9.3 IBL 与 PBR 是一对系统设计

PBR 给出表面如何响应入射光;IBL 给出环境入射光的近似。两者必须使用一致的颜色空间、粗糙度定义、预过滤规则和能量约束。只换一个 PBR Shader 而没有合理环境光,材质往往会显得灰、暗或像在真空中。

10. 大世界阴影:Cascade 与软阴影

10.1 Cascade Shadow Map

方向光需要覆盖很远的可见区域。一张 Shadow Map 同时覆盖近景与远景时,近景纹素密度不够,远景又浪费精度。级联阴影的解决方式是:

  1. 将相机视锥划分成多个深度区间。
  2. 为每个区间分别渲染 Shadow Map。
  3. 像素着色时,根据深度选择对应级联。

这样可以把更多分辨率分配给近处画面,符合人眼和屏幕空间的需求。

10.2 级联交界的处理

相邻级联的投影与分辨率并不完全一致,交界处容易出现突然变线、闪烁或亮度断层。课程展示了在重叠区域进行混合的思路:不要只依据“某一像素当前属于哪一层”硬切换,而应在过渡带平滑插值。

10.3 PCSS / VSSM 的位置

课件还讨论了软阴影近似,例如 PCSS(Percentage-Closer Soft Shadows)通过 blocker 与 receiver 的相对几何关系估计过滤半径;VSSM 等方法则将可见性近似转换为更易过滤的数据形式。

共同目标是让阴影边缘随遮挡关系呈现合理软化,而不是恒定宽度的硬边。代价通常是更多采样、过滤成本和稳定性处理。

11. 课程中归纳的 AAA 渲染组合

约 103 分钟处的总结页给出一种常见组合:

Lightmap + Light Probe
PBR + IBL
Cascade Shadow + VSSM

这不是唯一渲染架构,而是一组职责互补的工程拼图:

  • 静态环境的高质量间接光交给 Lightmap。
  • 动态对象的环境过渡交给 Light Probe。
  • 物体外观统一到 PBR 材质模型。
  • 环境反射和漫反射环境光由 IBL 补足。
  • 主方向光的大范围遮挡由级联阴影处理,并以软阴影技术改善边缘。

理解“谁负责哪一部分”比死记每个缩写更重要。

12. 实时 GI、复杂材质与 Shader Management

12.1 GPU 能力增长带来的选择

视频后段提到 Compute Shader、Mesh Shader、Ray Tracing Shader 以及更现代的 GPU/图形 API。硬件演进扩大了可行算法的边界,例如屏幕空间 GI、基于距离场/体素的 GI、光追 GI 等。

但“可以实时”不等于“总该实时”。引擎仍要根据平台、场景动态程度、内容规模、帧预算和画面目标,在烘焙、探针、屏幕空间近似与更昂贵方法之间组合。

12.2 复杂材质不能被一个简单模型完全覆盖

课程用头发、皮肤等例子提醒:标准 PBR 对普通不透明表面很有效,但对各向异性头发、次表面散射皮肤等现象,需要 BSDF、BSSRDF 或额外的专用近似。正确做法不是否定统一材质模型,而是承认它有适用域,并为特殊材质保留扩展路径。

12.3 Uber Shader 与变体爆炸

Shader Management 是引擎中容易被低估的系统问题。一个通用的 Uber Shader 会依据:

  • 光照类型与数量;
  • 材质特性(法线贴图、金属度、透明、皮肤等);
  • 渲染通道;
  • 平台与质量等级;
  • 预处理宏;

生成大量 Shader Variant。课件展示的真实游戏例子中,少量 Uber Shader 可扩展为数量极大的运行时着色器组合。

因此,引擎需要管理:变体裁剪、离线编译、缓存、按需加载、预热、回退路径和统计诊断。Shader 变体不是“美术参数多一点”的问题,而是构建时间、包体、内存、加载卡顿与渲染状态切换共同组成的系统成本。

13. 复习用速记

13.1 一条因果链

渲染方程难以直接实时求解
→ 可见性用 Shadow Map 等方法近似
→ 半球积分用解析、采样、SH、环境卷积等方式降维
→ 间接光用 Lightmap/Probe/IBL/实时 GI 分担
→ 材质用 PBR 保持光照变化下的一致性
→ 规模化实现依赖 Shader 变体与资源管理。

13.2 最容易混淆的三组概念

概念 主要存什么 主要服务谁
Lightmap 静态表面上的烘焙光照 静态几何
Light Probe 空间采样点的环境光照 动态物体、跨区域过渡
Reflection Probe 某位置周围的环境反射 镜面/粗糙镜面反射
概念 解决的主问题
PBR 表面如何合理响应光
IBL 环境从各方向提供多少入射光
Shadow Map 光源到表面是否被遮挡
微表面项 直觉
D 朝向恰好合适的微面有多少
F 当前角度反射比例有多高
G 微面之间有多少互相挡住

14. 自测题

  1. 渲染方程中 L_e、L_i、L_o 分别表示什么?
  2. 为什么课程把实时渲染困难归为可见性、积分和递归?
  3. Shadow Map 如何把可见性查询转换为纹理比较?
  4. Shadow Map 的分辨率问题和深度精度问题为何是两类不同问题?
  5. 为什么低阶 SH 适合表示漫反射环境光,却不擅长锐利镜面反射?
  6. Lightmap 与 Light Probe 分别适合哪些对象?
  7. 在微表面 BRDF 中,D、F、G 各自描述什么现象?
  8. 粗糙度为何会影响预过滤环境贴图的采样层级?
  9. 为什么颜色贴图与粗糙度贴图不能以相同的色彩空间规则读取?
  10. IBL 中的 irradiance map、prefiltered environment map、BRDF LUT 如何分工?
  11. 级联阴影为什么比单张超大 Shadow Map 更适合方向光的大世界场景?
  12. 复杂材质为什么需要在统一 PBR 之外保留专用模型?
  13. 什么是 Shader Variant Explosion?它会影响哪些工程指标?

15. 术语表

术语 含义
BRDF 双向反射分布函数,描述不透明表面从入射方向到出射方向的反射分配
BSDF 更一般的散射函数,除反射外还可包含透射
BSSRDF 描述次表面散射等“光在表面下方传播后再离开”的现象
PBR 基于物理的渲染;强调材质和光照假设的一致性
Shadow Map 从光源视角存深度,并用深度比较判断遮挡的技术
Lightmap 绑定到静态几何 UV 的烘焙光照纹理
Light Probe 存储空间采样点环境光的结构,常用于动态物体
Reflection Probe 存储某位置周围环境反射信息的探针
SH 球谐函数;用于压缩和表示球面方向函数的基函数系统
IBL 基于图像的光照,将环境图作为入射光源
NDF 法线分布函数,微表面模型中的 D 项
Fresnel 描述反射率随观察/入射角变化的效应
CSM 级联阴影贴图,将视锥分段以提高近处阴影分辨率
PCSS 近似软阴影的一类方法,根据遮挡物与接收面关系调整过滤范围
Uber Shader 通过大量分支、宏或变体覆盖多种材质/光照条件的通用着色器

17. 参考资料