离线可学 · 无需安装
GAMES101 × UNREAL ENGINE 5

看懂一帧画面,
从第一个像素开始。

给 UE 客户端初学者的图形学速成路线。把公式变成看得见的实验,把引擎术语连成完整的渲染过程,再用项目和追问检验理解。

LIGHT01 / GEOMETRY02 / PIXELSp → M → V → P
A FRAME IS A SERIES OF DECISIONS.
SELF-PACED / HANDS-ON / INTERVIEW-READY
14 核心学习单元
9 可调实验与流程探索
36 道题 · 即时解析
28–40h 建议首轮投入,含项目
00

先明确:你要学会什么

学习导航 · 不要求先学完高数 · 建议 20 分钟

你已经会在 UE 里放模型、调材质、打灯。现在要回答的是:这些操作怎样变成屏幕上的颜色,以及哪里会变慢。

第一层 · 讲得通

从一个点到一个像素

说清坐标变换、覆盖判断、深度测试、纹理采样和光照计算之间的关系。

第二层 · 找得到

把概念放回 UE

分清 Base Pass、GBuffer、光照、透明、后处理,知道四个 UE5 系统分别解决什么。

第三层 · 拿得出

用证据写进简历

完成对照场景和性能记录,能解释一次优化的原因、收益、画质代价与适用条件。

本文的约定:公式采用列向量;教学相机默认朝 −Z、Y 向上。UE 世界坐标采用自己的约定,第 02 章会对照。引擎部分以 UE 5.6 官方文档、桌面 Deferred 为明确参考,适用于建立 UE5 概念;移动端、Forward、Substrate、实验特性与不同版本要另查实际配置。图示均为本页原创示意,浏览器实验不是 UE 渲染结果。

两条路线,你可以先跑一遍,再做扎实

6–8 小时概览:读每章开头、做实验、答随堂题,先搭起知识结构。28–40 小时首轮:再补关键课程片段与项目。零数学或零 C++ 基础需要更多时间;完成阅读并不等于已经能写渲染器。

DAY 01 · 3–4h

空间与相机

01–02 章;GAMES101 L02–04。手算点积与一个 MVP 例子。

DAY 02 · 4–5h

三角形到像素

03–05 章;L05–06、08–09。完成覆盖、深度、过滤实验。

DAY 03 · 4–5h

颜色从哪来

06–08 章;L07、12–17 相关片段。区分材质、阴影、GI。

DAY 04 · 3–4h

映射 UE

09–11 章;在编辑器里看 Wireframe、Buffer Visualization。

DAY 05 · 4–6h

第一次测量

12 章;搭实验场景、固定条件、定位最大 GPU 开销。

DAY 06 · 6–10h

做出项目证据

13 章;完成三个对照实验、保存捕获与说明文档。

DAY 07 · 4–6h

闭卷复盘

14 章;10 题测验、口述追问、修改项目说明与简历。

NEXT · 持续练习

补齐代码能力

选做 GAMES101 作业 1–3,再做 5–7;实现与解释都要自己完成。

GAMES101 要不要从头全部看完?

这门课系统覆盖光栅化、几何、光传播与动画模拟,本页围绕 UE 客户端所需的渲染主线重新编排。遇到概念卡住再回看对应讲次:L02–09 打基础,L12 阴影、L13–17 光追与材质是重点;L10–11 几何、L18–22 进阶外观/相机/颜色/动画可在首轮后补全。这里的时长是学习计划估计,不能代替完整课程的深度。

课程结构核验:GAMES101 官方课程主页课程官方录像合集

01

向量:让“方向”变成可计算的量

GAMES101 L02 · 建议 45 分钟 · 先会解释,再记公式

点回答“在哪里”,向量回答“朝哪里、走多远”。玩家在 A,目标在 B,那么 B − A 是指向目标的向量。长度是距离,除以长度就得到只保留方向的单位向量。

v = B − A |v| = √(vₓ² + vᵧ² + v_z²) normalize(v) = v / |v| (v ≠ 0;零向量必须单独处理) a · b = aₓbₓ + aᵧbᵧ + a_zb_z = |a||b| cos θ

点积:两个方向有多一致?

两个单位向量的点积就是夹角余弦:同向为 1,垂直为 0,反向为 −1。正负号可以判断前后半球;值的大小可决定受光强弱。

例:法线 n=(0,0,1),指向光源的方向 l=(0,0.6,0.8),两者都归一化,因此 n·l=0.8。相同光源下,这个面接收的投影通量是正对光源时的 80%。

叉积:求垂直方向和面积

a×b 垂直于 a、b 所在平面,长度是它们张成的平行四边形面积。三角形面积是 |(B−A)×(C−A)|/2。

交换顺序会翻转方向。网格顶点绕序影响正反面,法线影响着色;“法线朝前”与“背面剔除保留该面”不是同一个规则。

实验 01 / 转动光线,观察点积
夹角增大时余弦变小,超过 90 度后单面 Lambert 漫反射取零。

试 0°、60°、90°、120°。这里 l 指“表面指向光源”,与光实际传播方向相反。

把光束想成一把筷子:斜着照会摊到更大的面积上,单位面积收到的光就更少。

矩阵:把一组基向量换成另一组

矩阵并不只是数字表。用列向量时,矩阵的每一列告诉你原来的 X/Y/Z 基方向变到哪里。矩阵乘法能把缩放、旋转串起来;平移需要下一章的齐次坐标。

落到 UE:用 Normalize(Target − Position) 得到方向;用 Dot(Forward, Direction) 判断目标是否在前方。做光照前,法线 n 和光向量 l 必须处在同一坐标空间,否则点积的结果没有你期望的几何意义。

对应学习:官方 L02 讲义入口

继续:坐标变换 →
02

变换:一个顶点怎样走到屏幕上

GAMES101 L03–04 · 建议 70 分钟

把一个模型放进场景,就像把一把椅子搬进摄影棚。模型坐标描述椅子自身,世界坐标描述它在摄影棚里的位置,相机坐标描述它相对镜头的位置;投影决定它在照片上有多大。

模型空间Local / Object
M →
世界空间World
V →
相机空间View
P →
裁剪空间Clip · 仍有 w
÷w →
NDC → 屏幕标准化 → Viewport
p_clip = P · V · M · p_local ← 列向量约定,右边先执行 p_ndc = (x_clip / w_clip, y_clip / w_clip, z_clip / w_clip) V = inverse(CameraWorldTransform)

为什么多出一个 w?

把点写成 (x,y,z,1),方向写成 (x,y,z,0)。平移矩阵最后一列是位移 t,乘点时会加上 t,乘方向时会被 0 消掉。于是平移也能参与统一的 4×4 矩阵运算。

透视矩阵产生的 w 携带与视深相关的信息;后续除以 w 才形成“远处更小”。乘投影矩阵后还没完成透视除法。

顺序为什么不能随便换?

点 (1,0) 先放大两倍再向右移 3,得到 (5,0);先平移再缩放得到 (8,0)。因此一般 TS ≠ ST。

相机右移,静止物体在相机坐标中左移,所以视图矩阵是相机世界变换的逆。矩阵的内存行主序/列主序与数学上采用行向量/列向量是两个问题。

透视的本质:相似三角形

取正的相机距离 d = −z_view、像平面尺度 f,则 x′=fx/d,y′=fy/d。同样高的物体,距离翻倍,投影高度减半。视角 FOV 增大,f=1/tan(FOV/2) 变小,看见的范围更广,同一物体更小。正交投影没有这个距离缩放。

实验 02 / 一只真正经过投影计算的线框立方体
透视投影使远处缩小,正交投影中距离不改变尺寸。

切到正交后改变距离。正交相机的可视高度固定为 6 个单位,FOV 对它不生效。

采用右手教学相机、Y 向上、−Z 朝前;这是数学演示,与 UE 世界轴的命名不同。

面试容易漏掉的两步

先在裁剪空间裁剪,再做透视除法。跨过近平面的三角形不能简单地把某个顶点“删掉”;需要裁出新的边界,否则除以接近零或负的 w 会产生异常投影。之后 NDC 经视口变换到像素位置。深度范围依图形 API 和配置而变,不应只背一种范围。

法线不是普通位置。有非均匀缩放时,法线要用线性变换 A 的逆转置 (A⁻¹)ᵀ 再归一化。原因是仍需满足 n′·t′=0,才能与变换后的切线垂直。只有纯旋转/适当统一缩放时才可简化。

UE 对照:默认世界是左手系,+X 前、+Y 右、+Z 上,长度默认厘米。GAMES101 常用相机朝 −Z 的教学约定;不要复制公式时漏了轴转换。行/列向量、手性、NDC 深度与 reversed-Z 要分别核对,不能由“左手系”推导出所有答案。

GAMES101 L04:变换讲义Epic:坐标与单位

继续:光栅化 →
03

光栅化:哪些像素属于这个三角形

GAMES101 L05–06、08 · 建议 60 分钟

光栅化把连续三角形转换为离散采样点上的覆盖信息。它回答“这片表面影响哪些位置”,着色才回答“这些位置应该是什么颜色”。一个像素可能被多层表面覆盖,必须继续解决遮挡。

顶点/索引缓冲位置、法线、UV
→
顶点处理输出 Clip 位置
→
裁剪与光栅化覆盖 + 属性插值
→
片元/像素着色计算材质输出
→
深度与混合写入目标缓冲

这是逻辑依赖图。GPU 可做 Early-Z、并行、重排;不能从箭头推断每块硬件的唯一执行时刻。

覆盖判断:看它在每条边的哪一侧

对三角形的每条有向边计算二维叉积符号。如果采样点在所有边的内侧,就被三角形覆盖。只遍历三角形屏幕包围盒可以省下大量工作。

共用边上的点需要一致规则,例如 top-left rule,避免两块三角形既都不画又都重复画。片元是一次潜在贡献,不等于最终像素。

Z-buffer:每个位置记住最近深度

先把深度缓冲设为“最远”。新片元更近才更新深度与颜色。这样不透明遮挡通常不依赖绘制顺序;同深度、精度与状态设置仍会影响结果。

常规例子中 z 小表示近,用 less 比较。UE 常见的 reversed-Z 用近处大、远处小,反转比较方向以配合浮点深度提升精度。它是深度编码策略,不是颠倒物理遮挡。

// 教学伪代码:常规深度;实际 GPU 可提前进行深度测试
for (triangle : triangles)
  for (sample : triangle.boundingBox)
    if (covered(triangle, sample)) {
      z = interpolateDepth(triangle, sample);
      if (z < depth[sample]) {
        depth[sample] = z;
        color[sample] = shade(interpolateAttributes(triangle, sample));
      }
    }
实验 03 / 亲自切换深度规则
深度测试决定重叠区显示哪个三角形。

B 距离固定为 5。这里用线性映射演示比较方向;实际透视深度通常不是线性距离。

相同距离时本实验使用严格比较,先绘制的 A 胜出;真实项目应避免依赖共面片元的偶然结果。

为什么透明物体比较麻烦?

不透明表面只留下最近层通常就够了;透明要混合多层颜色。普通 alpha 混合是 C = αC_front + (1−α)C_back,顺序不同结果不同。常见做法是保留深度测试、关闭透明深度写入,并按远到近画;物体互相穿插时简单排序仍不够。

UE 里的三个概念:Opaque 是实心;Masked 根据阈值丢弃片元,保留部分通常像不透明表面写深度;Translucent 需要透明混合和专门路径。Early-Z 可以在昂贵着色前拒绝被遮挡片元,但 discard、深度写出与副作用等会影响可用优化。

Microsoft:光栅化阶段Direct3D 规范:插值、深度与混合

继续:采样 →
04

采样:锯齿不是“边缘不够模糊”

GAMES101 L05–06 · 建议 45 分钟

屏幕像一张格子纸。真实图像连续变化,像素只有有限个;如果每格只看一个点,一条很细的线可能刚好全被漏掉。高频细节无法由低密度样本区分,会伪装成错误的低频形状,这就是混叠 Aliasing。空间上是锯齿、摩尔纹;时间上是闪烁、车轮倒转。

一个像素理想上代表一定区域与时间内的滤波结果,不是一个数学点。解决思路是在采样前控制高频,或取得更多有效样本。事后模糊可以遮盖部分瑕疵,却无法还原从未采到的信息。Nyquist 的“超过最高频率两倍”以带限信号为前提,三角形硬边并不天然带限。

实验 04 / 数一数,一个像素覆盖了多少
每格采样数增加后,三角形边缘得到部分覆盖灰度。

慢慢移动边缘:1 点采样会跳变,多点覆盖会平滑过渡。本例只计算常量色三角形的覆盖,不测量 GPU 代价。

白线为连续三角形边界,绿色亮度为该像素内部被覆盖样本的比例。它展示超采样覆盖积分的直觉。

方法样本来自哪里优势与代价
SSAA更高分辨率完成渲染,再过滤缩小覆盖几何与着色的多种混叠,通常很贵
MSAA像素内多个覆盖/深度样本;着色通常复用擅长几何轮廓;不能保证消除高光、纹理闪烁,不等于所有着色执行 N 次
FXAA单帧最终图像中的边缘轻量、可能模糊细节,没有多帧恢复能力
TAA抖动后的当前帧 + 重投影历史提高有效采样量;依赖运动/深度和历史剔除,可能拖影、变软
TSR较低分辨率当前帧 + 时域信息,重建更高输出分辨率同时做时域抗锯齿与超分;会有自身成本与历史失效问题
引擎映射:Deferred 的多张 GBuffer 让 MSAA 的存储和着色处理复杂,UE 的桌面 MSAA 主要在 Forward 路径使用。TAA/TSR 则利用跨帧信息。选哪种要同时考虑画质、运动表现和平台预算。

PBRT:采样与图像重建Epic:Forward 与 MSAA

继续:纹理 →
05

纹理:给表面一个能查询的数据表

GAMES101 L08–09 · 建议 60 分钟

纹理不只是一张照片,它是 GPU 上可采样的二维/三维数据。UV 是表面到纹理的地址,texel 是纹理中的格子,pixel 是屏幕中的格子。两者数量和方向通常不一致。

三角形内部的 UV 从哪来?

给三个顶点属性,再按重心坐标混合:P=λ₀A+λ₁B+λ₂C,且 λ₀+λ₁+λ₂=1。在三角形内部权重非负。例如权重 (0.2,0.3,0.5),UV 顶点为 (0,0)、(1,0)、(0,1),平面线性混合得到 (0.3,0.5)。

透视投影后的属性校正(λ 为屏幕重心权重): a = (λ₀a₀/w₀ + λ₁a₁/w₁ + λ₂a₂/w₂) / (λ₀/w₀ + λ₁/w₁ + λ₂/w₂)

屏幕上等距离不代表空间中等距离。假设一条边两端的属性 a 分别为 0 和 1,w 分别为 1 和 2,屏幕中点的正确值是 (0.5×0+0.5×1/2)/(0.5/1+0.5/2)=1/3,不是 1/2。直接线性插值 UV,会让斜着的地板纹理扭曲。

放大:从少量 texel 重建

最近邻直接取一个格子,产生块状边缘;双线性对相邻 4 个 texel 按距离加权,放大更平滑。它没有恢复不存在的真实细节。

缩小:一个像素覆盖很多 texel

只取 4 个点可能仍漏掉大片区域,产生闪烁。Mipmap 预先把纹理逐层低通过滤并缩小,运行时按纹理足迹选层;三线性在相邻两层的双线性结果之间再插值。

实验 05 / 高频条纹为什么会“倒着变粗”
高频条纹在单点采样下出现伪造低频;区域平均接近灰色。

横向只有 96 个屏幕样本。超过 48 周期后会混叠。对比移动时上下两行的稳定性。

上:单点采样。下:对正弦条纹做像素宽度的精确盒式积分,说明预过滤原理;不是完整 Mipmap 或各向异性算法。

一条完整二维 Mip 链在同格式、忽略对齐时占基础层约 1+1/4+1/16+…=4/3 的存储。用额外约三分之一存储换取稳定性与采样效率。斜看地板时足迹是细长形,各向异性过滤沿长轴增加采样,减少普通 Mip 过度模糊。

法线贴图为什么看起来有凹凸,却没有改变轮廓?

常见切线空间法线贴图把方向编码进 RGB,解码后借助 TBN(切线、双切线、法线)转换到着色使用的空间。它改变“如何反光”,不会直接移动三角形顶点。轮廓、自遮挡、碰撞想真正改变,需要几何或其他专门技术。

UE 贴图检查顺序:Base Color 等颜色贴图通常使用 sRGB 解码;Roughness、Metallic、AO 等数值数据通常关闭 sRGB;法线使用正确 Normalmap 导入/压缩设置,并检查切线基与绿色通道约定。把数据当颜色转换,会改变它的数值含义。

Microsoft:纹理过滤Direct3D:透视属性插值规范GAMES101 L08–09 入口

继续:光照与材质 →
06

光照:材质不是颜色,而是对光的响应

GAMES101 L07、15、17 · 建议 90 分钟

同一块红塑料,在暗室里看不见,白灯下呈红色,掠射角又会出现白色反光。最终颜色 = 入射光 × 表面如何散射 × 可见性,还要经过相机曝光和显示转换。Base Color 只是输入之一。

先弄懂三种“光的量”

辐射通量 Φ

单位时间的光能量,单位 W。像“水管每秒流多少水”。

辐照度 E

单位面积收到的通量,单位 W/m²。像“地面每平方米收到多少水”。

辐亮度 L

按方向、按投影面积计量的光,单位 W/(m²·sr)。像“沿镜头这条方向看过去有多亮”。

sr(球面度)描述方向在空间中占多大范围。不要把方向量和总能量混为一谈。游戏常用 RGB 近似光谱;“用三个颜色通道”是工程表示,不表示光只有三种波长。

第一步:Lambert 漫反射

L_o = (ρ / π) · E_⊥ · max(0, n·l) ρ:漫反射率(RGB);E_⊥:正对该光源时的辐照度;n、l 都归一化

余弦项负责斜着照会变暗;ρ/π 是 Lambert BRDF,除以 π 才让整个半球反射能量与反射率一致。理想点光源的辐照度还随距离平方衰减;距离翻倍,其他条件相同约变为 1/4。方向光则是另一个建模假设。

第二步:从高光公式走到微表面

Blinn–Phong 用 h=normalize(l+v),再用 max(0,n·h)^p 做高光,p 越大越集中。它是理解“看向哪里影响反光”的好起点,但不能直接当成 UE 的完整 PBR 模型。

BRDF,双向反射分布函数,描述从方向 l 来的光有多少被反射到方向 v。它不是灯光,不是纹理,也不直接等于最终颜色。物理合理模型通常满足非负、互易、能量守恒。微表面模型把看似平滑的表面想成许多微小镜片。

f_spec(l,v) = D(h) · F(v,h) · G(l,v) / [4(n·l)(n·v)] D:微表面朝向分布 F:Fresnel 角度反射比例 G:微表面遮挡/掩蔽 常见 Fresnel 近似:F = F₀ + (1−F₀)(1−v·h)⁵

粗糙度改变微镜片方向的分散程度,所以高光会变宽、峰值常降低;它不是“把反射直接关掉”。Fresnel 解释很多非金属在掠射角看起来更反光。几何遮挡项 G 管的是微表面互相挡住,和物体投到地上的阴影贴图不是同一个尺度的问题。

实验 06 / GGX 材质球:改变粗糙度与金属度
粗糙度控制高光扩散,金属度改变反射颜色与漫反射分配。

先观察高光宽度,再切换金属。没有环境反射的金属暗部可能很暗,别靠提高 Base Color 来补灯光问题。

本页在 CPU 上计算简化 Cook–Torrance/GGX、Schlick Fresnel 与 Smith 几何项,使用单方向光、少量漫反射环境项和 Reinhard 映射;没有 IBL、GI 或 UE 的完整材质实现。粗糙度下限 0.05 用于数值稳定。

UE 常见材质输入你应该理解的含义常见误解
Base Color非金属的漫反射颜色;金属工作流中也用于有色镜面反射不是含阴影和高光的最终截图
Metallic纯净均匀表面通常用 0 或 1;混合/过渡可有中间值不是“越大越高级、越亮”
Roughness控制微表面分布,改变反射清晰度和高光宽度粗糙金属仍有反射,不自动变成 Lambert 材质
Specular常规 UE 非金属工作流调节 F₀;默认 0.5 对应约 4% 法向反射0.5 不是反射 50% 入射光;Substrate 等另看具体模型
Normal改变着色法线不会自动改变轮廓或碰撞
Emissive输出自发光,可大于 1亮在画面里不保证所有配置下都稳定照亮周围
为什么不能无限叠加漫反射和高光?

反射出去的能量不能凭空超过收到的能量。镜面部分拿走了一部分入射能量,漫反射要相应减少;纯金属的可见外观主要由有色镜面反射描述。本实验用简单的能量分配,真实多次微表面散射与 UE 特殊着色模型更复杂。

PBRT:辐射度量PBRT:BRDF 与表面反射Epic:PBR 材质参数

继续:阴影与颜色 →
07

阴影与显示:算对光,还要看对光

GAMES101 L12、19–20 · 建议 60 分钟

Shadow Map:站到灯的位置,再看一次

第一次从灯的视角渲染深度,记录灯能直接看见的最近表面;第二次从相机渲染,把表面点变换到灯的空间,比较它与阴影图里的深度。如果它比灯看见的那一层更远,说明中间有遮挡。

灯的位置遮挡物直接可见被遮挡的 P灯眼里的深度比较阴影图:记录最近深度 dₛ当前点:转换得到深度 dₚ若 dₚ > dₛ + bias → 阴影此处使用常规“近小远大”的比较约定
相机问“我能看见这个点吗”,阴影图问“灯能看见这个点吗”。两者都是可见性问题,但观察位置不同。

自阴影条纹:Shadow Acne

采样分辨率和精度误差让本该同一表面相互遮挡。给比较加适当 bias 可缓解;bias 太大又会让阴影与物体分离(Peter Panning)。

软边:PCF

对邻近多个阴影深度比较结果求平均,得到部分可见性。它不是先把深度平均后再比较,也不等于精确求解面光源的真实半影。

为什么一定要在线性空间做光照?

sRGB 是对显示颜色的非线性编码;直接对编码值相加,不对应能量相加。应先解码到线性空间,完成光照和需要线性意义的混合,再做显示编码。常见近似“γ=2.2”方便理解,但精确 sRGB 是分段函数。

线性值 L → sRGB 编码 S: S = 12.92L 当 L ≤ 0.0031308 S = 1.055L^(1/2.4) − 0.055 否则 黑白各 50% 能量:L=0.5 → S≈0.735,而不是 S=0.5
实验 07 / 黑白混合:同一个“50%”,两种亮度
直接平均 sRGB 编码
在线性空间平均后编码

这是黑与白的能量混合示例,不是说所有 UI 插值都必须选择同一种颜色空间;渲染光照要保持能量的线性意义。

HDR → 曝光 → 色调映射 → 显示

HDR 表示场景亮度可以超过普通 0–1 显示范围;曝光决定相机把多少光映射到图像;Tone Mapping压缩高动态范围并形成外观;sRGB 编码负责对应显示。色调映射和 gamma/sRGB 转换不是同一步。

Bloom 让强光向周围扩散,模拟部分成像效果;它不是全局光照。提高曝光能让整张图更亮,不意味着场景多了一盏灯。做材质对照时要固定曝光,否则自动曝光会把不同实验“拉回差不多亮”。

GAMES101 L12 / L20 入口Epic:色调映射与调色Epic:纹理 sRGB 属性(旧版基础说明)

继续:光追与 GI →
08

光追与 GI:把没直达眼睛的光也算进来

GAMES101 L13–16 · 建议 90 分钟

光栅化从三角形出发,寻找它覆盖哪些屏幕位置;光线追踪从一条射线出发,寻找沿途第一个交点。两者可以服务于同一帧:主可见性用光栅,反射或阴影用光追。“用了光追”不代表整幅画面都用路径追踪。

r(t) = o + t·d, t ≥ 0 o:射线起点;d:方向;t:沿射线的参数(d 为单位向量时可对应距离)

从求交到 BVH

最朴素的方法是一条射线遍历所有三角形,N 条射线、M 个三角形就可能要做 N×M 次测试。BVH 把几何组织成一棵包围盒树:先测盒子,没碰到整支都跳过;碰到了再深入子节点,最后才测试三角形。

根包围盒左组:命中右组:跳过三角形三角形几何几何先测范围,再测细节
树质量、射线方向、几何重叠和动态更新会影响代价。不能保证每条射线总是 O(log M)。球形图标在这里代表一组被包围的几何。

直接光、间接光和渲染方程

灯直接照到桌面是直接光;灯先照到红墙,墙再把带红色的光反射到桌面,是间接光。全局光照 GI 关心表面之间的光传输,而不仅是加一个统一“环境亮度”。

L_o(x,ω_o) = L_e(x,ω_o) + ∫Ω f_r(x,ω_i,ω_o) · L_i(x,ω_i) · max(0,n·ω_i) dω_i 看见的光 = 自发光 + 把所有入射方向的贡献加起来

把积分想成“遍历半球所有方向,每个方向的光乘上材质响应和投影因子”。困难在于入射光 L_i 往往来自别的表面,那个表面的光也要继续算,于是问题会递归。可见性可以包含在入射光求值中,或显式作为传输项;无遮挡不应凭空被假定。

路径追踪:随机采样这个积分

无法真的枚举无限方向,就按概率密度 p 抽取几个方向,用 f/p 的平均估计积分。一条相机射线命中后继续采样反弹方向,逐步累积光传输。重要性采样尽量把样本花在贡献大的方向,降低方差。

∫ f(ω)dω ≈ (1/N) Σ f(ωₖ) / p(ωₖ) 独立、有限方差等常见条件下:标准误差约 ∝ 1/√N 想把噪声幅度减半,样本数大约需要增加到 4 倍。

随机采样用噪声换取对复杂积分的估计;实时渲染样本少,会结合降噪、缓存与时域积累。降噪会带来偏差或细节损失;不能把“看起来没有噪点”直接等同于“完全正确”。

容易混淆真正的关系
Ray Tracing / Path Tracing光追是射线求交与传输技术族;路径追踪是一种用随机路径估计光传输的方法
GI / AOGI 求间接光传输;AO 近似局部遮蔽,不计算完整的颜色溢出与多次反弹
SSR / 光追反射SSR 主要依赖屏幕已有信息,屏幕外或被遮住的物体会缺失;场景光追可查询更完整几何,但更贵且仍受实现限制
Lumen / 离线路径追踪Lumen 组合多种实时近似与追踪/缓存来做 GI 和反射,不是无限采样的离线路径追踪器

PBRT:光追成像PBRT:路径追踪器Epic:Lumen 技术细节

继续:几何补全 →
09

补全地图:几何与动画怎样进入渲染

GAMES101 L10–12、21–22 · 首轮理解关系,建议 35 分钟

渲染器不只需要灯和材质,还需要“这一帧的表面在哪里”。几何表示负责描述形状,动画与模拟负责更新形状,然后把结果交给后续可见性与着色流程。

显式几何:直接给出表面

三角网格存顶点与连接关系,方便光栅化;参数曲面用参数 (u,v) 求位置,光栅路径常需离散成三角形。网格细分增加采样与平滑度,简化/LOD 则控制远处细节成本。

隐式几何:用规则定义内外

例如球面 x²+y²+z²−r²=0。便于判断点在内部或外部,求交和提取表面需要相应算法。距离场是有用的空间表示;近似距离场不等于原始三角网格的精确替代。

Bezier:把复杂曲线拆成反复插值

二次 Bezier 用三个控制点 A、B、C:先插值 P=(1−t)A+tB、Q=(1−t)B+tC,再插值 B(t)=(1−t)P+tQ。这就是 de Casteljau 思路。曲线经过首尾端点,中间控制点通常只控制走势,并不一定被穿过。

AB(控制点)Ct=0.5 时的曲线点PQ
“插值”是一种通用工具:控制曲线、动画参数、纹理采样都用到它,但各自的空间与数学含义要明确。

骨骼蒙皮与物理模拟

线性混合蒙皮把绑定姿态顶点乘上多个骨骼的“当前变换 × 逆绑定变换”,再按权重相加:p′ = Σ wᵢ Mᵢ p,通常权重和为 1。它便宜,但关节可能塌陷或出现糖纸扭曲。法线也需随形变处理。

质点弹簧用位置、速度和力更新运动,离散时间步长太大可能让显式积分不稳定。渲染帧率与模拟步长不是必须一一对应。对客户端开发,你首先要知道动画/模拟产生当前几何,运动信息还会影响速度缓冲和时域重建。

UE 关联:传统 Static Mesh LOD、Skeletal Mesh 动画、Nanite 几何细节管理解决不同问题。不要把“开启 Nanite”理解成取代全部动画与网格处理;具体支持范围随版本变化。

GAMES101:几何与动画课程入口

继续:UE 一帧 →
10

拆解 UE 的一帧:谁在算,算出什么

从图形学连接引擎 · 建议 80 分钟 · 桌面 Deferred 概念路径

先分开两条线:CPU 提交工作,GPU 执行工作

Game ThreadCPU:游戏与场景状态
→
Render ThreadCPU:组织渲染工作
→
RHI / RHI ThreadCPU:平台接口与命令
→
GPU执行 Draw / Dispatch

角色移动先更新游戏状态;渲染相关数据传给渲染线程,通过 RHI 抽象连接图形 API,GPU 最终执行。各阶段能处理不同帧、并行重叠,也会因依赖而等待。Render Thread 是 CPU 线程,RHI 不是显卡本身。具体线程启用方式依平台与配置变化。

Draw Call 是发起绘制的命令,不等于一个三角形。一条调用可画很多三角形;一个物体可能因材质分区、深度、阴影等被多次绘制。Shader 是 GPU 程序;Pass 是完成某个目的的一组渲染工作;Render Target 是写入结果的纹理/缓冲。RDG(Render Dependency Graph)组织 Pass 与资源读写依赖,帮助安排资源生命周期和执行,不是一种新的光照公式。

点开每一站:输入 → 处理 → 输出

实验 08 / 一帧流程探索器

这是理解依赖关系的教学路线,不是逐事件捕获。阴影可单独准备,GI/反射/透明/TSR 会交错或分支;Nanite、Substrate、RHI 与版本会改变资源和阶段细节。

Deferred:先记住表面,再给表面打光

想象先填写一张“可见表面信息表”:这个像素的法线、底色、粗糙度、金属度是什么。这组屏幕空间纹理就是 GBuffer。随后灯光 Pass 读取这些属性与深度等数据计算光照,避免对每盏灯都重新计算完整材质。深度常在单独资源中;位置可由屏幕坐标、深度和逆矩阵重建,不必总存完整 XYZ。

缓冲放的是什么能用来做什么
Scene Depth当前视角表面深度遮挡、重建位置、后处理等
GBuffer 属性材质/法线等打包信息,布局取决于路径与版本延迟光照和部分屏幕空间效果
Velocity投影后的运动信息,语义取决于具体实现时域重投影、运动模糊
Scene Color阶段性的场景颜色,常为 HDR后续合成、曝光与后处理

Forward:画表面时计算光照

常在绘制材质时处理相应光照,避免传统多张 GBuffer 的部分带宽。UE Forward 使用空间划分等办法筛选灯光,不等于“每个像素暴力遍历全部灯”。常用于评估 VR/MSAA 场景。

Deferred:表面和光照分开

多灯与屏幕空间功能方便组织,但写读 GBuffer 有带宽成本;透明多层与 MSAA 更复杂。透明物体通常走补充路径,不意味着整个引擎只能二选一。

第一个编辑器练习:打开包含球体与地面的场景,在视口 View Mode(视图模式)→ Buffer Visualization 中观察 Base Color、World Normal、Roughness、Scene Depth(菜单随版本/路径变化)。把灯强度改大,Base Color 不应因此直接改变;把材质粗糙度改大,Roughness 视图应改变。这能帮你区分“输入属性”和“最终光照”。
能不能背一串 UE 源码类名就算懂渲染管线?

面试更有价值的是说明数据依赖:这个 Pass 读什么、写什么、为什么需要它、性能为什么变化。若你阅读引擎源码,可从当前版本的 Renderer 模块、DeferredShadingRenderer、BasePassRendering、RenderGraphBuilder 等相关文件搜索入口,但文件和调用细节要以实际版本为准。会解释概念不代表已经掌握引擎源码扩展。

Epic:图形编程概览(仅取概念层)Epic:并行渲染Epic:Forward 路径

继续:UE5 关键系统 →
11

UE5 四个关键词,四种不同的问题

建议 50 分钟 · 先知道职责,再研究内部算法

GEOMETRY

Nanite · 几何细节

把几何划分为层次 cluster,按屏幕需求选择和流送细节,并采用专门的可见性/栅格化流程。它仍基于三角形,不是把模型“变成像素贴图”。

收益:管理高密度几何,减少部分传统提交与手工细节管理负担。边界:不让光照、复杂材质、透明、阴影免费;大量覆盖与重叠仍可能贵。

LIGHT TRANSPORT

Lumen · 间接光与反射

结合屏幕追踪、软件距离场或硬件光追,以及表面缓存等手段计算动态 GI 与反射。红墙反弹出的红色间接光属于它关注的问题。

收益:动态场景的间接光响应。边界:不是完整离线路径追踪;屏幕信息、几何表示、缓存更新和噪声控制会带来误差。

VISIBILITY FROM LIGHTS

VSM · 高细节阴影

Virtual Shadow Maps 把大阴影图分页,按需要分配并复用缓存。它解决从光源看表面的可见性,与 Lumen 的 GI 职责不同。

收益:高细节与近景阴影。边界:移动物体、灯光或形变可能让缓存失效;页面更新、灯光范围与几何都会影响成本。

RECONSTRUCTION

TSR · 重建清晰画面

利用较低分辨率当前图像、深度、速度与历史,重建更高分辨率输出;还承担时域抗锯齿。

收益:降低部分内部渲染成本。边界:自身要计算,历史可能失效;它不是生成额外中间帧的“帧生成”。

以 UE 5.6 为例的配置边界:Lumen 不兼容 Forward Shading;Nanite 的特性支持也受路径和平台限制。Lumen 不强制需要 RTX 或 Nanite,软件与硬件模式支持范围不同。不要把某个网上配置当作所有平台的默认答案。

看到问题,先对应负责的系统

看到的现象先检查为什么
间接光漏到薄墙背面Lumen 可视化、墙体厚度、几何表示近似场景表示未必精确覆盖所有薄结构
移动相机后细节拖尾速度信息、历史剔除、TAA/TSR 设置当前像素复用了不再匹配的过去信息
大量移动物体时阴影变贵VSM 页面与缓存失效、投影灯原本缓存的阴影内容需要重新生成
Nanite 开启后 GPU 仍很慢材质、透明、光照、阴影等 Pass几何细节只是成本的一部分
几个容易在面试里被追问的版本细节

静态光照:启用 Lumen GI 不会和烘焙 lightmap GI 简单加倍叠加;Lumen 反射可以独立配置,5.6 总览中描述了与烘焙 GI 组合的硬件光追方案。

骨骼网格:Nanite 支持持续演进,5.6 已有实验性 Skeletal Mesh 相关能力。答“永远不支持骨骼”比答“取决于版本与特性成熟度,我会查支持表”更容易出错。

屏幕比例:50% 通常指宽和高各为 50%,内部像素数量约 25%,但并非全部 GPU 成本都随像素等比例下降;TSR 后仍可能有按输出分辨率执行的工作。

NaniteLumen 总览Virtual Shadow MapsTSR

继续:性能分析 →
12

性能:少猜,先找到最贵的那几毫秒

建议 80 分钟 + 编辑器测量 · 学会一套可复现的方法

60 FPS 每帧预算约 16.67 ms,30 FPS 约 33.33 ms。从 10 ms 降到 8 ms,和从 20 ms 降到 18 ms 都省了 2 ms,但 FPS 增幅不同,所以优化报告先写毫秒。

FPS ≈ 1000 / FrameTime_ms 流水线充分重叠、无额外等待时:稳态帧间隔 ≈ max(CPU 各关键阶段, GPU) 实际还受同步、限帧、VSync、调度、并行依赖与呈现影响。

四类常见瓶颈

限制来自可能表现可验证的假设
CPU 游戏/提交Game 或 Draw 高,降分辨率帮助有限Tick、动画、可见对象、状态切换、提交次数或等待是否过多?
几何与可见性复杂几何/阴影相关 Pass 高视距、LOD、投影对象、实例化、Nanite 是否合适?
像素着色/Overdraw大屏幕覆盖、透明或复杂材质很贵同一位置被画很多层?材质指令或纹理采样太重?
带宽/资源大量纹理/缓冲读写、资源切换或流送问题纹理尺寸、Mips、格式、Render Target 数量与读写是否过高?
实验 09 / 预算计算器:为什么减半分辨率不等于 4 倍 FPS

教学假设:GPU 的 60% 随内部像素数缩放,40% 固定;CPU 不变,不含等待。这不是 UE 性能预测器。

尝试把 Game 调到 25 ms,再降屏幕比例。GPU 省下了时间,但帧率可能不变,因为瓶颈转移到了 CPU。

一套你现在就能执行的排查流程

  1. 锁定实验条件:记录 UE 版本、RHI、硬件、输出分辨率、画质、固定相机、测试模式。先等 shader 编译与资源加载稳定。比较时固定动态分辨率策略、限帧与垂直同步状态。
  2. 先分 CPU/GPU:执行 stat unit,观察 Frame、Game、Draw、GPU、RHIT。Draw 是渲染线程时间,不是 Draw Call 数量。最大者只能帮助初判,还要排除等待。
  3. 定位 GPU 大项:stat gpu 看分类;ProfileGPU 看 Pass。UI/日志输出随版本变化,必要时使用 Insights 的 GPU 轨迹。
  4. 追 CPU 尖峰与等待:使用 Unreal Insights,开启相关 Trace 通道,录制并检查帧与线程时间线。保存 .utrace;不要把传统 stat 的 .uestats 混为同一种文件。
  5. 改变一个变量:例如 100% → 75% 屏幕比例,或只关闭某个实验灯的投影。至少重复测量,观察波动与画质。
  6. 复测与解释:保存前后 ms、同视角截图、改动点和可接受代价。没有改善也有价值:它否定了一个瓶颈假设。
练一次有用的判断:GPU 20 ms,Game 6 ms,Draw 5 ms;降低屏幕比例后 GPU 变 13 ms,CPU 不变。初步支持像素相关开销较高,但不能直接推出“材质一定是唯一瓶颈”。要看哪些 GPU Pass 跟着下降,再定位。GPU 多 Pass 还可能有异步重叠,不要随意把事件树里的所有数字相加。
面试官问:“Draw Call 越少一定越快吗?”

不一定。减少提交可能降低 CPU 开销,但大合批可能削弱剔除粒度;更复杂的 shader 或更多 Overdraw 可能增加 GPU 负担。实例化也有适用条件,多个材质槽或不同状态会影响批次。优化目标是目标平台下的帧时间与画质,而不是孤立指标。

为什么 Shader Complexity 视图不等于真实 GPU 毫秒?

它给出有用的复杂度线索,但纹理缓存、内存访问、指令类型、执行分歧、分辨率与其他 Pass 都影响真实耗时。Quad Overdraw 帮助观察浪费的着色工作;最终仍需用 GPU 分析工具核验。

Epic:Stat 命令Epic:Unreal InsightsEpic:并行渲染模型

继续:实战项目 →
13

做一个能被追问的项目

项目名建议:UE5 渲染观察与性能对照实验 · 建议 6–10 小时

简历最有分量的句子是“我做了什么、怎么验证、结论适用在哪里”。下面的项目足够小,可以真正完成,又能串起前面的全部主线。

准备场景:一间实验室,三组对照

  1. 新建可运行的桌面 UE5 项目,记录具体版本、RHI 与显卡。使用基本体搭一个有地面、两面墙的场景,一面墙设红色。不要一开始引入大型资产包。
  2. 摆放 6 个球:非金属/金属各一排,Roughness 取 0.1、0.4、0.8。添加 Directional Light、Sky Light;按项目路径设置 GI/反射,并固定相机。
  3. 用 Post Process Volume 固定曝光条件(设置名称随版本变化);记录相机、分辨率、画质。给材质的 Roughness、Metallic 建参数,并用 Material Instance 调节。
  4. 新增一组可调层数的透明平面,另一组重复不透明物体。给测试对象统一命名,方便每次只切一个因素。
A / 材质与缓冲

属性和成像分开看

保存 Lit、Base Color、World Normal、Roughness 同视角截图。改变光强与粗糙度,观察哪些视图变化。

验收:能解释高光变化、法线颜色编码、材质输入与最终颜色的区别。

B / GI 与阴影

一次只改一个系统

在支持的 Deferred 配置中比较 Lumen GI 开/关的间接光,再单独比较投影开/关;使用相同曝光和相机,等待更新稳定。

验收:区分直接阴影、颜色溢出、屏幕反射与缓存误差;记录开关可能带来的其他配置影响。

C / 性能与代价

用 ms 证明假设

比较 100% / 75% / 50% 屏幕比例与 1 / 8 / 16 层透明覆盖,分别控制变量。用 GPU 工具找变化最大的 Pass。

验收:至少一组可复现的前后记录;即使 FPS 没涨,也要能解释 CPU 限制或其他原因。

进一步:把“理解”落实到代码

选做 GAMES101 作业 1–3,或自己实现一个最小 CPU 光栅器。最小验收:能旋转三角形;两个三角形互换绘制顺序后不透明遮挡一致;UV 使用透视校正;对照有/无多点采样结果。额外记录共面深度、近平面裁剪与退化三角形的处理。如果基于课程框架,注明自己完成的部分。

建议项目交付目录(你实际创建并填充):
RenderingLab/
  README.md              # 环境、运行方式、问题、结论
  Screenshots/           # 同视角的前后对照
  Captures/              # GPU 分析记录 / Insights .utrace
  Measurements.csv       # 每组多次测量,保留原始值
  Notes.md               # 为什么有效、画质代价、下一步
  Source/                # 你自己实现或修改的代码(如有)

可保存的实测记录

这里填写你自己的测量。输入会保存在当前浏览器;导出后可带到其他设备。它不会自动连接 UE,也不会替你生成实测成绩。

填写真实前后数据后,这里会计算变化;降低 GPU 时间不自动等于同等幅度提高 FPS。

你的“可以写进简历”验收清单

按你的真实完成程度,选择措辞

只有基础学习与练习

“了解实时渲染基础,能够解释 MVP 变换、光栅化、深度测试、纹理过滤与 PBR 基本原理,理解 UE5 桌面 Deferred 的主要数据流。”

完成 UE 项目与证据后

“完成 UE5 渲染观察与性能对照实验,使用 Buffer Visualization 与 GPU 分析工具定位[具体问题],在[环境]中将[目标 Pass / GPU 帧时间]从[实测 A]ms 调整到[实测 B]ms,记录了[画质代价]及适用条件。”

“了解渲染原理”“能分析自己的实验”是可信的起点。“精通 UE 渲染底层”“实现了 Lumen/Nanite”需要远超本页的源码与工程经验。请只填写亲自验证的数据,也不要把本页浏览器实验当作你自己的 UE 项目。
进入闭卷自测 →
14

不看答案,你能讲到哪一步

先做题,再口述;做对选择题不等于具备项目经验

已练习 0 题
首次正确率 —
当前答对 0 题
最近测验 —
打开错题回看 (0)

10 题闭卷闯关

从完整题库随机抽取 10 道,按基础、光照、引擎分组覆盖。提交前不显示解析;一次作答至少 8 题正确可视为本页知识自测通过。题目不重复,选项顺序固定;这不是能力认证。

尚未开始。建议用 15 分钟完成,并能解释其他选项为什么不对。

口述追问卡:按四步答,而不是背名词

先给定义,再讲机制,接着给UE 例子或实验,最后说限制与取舍。每题用 60–120 秒,回答后再展开要点。

01 / 18

评分仅为自评,会随学习记录保存。

最后的 3 分钟陈述

“角色动了以后,CPU 怎样把数据交给 GPU?一个顶点怎样变成表面属性?为什么需要深度和 GBuffer?灯光、间接光、阴影分别从哪里来?为什么最后还需要 TSR 和色调映射?我的项目在哪一环发现了问题,怎样证明改动有效?”

查看原始资料 →
15

资料库:知道下一步该查哪里

资料核验日期:2026-10-16 · 优先课程作者与官方文档

正文为面向初学者重新组织的原创解释,公式、例子与交互图解帮助理解;章节末尾链接用于核对与深入。外部课程与文档需联网,本站正文、图解和练习可离线使用。

按学习问题选资料

01 · GAMES101 官方主页 ↗课程大纲、全部讲义、录像与作业入口。查概念时从对应讲次进入。 02 · GAMES 官方录像合集 ↗按 Lecture 号定位;优先 L02–09、L12–17。不要只照抄作业答案。 03 · Physically Based Rendering,第 4 版 ↗免费在线英文教材。先读 Introduction,再按需查 BRDF、采样、路径追踪。 04 · Microsoft:Rasterizer Stage ↗核对裁剪、透视除法、视口、覆盖与插值在图形管线中的位置。 05 · Microsoft:Texture Filtering ↗最近邻、双线性、Mip 与各向异性,适合给纹理实验补概念。 06 · NVIDIA:深度精度可视化 ↗为什么透视深度非线性,以及浮点 reversed-Z 如何改善精度。 07 · Epic:Physically Based Materials ↗先看 Base Color、Roughness、Metallic、Specular 参数含义。 08 · Epic:Parallel Rendering ↗Game、Render、RHI 和 GPU 的分工;不要把 CPU 线程当 GPU。 09 · Epic:Forward Shading ↗阅读与 Deferred 的取舍和支持范围,特别是 MSAA 与屏幕空间功能。 10 · Epic:Render Dependency Graph ↗进阶入口:Pass 的资源读写、依赖、生命周期;首轮只读概览。 11 · Epic:Lumen GI & Reflections ↗先看它处理哪些光照,再读 Technical Details 的追踪与缓存。 12 · Epic:Lumen Technical Details ↗软件/硬件追踪、Surface Cache、屏幕追踪、薄墙与小发光体限制。 13 · Epic:Nanite ↗原理概览与当前版本的 Supported Features,不背过时的绝对限制。 14 · Epic:Virtual Shadow Maps ↗阴影页、缓存复用与失效,帮助理解动态场景阴影开销。 15 · Epic:Temporal Super Resolution ↗输入/输出分辨率、历史与速度,理解重建质量和性能。 16 · Epic:Stat Commands ↗核对 stat unit、stat gpu 等字段,先测量再调参。 17 · Epic:Unreal Insights ↗学习录制、打开轨迹、观察线程与帧时间;适合定位卡顿和等待。 18 · Epic:Color Grading / Tonemapper ↗把场景亮度与显示外观分开;做实验时固定曝光。

作业从官方课程主页的「课程作业」链接进入。此次抓取作业论坛超时,因此没有把旧提交系统或下载地址宣称为已验证可用;以课程网站当前状态为准。GAMES101 属于 2020 课程体系,基础数学长期适用;引擎特性则必须核对你的具体版本。

面试前 5 分钟速查

词一句话不要混淆
MVP模型 → 视图 → 投影,随后裁剪/除 w/视口乘完 P 不等于最终像素坐标
Rasterization把几何转换成离散覆盖与插值信息不单独决定最终光照
Depth Buffer记录当前视角最近可见深度不是从灯视角生成的 Shadow Map
BRDF表面在入射/出射方向之间怎样反射不是 GI 求解器
GBuffer延迟路径记录可见表面属性的一组缓冲不是所有阶段的最终 Scene Color
Draw / Draw Callstat unit 的 Draw 是时间;Draw Call 是命令单位和含义不同
Nanite / Lumen几何细节 / GI 与反射开启一种不会替代另一种职责
VSM / TSR阴影 / 时域重建不是 GI / 帧生成
Optimization固定条件、定位、改一项、测 ms、记代价不是把所有质量开关调低
建议最终能留下三样东西:一张你自己画的渲染数据流图、一份可复现的 UE 实验报告、一次不用读稿的口述解释。它们比“看完了多少视频”更能说明你学会了什么。
回到顶部 ↑