动态图形

在运行时控制 LOD、遮挡剔除与后处理,定位并缓解 GPU 侧动态渲染压力。

学习目标

  • 能解释 Profiler / Frame Debugger 中 GPU ms 高时,如何区分 Vertex、Fragment(Overdraw)与 Post-processing 三类瓶颈
  • 能说出 LOD Group、Occlusion Culling 与后处理 Volume 各自削减哪一类 GPU 成本,以及各自的启用前提
  • 能回答:开放世界远景卡顿、室内转角仍绘制墙后物体、移动端后处理拖帧——你会先查 LOD、Occlusion 还是 Post Stack 中的哪一项?

原书边界:Chapter 6

Packt 第三版把本章命名为 Dynamic Graphics。官方目录列出的核心范围如下;这些条目共同构成本章的一对一边界:

  • Exploring the Rendering Pipeline:纳入本章实验与验收,不拆到别章重复计数。
  • Detecting performance issues:纳入本章实验与验收,不拆到别章重复计数。
  • Rendering performance enhancements:纳入本章实验与验收,不拆到别章重复计数。

沿 CPU 提交、顶点、光栅、片元、带宽与后处理逐段定位瓶颈,再选择剔除、LOD、光照、阴影或 Shader 改动。Built-in、URP 与 HDRP 的工具入口不同,但先判 CPU/GPU bound、再缩小阶段的诊断顺序不变。 因此,本章既保留 2019/2020 语境,也明确标出迁移到现代 Unity 时哪些是稳定原理、哪些只是版本相关接口。

镜头一转远景就掉帧,GPU 在忙什么

你已经把 Draw Call 合批了、物理也睡了——帧率却在 拉远镜头看城市场景打开全屏 Bloom + 景深 时掉到 40。Profiler 里 GPU ms 顶满 16.6ms 预算,CPU 却还有余量。这不是提交慢,而是 显卡在顶点、像素或后处理上算不过来

上一章物理是 CPU 侧;这章要解决的,是 运行时仍随镜头、距离、特效变化的 GPU 账单。目标不是关掉画面,而是 远处换简模、被挡的不画、用不上的后处理别每帧全屏算

像摄影棚灯光:近景精修,远景只留轮廓

想象拍外景:近处演员 要高清妆容与布料褶皱;百米外的楼群 观众看不清窗框,只要 silhouette 对就行。若远处仍用近景道具、还把被墙挡住的布景也打光渲染,灯光师(GPU)会烧断保险丝。

这章的三把剪刀——LOD、遮挡剔除、后处理分级——都是按「观众真的看得到吗」动态减工作量。

GPU 瓶颈:先分清卡在管线哪一段

Ch1 你已会用 Profiler 对比 CPU ms 与 GPU ms。当 GPU bound 时,下一步不是继续合批,而是看 GPU 在干什么

在 Frame Debugger 里体现为 一串自上而下执行的 Render Pass。常见三类热点:

GPU 帧内典型阶段(Frame Debugger 自上而下)Vertex顶点变换·蒙皮Raster三角形→片元Fragment像素着色·OverdrawPost后处理全屏 PassGame → Stats:Batches / Tris / Saved by batching · Window → Analysis → Frame Debugger
Profiler GPU ms 高时,用 Frame Debugger 看哪一段 Pass 占时最长,再对症减几何、减 Overdraw 或砍后处理。
  • Vertex / 几何:Stats 里 Triangles、Vertices 极高——远景仍提交高面数、大量 Skinned Mesh
  • Fragment / FillOverdraw 高——半透明粒子叠层、UI 全屏、大分辨率
  • Post-processing:Volume 里 Bloom、DOF、SSR 等多 Pass 全屏
GPU 帧内典型阶段(Frame Debugger 自上而下)Vertex顶点变换·蒙皮Raster三角形→片元Fragment像素着色·OverdrawPost后处理全屏 PassGame → Stats:Batches / Tris / Saved by batching · Window → Analysis → Frame Debugger
Fragment/Fill bound:半透明叠层、大分辨率全屏绘制——Stats Overdraw 高;减粒子、减透明层、降分辨率。
GPU 帧内典型阶段(Frame Debugger 自上而下)Vertex顶点变换·蒙皮Raster三角形→片元Fragment像素着色·OverdrawPost后处理全屏 PassGame → Stats:Batches / Tris / Saved by batching · Window → Analysis → Frame Debugger
Post bound:Bloom/DOF/SSR 等全屏 Pass 堆叠——Profiler 里 Post-processing 或 URP Renderer Feature 占时高。

LOD Group:远处换简模

LOD Group 组件管理:每个级别绑定一个 Renderer(或子物体),Inspector 里设置 Screen Relative HeightDistance 切换阈值。

CameraLOD00–20m~12k trisLOD120–50m~4k trisLOD250–100m~800 trisCulled>100m近处 LOD0:最高面数,玩家能看清细节
LOD Group 按与相机距离自动切换 Renderer 网格;跨级切换可用 fade 或 hysteresis 减 pop。
CameraLOD00–20m~12k trisLOD120–50m~4k trisLOD250–100m~800 trisCulled>100m中距 LOD1:面数约降 60–70%,轮廓仍可读
LOD Group 按与相机距离自动切换 Renderer 网格;跨级切换可用 fade 或 hysteresis 减 pop。
CameraLOD00–20m~12k trisLOD120–50m~4k trisLOD250–100m~800 trisCulled>100m远距 LOD2:极简 proxy;再远则 Culled 完全不提交
LOD Group 按与相机距离自动切换 Renderer 网格;跨级切换可用 fade 或 hysteresis 减 pop。
CameraLOD00–20m~12k trisLOD120–50m~4k trisLOD250–100m~800 trisCulled>100m超出最大距离 → 不渲染;LOD Group 在 Inspector 配置各级网格与切换阈值
LOD Group 按与相机距离自动切换 Renderer 网格;跨级切换可用 fade 或 hysteresis 减 pop。

配置要点

  • LOD0 保留玩家能看清的细节;LOD2 可用极简 proxy 或 impostor
  • 最后一级可设为 Culled,超出距离 0 Draw Call
  • 跨级 pop 明显时:启用 Fade Mode(Cross Fade / Speed Tree)或略重叠阈值(hysteresis)
  • Skinned Mesh 也支持 LOD,但切换时注意动画是否共用同一 Avatar

Occlusion Culling:被墙挡住的别画

解决 Frustum Culling 管不到 的情况:转角后整栋楼的 Renderer 仍在视锥内,却被墙体完全挡住。

视锥Occluder可见仍绘制!可见仅 Frustum Culling:视锥内但被挡的物体仍会 Draw → Overdraw / Vertex 浪费
Window → Rendering → Occlusion Culling 烘焙 Occluder/Occludee;适合室内、城市峡谷等静态遮挡。

未烘焙或未启用时,墙后物体 仍会 Draw,浪费 Vertex 与 Overdraw。

视锥Occluder可见已剔除可见Occlusion Culling 烘焙后:被 Occluder 挡住的 Renderer 跳过 Draw Call
Window → Rendering → Occlusion Culling 烘焙 Occluder/Occludee;适合室内、城市峡谷等静态遮挡。

启用后需 烘焙 Occlusion 数据(Window → Rendering → Occlusion Culling):标记 Occluder Static 的墙体参与遮挡,Occludee 物体被写入剔除单元。适合 室内、走廊、城市峡谷 等静态遮挡丰富的场景;开放平原收益有限。

后处理栈:全屏 Pass 叠加

在 URP/HDRP 中由 Volume Profile 驱动。每个 Effect 多为 至少一次全屏 Draw,分辨率越高、Pass 越多,Fragment 带宽 越贵。

移动端常见策略:全局 Volume 只留 Tonemap + 轻 Bloom;DOF / Motion Blur / SSR 按 Quality Level 或场景局部 Volume 开关。Profiler 里逐项 禁用 Volume Override 对比 GPU ms,比凭感觉调参快。

粒子与 LineRenderer:动态生成的 GPU 税

不属于静态 LOD/Occlusion 能覆盖的范围——它们 每帧变,且多为 半透明、从近到远叠满屏幕

动手:GPU 动态图形排查

下面五步把「GPU bound + 镜头相关卡顿」从定位到改动走通。每切一步,示意图对应当前关注点——建议在卡顿镜头下同步打开 Profiler GPU 与 Frame Debugger。

猜一猜:拉远镜头 Tris 几乎不变,和 Tris 随距离明显下降,分别更该先查 LOD 还是 Occlusion?

分步1 / 5

① 基线:确认 GPU bound 与 Stats 读数

GPU 帧内典型阶段(Frame Debugger 自上而下)Vertex顶点变换·蒙皮Raster三角形→片元Fragment像素着色·OverdrawPost后处理全屏 PassGame → Stats:Batches / Tris / Saved by batching · Window → Analysis → Frame Debugger
Profiler GPU ms 高时,用 Frame Debugger 看哪一段 Pass 占时最长,再对症减几何、减 Overdraw 或砍后处理。

Play 卡顿场景,Profiler 对比 CPU ms 与 GPU ms。Game Stats 记下 Tris、Batches、SetPass;GPU 更高则本清单有效。Frame Debugger 看 Pass 列表哪段最长。

容易踩的坑

小结

  • GPU bound 时先分 Vertex(Tris)/ Fragment(Overdraw)/ Post 三类瓶颈
  • LOD Group 按距离降面数或 Culled;需真实多级网格与合理阈值
  • Occlusion Culling 剔除视锥内被挡静态物;需烘焙,适合室内/城市
  • 后处理栈 每层≈全屏 Pass;按平台分级 Volume,逐项 Profiler 对比
  • 粒子 / LineRenderer 动态透明叠层是常见 Fill bound;限数量、并材质、降更新

练习

问题 1(改 Demo 型) 在 GPU ms 最高的镜头打开 Stats,记下 Tris 与 Batches。任选 为一个重复 Prefab 加 LOD Group烘焙 Occlusion 一个小室内 只做一处改动,同镜头复测——GPU ms 与 Tris 变化多少?

问题 2(问答型) Frustum Culling 与 Occlusion Culling 各剔除哪类物体?为何开放平原 Occlusion 收益小?

问题 3(问答型) 后处理 Bloom 为何比 Color Grading 更耗 GPU?移动端常如何取舍?

名词解释

本章出现的专业名词,用大白话再讲一遍。

LOD(细节层次)

按与相机距离切换网格精度。详见 LodTransitionDiagram 与 LOD Group Stepper。

LOD Group

管理多级 Renderer 与切换阈值的组件。详见 LodTransitionDiagram。

Occlusion Culling(遮挡剔除)

剔除视锥内被静态遮挡物挡住的物体。详见 OcclusionCullingDiagram mode on。

Frustum Culling(视锥剔除)

相机视锥外物体不提交;引擎默认开启,与 Occlusion 互补。

Post-processing Stack(后处理栈)

渲染完成后依次施加的全屏效果链。详见 PostProcessStackDiagram。

Overdraw

同一像素被多次绘制;Stats 与 Fragment bound 的关键指标。详见 RenderingPipelineGpuDiagram highlight fragment。

Volume Profile

URP/HDRP 中挂载后处理参数的 ScriptableObject,可按全局/局部/Quality 分级。

资料与写作方式声明

本章以Packt《Unity Game Optimization》第3版权威目录界定学习范围,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…