看懂一帧画面,
从第一个像素开始。
给 UE 客户端初学者的图形学速成路线。把公式变成看得见的实验,把引擎术语连成完整的渲染过程,再用项目和追问检验理解。
先明确:你要学会什么
学习导航 · 不要求先学完高数 · 建议 20 分钟
你已经会在 UE 里放模型、调材质、打灯。现在要回答的是:这些操作怎样变成屏幕上的颜色,以及哪里会变慢。
从一个点到一个像素
说清坐标变换、覆盖判断、深度测试、纹理采样和光照计算之间的关系。
把概念放回 UE
分清 Base Pass、GBuffer、光照、透明、后处理,知道四个 UE5 系统分别解决什么。
用证据写进简历
完成对照场景和性能记录,能解释一次优化的原因、收益、画质代价与适用条件。
两条路线,你可以先跑一遍,再做扎实
6–8 小时概览:读每章开头、做实验、答随堂题,先搭起知识结构。28–40 小时首轮:再补关键课程片段与项目。零数学或零 C++ 基础需要更多时间;完成阅读并不等于已经能写渲染器。
空间与相机
01–02 章;GAMES101 L02–04。手算点积与一个 MVP 例子。
三角形到像素
03–05 章;L05–06、08–09。完成覆盖、深度、过滤实验。
颜色从哪来
06–08 章;L07、12–17 相关片段。区分材质、阴影、GI。
映射 UE
09–11 章;在编辑器里看 Wireframe、Buffer Visualization。
第一次测量
12 章;搭实验场景、固定条件、定位最大 GPU 开销。
做出项目证据
13 章;完成三个对照实验、保存捕获与说明文档。
闭卷复盘
14 章;10 题测验、口述追问、修改项目说明与简历。
补齐代码能力
选做 GAMES101 作业 1–3,再做 5–7;实现与解释都要自己完成。
GAMES101 要不要从头全部看完?
这门课系统覆盖光栅化、几何、光传播与动画模拟,本页围绕 UE 客户端所需的渲染主线重新编排。遇到概念卡住再回看对应讲次:L02–09 打基础,L12 阴影、L13–17 光追与材质是重点;L10–11 几何、L18–22 进阶外观/相机/颜色/动画可在首轮后补全。这里的时长是学习计划估计,不能代替完整课程的深度。
课程结构核验:GAMES101 官方课程主页课程官方录像合集
向量:让“方向”变成可计算的量
GAMES101 L02 · 建议 45 分钟 · 先会解释,再记公式
点回答“在哪里”,向量回答“朝哪里、走多远”。玩家在 A,目标在 B,那么 B − A 是指向目标的向量。长度是距离,除以长度就得到只保留方向的单位向量。
点积:两个方向有多一致?
两个单位向量的点积就是夹角余弦:同向为 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。
交换顺序会翻转方向。网格顶点绕序影响正反面,法线影响着色;“法线朝前”与“背面剔除保留该面”不是同一个规则。
试 0°、60°、90°、120°。这里 l 指“表面指向光源”,与光实际传播方向相反。
把光束想成一把筷子:斜着照会摊到更大的面积上,单位面积收到的光就更少。
矩阵:把一组基向量换成另一组
矩阵并不只是数字表。用列向量时,矩阵的每一列告诉你原来的 X/Y/Z 基方向变到哪里。矩阵乘法能把缩放、旋转串起来;平移需要下一章的齐次坐标。
Normalize(Target − Position) 得到方向;用 Dot(Forward, Direction) 判断目标是否在前方。做光照前,法线 n 和光向量 l 必须处在同一坐标空间,否则点积的结果没有你期望的几何意义。对应学习:官方 L02 讲义入口
变换:一个顶点怎样走到屏幕上
GAMES101 L03–04 · 建议 70 分钟
把一个模型放进场景,就像把一把椅子搬进摄影棚。模型坐标描述椅子自身,世界坐标描述它在摄影棚里的位置,相机坐标描述它相对镜头的位置;投影决定它在照片上有多大。
为什么多出一个 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) 变小,看见的范围更广,同一物体更小。正交投影没有这个距离缩放。
切到正交后改变距离。正交相机的可视高度固定为 6 个单位,FOV 对它不生效。
采用右手教学相机、Y 向上、−Z 朝前;这是数学演示,与 UE 世界轴的命名不同。
面试容易漏掉的两步
先在裁剪空间裁剪,再做透视除法。跨过近平面的三角形不能简单地把某个顶点“删掉”;需要裁出新的边界,否则除以接近零或负的 w 会产生异常投影。之后 NDC 经视口变换到像素位置。深度范围依图形 API 和配置而变,不应只背一种范围。
法线不是普通位置。有非均匀缩放时,法线要用线性变换 A 的逆转置 (A⁻¹)ᵀ 再归一化。原因是仍需满足 n′·t′=0,才能与变换后的切线垂直。只有纯旋转/适当统一缩放时才可简化。
光栅化:哪些像素属于这个三角形
GAMES101 L05–06、08 · 建议 60 分钟
光栅化把连续三角形转换为离散采样点上的覆盖信息。它回答“这片表面影响哪些位置”,着色才回答“这些位置应该是什么颜色”。一个像素可能被多层表面覆盖,必须继续解决遮挡。
这是逻辑依赖图。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));
}
}
B 距离固定为 5。这里用线性映射演示比较方向;实际透视深度通常不是线性距离。
相同距离时本实验使用严格比较,先绘制的 A 胜出;真实项目应避免依赖共面片元的偶然结果。
为什么透明物体比较麻烦?
不透明表面只留下最近层通常就够了;透明要混合多层颜色。普通 alpha 混合是 C = αC_front + (1−α)C_back,顺序不同结果不同。常见做法是保留深度测试、关闭透明深度写入,并按远到近画;物体互相穿插时简单排序仍不够。
采样:锯齿不是“边缘不够模糊”
GAMES101 L05–06 · 建议 45 分钟
屏幕像一张格子纸。真实图像连续变化,像素只有有限个;如果每格只看一个点,一条很细的线可能刚好全被漏掉。高频细节无法由低密度样本区分,会伪装成错误的低频形状,这就是混叠 Aliasing。空间上是锯齿、摩尔纹;时间上是闪烁、车轮倒转。
一个像素理想上代表一定区域与时间内的滤波结果,不是一个数学点。解决思路是在采样前控制高频,或取得更多有效样本。事后模糊可以遮盖部分瑕疵,却无法还原从未采到的信息。Nyquist 的“超过最高频率两倍”以带限信号为前提,三角形硬边并不天然带限。
慢慢移动边缘:1 点采样会跳变,多点覆盖会平滑过渡。本例只计算常量色三角形的覆盖,不测量 GPU 代价。
白线为连续三角形边界,绿色亮度为该像素内部被覆盖样本的比例。它展示超采样覆盖积分的直觉。
| 方法 | 样本来自哪里 | 优势与代价 |
|---|---|---|
| SSAA | 更高分辨率完成渲染,再过滤缩小 | 覆盖几何与着色的多种混叠,通常很贵 |
| MSAA | 像素内多个覆盖/深度样本;着色通常复用 | 擅长几何轮廓;不能保证消除高光、纹理闪烁,不等于所有着色执行 N 次 |
| FXAA | 单帧最终图像中的边缘 | 轻量、可能模糊细节,没有多帧恢复能力 |
| TAA | 抖动后的当前帧 + 重投影历史 | 提高有效采样量;依赖运动/深度和历史剔除,可能拖影、变软 |
| TSR | 较低分辨率当前帧 + 时域信息,重建更高输出分辨率 | 同时做时域抗锯齿与超分;会有自身成本与历史失效问题 |
纹理:给表面一个能查询的数据表
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 分别为 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 预先把纹理逐层低通过滤并缩小,运行时按纹理足迹选层;三线性在相邻两层的双线性结果之间再插值。
横向只有 96 个屏幕样本。超过 48 周期后会混叠。对比移动时上下两行的稳定性。
上:单点采样。下:对正弦条纹做像素宽度的精确盒式积分,说明预过滤原理;不是完整 Mipmap 或各向异性算法。
一条完整二维 Mip 链在同格式、忽略对齐时占基础层约 1+1/4+1/16+…=4/3 的存储。用额外约三分之一存储换取稳定性与采样效率。斜看地板时足迹是细长形,各向异性过滤沿长轴增加采样,减少普通 Mip 过度模糊。
法线贴图为什么看起来有凹凸,却没有改变轮廓?
常见切线空间法线贴图把方向编码进 RGB,解码后借助 TBN(切线、双切线、法线)转换到着色使用的空间。它改变“如何反光”,不会直接移动三角形顶点。轮廓、自遮挡、碰撞想真正改变,需要几何或其他专门技术。
光照:材质不是颜色,而是对光的响应
GAMES101 L07、15、17 · 建议 90 分钟
同一块红塑料,在暗室里看不见,白灯下呈红色,掠射角又会出现白色反光。最终颜色 = 入射光 × 表面如何散射 × 可见性,还要经过相机曝光和显示转换。Base Color 只是输入之一。
先弄懂三种“光的量”
辐射通量 Φ
单位时间的光能量,单位 W。像“水管每秒流多少水”。
辐照度 E
单位面积收到的通量,单位 W/m²。像“地面每平方米收到多少水”。
辐亮度 L
按方向、按投影面积计量的光,单位 W/(m²·sr)。像“沿镜头这条方向看过去有多亮”。
sr(球面度)描述方向在空间中占多大范围。不要把方向量和总能量混为一谈。游戏常用 RGB 近似光谱;“用三个颜色通道”是工程表示,不表示光只有三种波长。
第一步:Lambert 漫反射
余弦项负责斜着照会变暗;ρ/π 是 Lambert BRDF,除以 π 才让整个半球反射能量与反射率一致。理想点光源的辐照度还随距离平方衰减;距离翻倍,其他条件相同约变为 1/4。方向光则是另一个建模假设。
第二步:从高光公式走到微表面
Blinn–Phong 用 h=normalize(l+v),再用 max(0,n·h)^p 做高光,p 越大越集中。它是理解“看向哪里影响反光”的好起点,但不能直接当成 UE 的完整 PBR 模型。
BRDF,双向反射分布函数,描述从方向 l 来的光有多少被反射到方向 v。它不是灯光,不是纹理,也不直接等于最终颜色。物理合理模型通常满足非负、互易、能量守恒。微表面模型把看似平滑的表面想成许多微小镜片。
粗糙度改变微镜片方向的分散程度,所以高光会变宽、峰值常降低;它不是“把反射直接关掉”。Fresnel 解释很多非金属在掠射角看起来更反光。几何遮挡项 G 管的是微表面互相挡住,和物体投到地上的阴影贴图不是同一个尺度的问题。
先观察高光宽度,再切换金属。没有环境反射的金属暗部可能很暗,别靠提高 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 特殊着色模型更复杂。
阴影与显示:算对光,还要看对光
GAMES101 L12、19–20 · 建议 60 分钟
Shadow Map:站到灯的位置,再看一次
第一次从灯的视角渲染深度,记录灯能直接看见的最近表面;第二次从相机渲染,把表面点变换到灯的空间,比较它与阴影图里的深度。如果它比灯看见的那一层更远,说明中间有遮挡。
自阴影条纹:Shadow Acne
采样分辨率和精度误差让本该同一表面相互遮挡。给比较加适当 bias 可缓解;bias 太大又会让阴影与物体分离(Peter Panning)。
软边:PCF
对邻近多个阴影深度比较结果求平均,得到部分可见性。它不是先把深度平均后再比较,也不等于精确求解面光源的真实半影。
为什么一定要在线性空间做光照?
sRGB 是对显示颜色的非线性编码;直接对编码值相加,不对应能量相加。应先解码到线性空间,完成光照和需要线性意义的混合,再做显示编码。常见近似“γ=2.2”方便理解,但精确 sRGB 是分段函数。
这是黑与白的能量混合示例,不是说所有 UI 插值都必须选择同一种颜色空间;渲染光照要保持能量的线性意义。
HDR → 曝光 → 色调映射 → 显示
HDR 表示场景亮度可以超过普通 0–1 显示范围;曝光决定相机把多少光映射到图像;Tone Mapping压缩高动态范围并形成外观;sRGB 编码负责对应显示。色调映射和 gamma/sRGB 转换不是同一步。
Bloom 让强光向周围扩散,模拟部分成像效果;它不是全局光照。提高曝光能让整张图更亮,不意味着场景多了一盏灯。做材质对照时要固定曝光,否则自动曝光会把不同实验“拉回差不多亮”。
光追与 GI:把没直达眼睛的光也算进来
GAMES101 L13–16 · 建议 90 分钟
光栅化从三角形出发,寻找它覆盖哪些屏幕位置;光线追踪从一条射线出发,寻找沿途第一个交点。两者可以服务于同一帧:主可见性用光栅,反射或阴影用光追。“用了光追”不代表整幅画面都用路径追踪。
从求交到 BVH
最朴素的方法是一条射线遍历所有三角形,N 条射线、M 个三角形就可能要做 N×M 次测试。BVH 把几何组织成一棵包围盒树:先测盒子,没碰到整支都跳过;碰到了再深入子节点,最后才测试三角形。
直接光、间接光和渲染方程
灯直接照到桌面是直接光;灯先照到红墙,墙再把带红色的光反射到桌面,是间接光。全局光照 GI 关心表面之间的光传输,而不仅是加一个统一“环境亮度”。
把积分想成“遍历半球所有方向,每个方向的光乘上材质响应和投影因子”。困难在于入射光 L_i 往往来自别的表面,那个表面的光也要继续算,于是问题会递归。可见性可以包含在入射光求值中,或显式作为传输项;无遮挡不应凭空被假定。
路径追踪:随机采样这个积分
无法真的枚举无限方向,就按概率密度 p 抽取几个方向,用 f/p 的平均估计积分。一条相机射线命中后继续采样反弹方向,逐步累积光传输。重要性采样尽量把样本花在贡献大的方向,降低方差。
随机采样用噪声换取对复杂积分的估计;实时渲染样本少,会结合降噪、缓存与时域积累。降噪会带来偏差或细节损失;不能把“看起来没有噪点”直接等同于“完全正确”。
| 容易混淆 | 真正的关系 |
|---|---|
| Ray Tracing / Path Tracing | 光追是射线求交与传输技术族;路径追踪是一种用随机路径估计光传输的方法 |
| GI / AO | GI 求间接光传输;AO 近似局部遮蔽,不计算完整的颜色溢出与多次反弹 |
| SSR / 光追反射 | SSR 主要依赖屏幕已有信息,屏幕外或被遮住的物体会缺失;场景光追可查询更完整几何,但更贵且仍受实现限制 |
| Lumen / 离线路径追踪 | Lumen 组合多种实时近似与追踪/缓存来做 GI 和反射,不是无限采样的离线路径追踪器 |
补全地图:几何与动画怎样进入渲染
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 思路。曲线经过首尾端点,中间控制点通常只控制走势,并不一定被穿过。
骨骼蒙皮与物理模拟
线性混合蒙皮把绑定姿态顶点乘上多个骨骼的“当前变换 × 逆绑定变换”,再按权重相加:p′ = Σ wᵢ Mᵢ p,通常权重和为 1。它便宜,但关节可能塌陷或出现糖纸扭曲。法线也需随形变处理。
质点弹簧用位置、速度和力更新运动,离散时间步长太大可能让显式积分不稳定。渲染帧率与模拟步长不是必须一一对应。对客户端开发,你首先要知道动画/模拟产生当前几何,运动信息还会影响速度缓冲和时域重建。
拆解 UE 的一帧:谁在算,算出什么
从图形学连接引擎 · 建议 80 分钟 · 桌面 Deferred 概念路径
先分开两条线:CPU 提交工作,GPU 执行工作
角色移动先更新游戏状态;渲染相关数据传给渲染线程,通过 RHI 抽象连接图形 API,GPU 最终执行。各阶段能处理不同帧、并行重叠,也会因依赖而等待。Render Thread 是 CPU 线程,RHI 不是显卡本身。具体线程启用方式依平台与配置变化。
Draw Call 是发起绘制的命令,不等于一个三角形。一条调用可画很多三角形;一个物体可能因材质分区、深度、阴影等被多次绘制。Shader 是 GPU 程序;Pass 是完成某个目的的一组渲染工作;Render Target 是写入结果的纹理/缓冲。RDG(Render Dependency Graph)组织 Pass 与资源读写依赖,帮助安排资源生命周期和执行,不是一种新的光照公式。
点开每一站:输入 → 处理 → 输出
这是理解依赖关系的教学路线,不是逐事件捕获。阴影可单独准备,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 更复杂。透明物体通常走补充路径,不意味着整个引擎只能二选一。
能不能背一串 UE 源码类名就算懂渲染管线?
面试更有价值的是说明数据依赖:这个 Pass 读什么、写什么、为什么需要它、性能为什么变化。若你阅读引擎源码,可从当前版本的 Renderer 模块、DeferredShadingRenderer、BasePassRendering、RenderGraphBuilder 等相关文件搜索入口,但文件和调用细节要以实际版本为准。会解释概念不代表已经掌握引擎源码扩展。
UE5 四个关键词,四种不同的问题
建议 50 分钟 · 先知道职责,再研究内部算法
Nanite · 几何细节
把几何划分为层次 cluster,按屏幕需求选择和流送细节,并采用专门的可见性/栅格化流程。它仍基于三角形,不是把模型“变成像素贴图”。
收益:管理高密度几何,减少部分传统提交与手工细节管理负担。边界:不让光照、复杂材质、透明、阴影免费;大量覆盖与重叠仍可能贵。
Lumen · 间接光与反射
结合屏幕追踪、软件距离场或硬件光追,以及表面缓存等手段计算动态 GI 与反射。红墙反弹出的红色间接光属于它关注的问题。
收益:动态场景的间接光响应。边界:不是完整离线路径追踪;屏幕信息、几何表示、缓存更新和噪声控制会带来误差。
VSM · 高细节阴影
Virtual Shadow Maps 把大阴影图分页,按需要分配并复用缓存。它解决从光源看表面的可见性,与 Lumen 的 GI 职责不同。
收益:高细节与近景阴影。边界:移动物体、灯光或形变可能让缓存失效;页面更新、灯光范围与几何都会影响成本。
TSR · 重建清晰画面
利用较低分辨率当前图像、深度、速度与历史,重建更高分辨率输出;还承担时域抗锯齿。
收益:降低部分内部渲染成本。边界:自身要计算,历史可能失效;它不是生成额外中间帧的“帧生成”。
看到问题,先对应负责的系统
| 看到的现象 | 先检查 | 为什么 |
|---|---|---|
| 间接光漏到薄墙背面 | 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 后仍可能有按输出分辨率执行的工作。
性能:少猜,先找到最贵的那几毫秒
建议 80 分钟 + 编辑器测量 · 学会一套可复现的方法
60 FPS 每帧预算约 16.67 ms,30 FPS 约 33.33 ms。从 10 ms 降到 8 ms,和从 20 ms 降到 18 ms 都省了 2 ms,但 FPS 增幅不同,所以优化报告先写毫秒。
四类常见瓶颈
| 限制来自 | 可能表现 | 可验证的假设 |
|---|---|---|
| CPU 游戏/提交 | Game 或 Draw 高,降分辨率帮助有限 | Tick、动画、可见对象、状态切换、提交次数或等待是否过多? |
| 几何与可见性 | 复杂几何/阴影相关 Pass 高 | 视距、LOD、投影对象、实例化、Nanite 是否合适? |
| 像素着色/Overdraw | 大屏幕覆盖、透明或复杂材质很贵 | 同一位置被画很多层?材质指令或纹理采样太重? |
| 带宽/资源 | 大量纹理/缓冲读写、资源切换或流送问题 | 纹理尺寸、Mips、格式、Render Target 数量与读写是否过高? |
教学假设:GPU 的 60% 随内部像素数缩放,40% 固定;CPU 不变,不含等待。这不是 UE 性能预测器。
尝试把 Game 调到 25 ms,再降屏幕比例。GPU 省下了时间,但帧率可能不变,因为瓶颈转移到了 CPU。
一套你现在就能执行的排查流程
- 锁定实验条件:记录 UE 版本、RHI、硬件、输出分辨率、画质、固定相机、测试模式。先等 shader 编译与资源加载稳定。比较时固定动态分辨率策略、限帧与垂直同步状态。
- 先分 CPU/GPU:执行
stat unit,观察 Frame、Game、Draw、GPU、RHIT。Draw 是渲染线程时间,不是 Draw Call 数量。最大者只能帮助初判,还要排除等待。 - 定位 GPU 大项:
stat gpu看分类;ProfileGPU看 Pass。UI/日志输出随版本变化,必要时使用 Insights 的 GPU 轨迹。 - 追 CPU 尖峰与等待:使用 Unreal Insights,开启相关 Trace 通道,录制并检查帧与线程时间线。保存
.utrace;不要把传统 stat 的.uestats混为同一种文件。 - 改变一个变量:例如 100% → 75% 屏幕比例,或只关闭某个实验灯的投影。至少重复测量,观察波动与画质。
- 复测与解释:保存前后 ms、同视角截图、改动点和可接受代价。没有改善也有价值:它否定了一个瓶颈假设。
面试官问:“Draw Call 越少一定越快吗?”
不一定。减少提交可能降低 CPU 开销,但大合批可能削弱剔除粒度;更复杂的 shader 或更多 Overdraw 可能增加 GPU 负担。实例化也有适用条件,多个材质槽或不同状态会影响批次。优化目标是目标平台下的帧时间与画质,而不是孤立指标。
为什么 Shader Complexity 视图不等于真实 GPU 毫秒?
它给出有用的复杂度线索,但纹理缓存、内存访问、指令类型、执行分歧、分辨率与其他 Pass 都影响真实耗时。Quad Overdraw 帮助观察浪费的着色工作;最终仍需用 GPU 分析工具核验。
做一个能被追问的项目
项目名建议:UE5 渲染观察与性能对照实验 · 建议 6–10 小时
简历最有分量的句子是“我做了什么、怎么验证、结论适用在哪里”。下面的项目足够小,可以真正完成,又能串起前面的全部主线。
准备场景:一间实验室,三组对照
- 新建可运行的桌面 UE5 项目,记录具体版本、RHI 与显卡。使用基本体搭一个有地面、两面墙的场景,一面墙设红色。不要一开始引入大型资产包。
- 摆放 6 个球:非金属/金属各一排,Roughness 取 0.1、0.4、0.8。添加 Directional Light、Sky Light;按项目路径设置 GI/反射,并固定相机。
- 用 Post Process Volume 固定曝光条件(设置名称随版本变化);记录相机、分辨率、画质。给材质的 Roughness、Metallic 建参数,并用 Material Instance 调节。
- 新增一组可调层数的透明平面,另一组重复不透明物体。给测试对象统一命名,方便每次只切一个因素。
属性和成像分开看
保存 Lit、Base Color、World Normal、Roughness 同视角截图。改变光强与粗糙度,观察哪些视图变化。
验收:能解释高光变化、法线颜色编码、材质输入与最终颜色的区别。
一次只改一个系统
在支持的 Deferred 配置中比较 Lumen GI 开/关的间接光,再单独比较投影开/关;使用相同曝光和相机,等待更新稳定。
验收:区分直接阴影、颜色溢出、屏幕反射与缓存误差;记录开关可能带来的其他配置影响。
用 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,也不会替你生成实测成绩。
你的“可以写进简历”验收清单
按你的真实完成程度,选择措辞
只有基础学习与练习
“了解实时渲染基础,能够解释 MVP 变换、光栅化、深度测试、纹理过滤与 PBR 基本原理,理解 UE5 桌面 Deferred 的主要数据流。”
完成 UE 项目与证据后
“完成 UE5 渲染观察与性能对照实验,使用 Buffer Visualization 与 GPU 分析工具定位[具体问题],在[环境]中将[目标 Pass / GPU 帧时间]从[实测 A]ms 调整到[实测 B]ms,记录了[画质代价]及适用条件。”
不看答案,你能讲到哪一步
先做题,再口述;做对选择题不等于具备项目经验
打开错题回看 (0)
10 题闭卷闯关
从完整题库随机抽取 10 道,按基础、光照、引擎分组覆盖。提交前不显示解析;一次作答至少 8 题正确可视为本页知识自测通过。题目不重复,选项顺序固定;这不是能力认证。
口述追问卡:按四步答,而不是背名词
先给定义,再讲机制,接着给UE 例子或实验,最后说限制与取舍。每题用 60–120 秒,回答后再展开要点。
评分仅为自评,会随学习记录保存。
最后的 3 分钟陈述
“角色动了以后,CPU 怎样把数据交给 GPU?一个顶点怎样变成表面属性?为什么需要深度和 GBuffer?灯光、间接光、阴影分别从哪里来?为什么最后还需要 TSR 和色调映射?我的项目在哪一环发现了问题,怎样证明改动有效?”
资料库:知道下一步该查哪里
资料核验日期:2026-10-16 · 优先课程作者与官方文档
正文为面向初学者重新组织的原创解释,公式、例子与交互图解帮助理解;章节末尾链接用于核对与深入。外部课程与文档需联网,本站正文、图解和练习可离线使用。
按学习问题选资料
作业从官方课程主页的「课程作业」链接进入。此次抓取作业论坛超时,因此没有把旧提交系统或下载地址宣称为已验证可用;以课程网站当前状态为准。GAMES101 属于 2020 课程体系,基础数学长期适用;引擎特性则必须核对你的具体版本。
面试前 5 分钟速查
| 词 | 一句话 | 不要混淆 |
|---|---|---|
| MVP | 模型 → 视图 → 投影,随后裁剪/除 w/视口 | 乘完 P 不等于最终像素坐标 |
| Rasterization | 把几何转换成离散覆盖与插值信息 | 不单独决定最终光照 |
| Depth Buffer | 记录当前视角最近可见深度 | 不是从灯视角生成的 Shadow Map |
| BRDF | 表面在入射/出射方向之间怎样反射 | 不是 GI 求解器 |
| GBuffer | 延迟路径记录可见表面属性的一组缓冲 | 不是所有阶段的最终 Scene Color |
| Draw / Draw Call | stat unit 的 Draw 是时间;Draw Call 是命令 | 单位和含义不同 |
| Nanite / Lumen | 几何细节 / GI 与反射 | 开启一种不会替代另一种职责 |
| VSM / TSR | 阴影 / 时域重建 | 不是 GI / 帧生成 |
| Optimization | 固定条件、定位、改一项、测 ms、记代价 | 不是把所有质量开关调低 |