《游戏引擎实现原理》渲染引擎 目录

《游戏引擎实现原理》卷二《渲染引擎》全书导航页:说明本卷定位与卷一《引擎内核》的关系、本卷差异化(在 RHI 上从零实现、每节跑出真实产物、真实像素与计时结果),给出顺序通读、只读 RHI 四章、直奔帧图与后处理三条阅读路径,讲清 L1–L2 可运行性口径,并按五个部分列出 18 章 54 节的完整章节索引,另含周计划表与常见问题速查,方便读者按需定位、跳读与随时查阅。

目录

欢迎继续《游戏引擎实现原理》。卷一《引擎内核》里,我们从零写出了一个能跑的引擎内核 helio——它管内存、管句柄、管实体和组件、管并发。但它是个「盲人」:它知道方块在哪,却不知道方块长什么样。这一卷要做的,就是把那份数据变成屏幕上的像素。

卷二《渲染引擎》要陪你做的是另一件实在的事:在卷一的 helio 内核之上,用 TypeScript 从零接出一套完整的渲染引擎,让《微光岛》的小岛第一次真正被画出来——有光、有影、有后处理、有 UI。

为什么先讲「RHI」再讲「画面」?因为渲染引擎里最容易被讲糊、也最贵的部分,不是那些看得见的着色技巧,而是看不见的抽象层——设备怎么建、命令怎么录、资源怎么绑、内存怎么管、多后端怎么统一。这一层站稳了,后面的几何、光照、帧图、后处理才不是空中楼阁。先有 RHI,才谈得上别的。

市面上讲渲染的书大多从「图形学管线」或「某个引擎的材质系统」切入。本卷走第三条路:每一节都写代码,每一节的代码都在本机真跑过,跑出来的就是这一节的结论——真实像素、真实计时。

这一卷写给谁

读者现状读完能拿到什么
读过卷一《引擎内核》的读者内核能跑,但没有画面一套接在内核之上的渲染引擎,和「数据怎么变像素」的完整链条
有图形学基础、想理解引擎实现懂管线与着色器,但不知道引擎怎么组织它们RHI、帧图、批次、阴影这些工程层的真实实现
前端 / Web 图形开发者熟 WebGL / WebGPU API,缺引擎视角多后端抽象、资源生命周期、命令录制的系统化做法
已读过渲染原理、想做自研渲染器懂「为什么这么画」,缺「怎么搭起来」一条从设备抽象到综合 demo 的可复制实现路径

前置知识:读完卷一《引擎内核》,或至少了解句柄、ECS 与 Job System 的基本概念;会写 TypeScript。不需要安装任何游戏引擎——本卷全部代码在 Node 26 与 headless Chromium 下运行。

三类读者,三类收获

下面把这四类人分别展开,你可以对照自己的处境挑一段读——它决定了你该走哪条阅读路径。

如果你读过卷一、想把内核接出画面。 你手里已经有一个能跑的 helio 内核,但它只会算、不会画。这一卷正好补上那道接缝:内核产出「数据 + 句柄」,渲染消费它们。你会看到卷一的世代句柄怎么变成资源引用、第 4.3 章的顶点布局怎么真正传上 GPU、第 15 章的跨线程同步点怎么落到「逻辑线程 ↔ 渲染线程」的真实边界。读完你得到的不是一堆孤立技巧,而是一条把内核数据喂给 GPU 的完整通路。

如果你有图形学基础、想理解引擎怎么组织渲染。 你可能已经会写着色器、懂管线,但面对「一帧到底怎么排」还是发虚。这一卷讲的是工程层:RHI 怎么把多后端统一成一套接口、帧图怎么用依赖 + 拓扑自动排 Pass、批次怎么按状态键排序、阴影怎么拟合级联。这些正是「会写着色器」和「能搭渲染器」之间的那层。

如果你是前端 / Web 图形开发者。 你对 WebGL2 / WebGPU 的 API 不陌生,但很少从「引擎」的角度把它们包起来:怎么让同一份渲染代码跑在两个后端上、怎么管理资源的上传与生命周期、怎么把命令录制分到多个线程。这一卷把这些平时散落在业务里的做法,收拢成一套可复用的抽象。

如果你已读过渲染原理、想做自研渲染器。 你懂「为什么这么画」,缺的是「怎么搭起来」的次序感。这一卷的 18 章本身就是一份施工顺序表:先立 RHI,再补资源与场景,然后才是材质、光照、帧图、后处理、2D、多线程,最后装配。每一章都能独立跑通,你可以在任何一步停下,把它接到自己的项目里。

与卷一《引擎内核》的关系

卷一和卷二不是「上半本 / 下半本」,而是**「地基 / 楼」**。卷二里的每一行渲染代码,几乎都能在卷一里找到它依赖的那根桩:

卷二要建的它接在卷一的哪一处
RHI 设备与多后端平台层 PAL 之上,新增 render/device
资源对象与生命周期复用第 6 章的世代句柄做资源引用
顶点与纹理上传消费第 4.3 章的顶点布局与对齐约定
场景图与变换复用第 8–9 章的矩阵与四元数
帧图的 Pass 编排复用第 3 章的拓扑排序与第 15 章的任务图
渲染线程与同步复用第 15 章的跨线程同步点

内核与渲染的接缝只有一句话:内核产出「数据 + 句柄」,渲染消费它们。 渲染层不认识 ECS 内部怎么存,它只拿到一份「这个句柄、这个变换、这个网格」的清单;内核也不知道 GPU 长什么样,它只把数据准备好。这条缝越清晰,两边越能各自演进——所以卷二往 render/ 里加 GPU 代码时,内核一行都不用改。

还没读卷一的读者,建议先去卷一目录 把内核过一遍;至少读完第 4 章(内存布局)、第 6 章(句柄)与第 15 章(同步),再回来看卷二会轻松很多。

本卷的差异化

和「讲图形学」或「讲某个引擎」的书比,本卷有三条很硬的不同:

  • 在 RHI 上从零实现。 我们不调用现成的渲染框架,而是自己定义设备、队列、命令编码器、管线状态、绑定组这一整套抽象,再为它写 WebGPU 与 WebGL2 两个真实后端,外加一个记录式的 NullRHI。你看到的是「引擎作者怎么写 RHI」,不是「怎么用某个 RHI」。
  • 每节可跑出真实产物。 每一节都产出一份能在本机运行、能截出图、能读到数字的东西:一张渲染出的图、一份 GPU 计时、一段命令录制的回放。结论不是「理论上会更快」,而是「本机实测快了这么多」。
  • 真实像素与计时结果。 凡是给出「这样画更好」的结论,背后都有一张真实渲染的图或一段真实计时。看到数字时,请连着它的测量条件一起看,而不是只记那个倍数。

本卷的可运行性口径

本套书的每一节都标注它属于哪一层,你据此知道「这一节的东西能不能在你机器上跑起来」:

层级含义你怎么验证
L1纯 TypeScript 逻辑,零运行时依赖Node 26 直接跑 .ts,或 vitest 跑单测
L2需要 GPU / 浏览器用 headless Chromium 跑(本卷大量使用)
L3只能做类型检查tsc --noEmit 通过
L4命令行不可复现正文会明确标注「需手动验证」
B性能基准跑出计时 JSON,数字写进正文对照表

这五层各自意味着什么,值得展开说清楚:

  • L1——能真跑。 排序键的比较、批次合并的算法、包围体的相交测试、帧图的依赖解析,这些都是纯 TypeScript,node src/xxx.ts 就能跑,配 vitest 就能断言。你看到的每一段 L1 代码,都是在本机跑过、被单测盯过的。
  • L2——需要 GPU / 浏览器。 这是本卷的主战场。凡是碰 GPU 的代码——设备、命令、管线、绘制——都得靠 headless Chromium 跑起来验证。本卷会给出统一的跑法,让你在本机也能复现每一张图。
  • L3——只能类型检查。 少数代码依赖只在特定后端才有的类型(比如某个扩展声明),能通过 tsc --noEmit 但无法直接执行。这类代码会被明确标注,正文会说明「为什么它跑不了」。
  • L4——命令行不可复现。 涉及真实硬件或真实帧率的观察(比如某个 GPU 上的实际帧率抖动),命令行里复现不了。正文会标「需手动验证」,并给出你该观察什么。
  • B——性能基准。 凡是给出「快了 N 倍」的结论,背后都有一份 B 级基准:它跑出计时 JSON,原始数字写进对照表。看到 B 级结论时,请连着原始数据一起看。

贯穿项目:《微光岛》从内核走进画面

卷一里那个「会走动的方块」,在这一卷里要真正被看见。全书仍然只有这一个项目:《微光岛》——一款低多边形 3D 收集冒险小游戏。卷二要做的,是给这个小岛接上一整套渲染能力:

画面需求牵出的技术点对应章节
小岛和角色被画出来RHI 设备、命令、管线2–5
地表、岩石、树木的几何顶点格式、程序化网格、纹理6
相机跟随角色、可拾取物体场景图、变换、相机与射线7
岛上成百上千个物体不掉帧视锥剔除、BVH、实例化合批8、9
不同表面有不同观感材质、着色器变体、参数绑定10、11
白天阳光、夜晚路灯光照模型、光源类型、集群光照12
树木与角色投下影子阴影贴图、级联阴影13
一帧有条不紊地排布帧图、Pass 依赖与资源生命周期14
画面调色、边缘平滑色调映射、抗锯齿、全屏 Pass 链15
背包与血条的 UI精灵批次、SDF 文本、合成顺序16
主线程不卡顿渲染线程、并行命令录制17
昼夜循环、可剖析、可收口渲染器装配、性能剖析18

范围红线:本卷做到「《微光岛》在真实 GPU 上被完整画出来」为止。物理、动画、音频等更上层的内容留给后续卷次。先把渲染这条链打通,是本卷唯一的目标。

关于基准数字的诚实声明

本卷会出现不少性能数字——绘制调用数、GPU 计时、内存占用、加速比。它们都来自作者本机实测,并附带测量条件。但它们有一个必须说清楚的边界:

这些数字是同机相对量级,绝对数值不可移植。 GPU 驱动、浏览器版本、后台负载都会影响结果;同一段渲染代码,换个批次大小、换个队列策略,帧时间可能差出一截。所以当你看到「合批后绘制调用降到原来的十分之一」时,请把重点放在方向而不是倍数上。

真正稳定的结论是那些量级差异,比如「逐物体绘制产生上千次绘制调用,合批后降到几十次」——这种结论不会因为环境微调而翻转。本卷会刻意把「方向性结论」和「具体倍数」分开表述:前者你可以直接采信,后者请当作「作者机器上的参考值」,并鼓励你在自己的机器上复现一遍。

三条阅读路径

本卷 18 章 54 节,一次读完大约 6 周(每天一小时),但不是每个人都该按同一种顺序读。下面三条路径覆盖了绝大多数人的需求。

路径 A:顺序通读(约 6 周)

最完整的一条。按顺序走完 18 章,每章的代码都亲手敲一遍。

第 1 章(总览)→ 第 2–5 章(RHI 四章)→ 第 6–9 章(资源与场景)
→ 第 10–13 章(材质、着色与光照)→ 第 14–16 章(帧图、后处理与 2D)
→ 第 17–18 章(多线程与综合)

适合谁:想把渲染引擎从头搭到尾、或打算自研渲染器的读者。第 18 章会把前面所有零件装配成一个能跑的渲染器,不要跳过。这条路径最慢,但拿到的是一套完整的、能自己复现的渲染器。

路径 B:只读 RHI 四章(约 2 周)

已经懂图形学、只关心「引擎怎么把 GPU 抽象出来」的话:

2.1 → 2.2 → 2.3 → 3.1 → 3.2 → 3.3 → 4.1 → 4.2 → 4.3 → 5.1 → 5.2 → 5.3

适合谁:时间有限、目标是「吃透 RHI 这一层」的读者。这 12 节从抽象设计一路走到多后端实现,是一条自洽的线。建议至少把第 3 章(命令与队列)和第 4 章(资源与内存)完整读——它们决定了后面所有性能结论的地基;跳过它们,第 14、15 章的实测数字会变成一堆没有根据的结论。

路径 C:直奔帧图与后处理(约 2 周)

只想知道「一帧怎么排、画面怎么调」的话:

1.1 → 14.1 → 14.2 → 14.3 → 15.1 → 15.2 → 15.3

适合谁:已经有一个能画的渲染器、想搞清「帧图与后处理怎么组织」的读者。这条路径最短,但会牺牲 RHI 的「为什么」。建议把 1.1 一帧都发生了什么 当作前置先读,它给了整条 CPU / GPU 时间线的全貌。

路径 D:按问题查(随时)

不打算通读,只在遇到具体问题时翻对应章节。

画面不出现 / 全黑 → 第 3、5 章;物体位置不对 → 第 7 章;帧率低 → 第 8、9 章
材质不生效 → 第 10、11 章;光照发灰 → 第 12 章;影子抖动 → 第 13 章
后处理花屏 → 第 14、15 章;UI 遮挡错乱 → 第 16 章;主线程卡顿 → 第 17 章

适合谁:已经有一个能跑的渲染器、正被某个具体问题卡住的读者。下节「常见问题速查」就是为这条路准备的——它把「你想解决的问题」直接映射到「去看哪一节」。

18 章分组清单

下面把 18 章按五个部分分组,每章链到它的第 1 节。想跳读时,从这里直接进。

第一部分:架构与 RHI(第 1–5 章)

先看一帧的全貌,再花四章把 GPU 抽象层从零建起来。

第二部分:资源与场景(第 6–9 章)

把几何、纹理、场景、相机接上,再解决「画哪些、按什么顺序画」。

第三部分:材质、着色与光照(第 10–13 章)

让画面「有材质、有光、有影」。

第四部分:帧图、后处理与 2D(第 14–16 章)

把一帧的 Pass 编排成图,加上全屏特效,再接上 UI。

第五部分:多线程与综合(第 17–18 章)

让它跑满多核,最后把全部零件装成一个能画的渲染器。

  • 第 17 章 多线程渲染 —— 渲染线程模型与命令缓冲、OffscreenCanvas 并行录制、与 Job System 对接
  • 第 18 章 综合 —— 渲染器装配与场景接入、昼夜循环与光照表现、渲染性能剖析与收口

周计划表

按路径 A 的顺序通读,可以照下面这张表安排节奏(每天约一小时):

周次章节本周焦点本周产物
第 1 周第 1–3 章一帧全貌与 RHI 抽象、命令与队列能录一段命令并提交
第 2 周第 4–5 章GPU 资源、内存池与多后端两个后端画出同一张三角形
第 3 周第 6–9 章几何纹理、场景相机、剔除与批次一个能剔除、能排序的场景
第 4 周第 10–13 章材质、着色器、光照与阴影一个有光有影的模型
第 5 周第 14–16 章帧图、后处理与 2D / UI一条带后处理的完整帧
第 6 周第 17–18 章多线程渲染与综合一个能跑的渲染器与《微光岛》画面

如果只有零散时间,可以只挑第 2–5 章(RHI)或第 14–15 章(帧图与后处理)这两段——它们各自成篇,是整卷最容易被单独拿走的两块。

常见问题速查

你想解决的问题去看
屏幕全黑,什么都没画出来3.1 、5.1
同一份代码想在两个后端都跑2.1 、5.2
资源删了但 GPU 还在用、偶发花屏3.3 、4.3
纹理上传后是黑的 / mipmap 有缝4.2 、6.2
物体位置或朝向不对7.1 、7.2
相机画面裁剪、拾取点不中7.3
远处物体太多、帧率上不去8.1 、8.2
大量同类物体逐个体绘制太慢9.3 、8.3
绘制顺序乱、透明物穿透9.1
每帧重复设状态、开销大9.2
改一个开关就多出一堆着色器变体10.2 、10.3
着色器参数绑定老是漏11.1 、11.2
着色器编译报错却看不出哪一行11.3
光照发灰、明暗不对12.1 、12.2
光源一多就卡12.3
阴影锯齿重、接缝明显13.1 、13.2
开了阴影帧率掉一半13.3
Pass 之间依赖理不清、改一处崩一片14.1 、14.3
后处理链花屏或没效果15.1 、15.2
后处理把帧率吃光了15.3
精灵一多就掉帧16.1
UI 文字糊、矢量图标发虚16.2
UI 被 3D 挡住或挡反了16.3
录制命令卡主线程17.1 、17.2
多线程录制和内核 Job System 对不上17.3
想把所有零件装成一个渲染器18.1 、18.3

怎么用这份索引

  • 想系统学:走路径 A,从第 1 章 1.1 开始。
  • 想抓重点:走路径 B,从第 2 章 2.1 开始,把 RHI 四章吃透。
  • 想查问题:直接用上面的「常见问题速查」,或跳到对应小节。
  • 想配代码:每一节的代码块都标了层级与来源文件,L1 的可以直接复制出来在 Node 26 上跑,L2 的按正文给的 headless Chromium 跑法复现。
  • 每篇正文末行都有「上一节 / 下一节」导航,也可以随时回到本页或卷索引 。

相关阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「engine」更多文章

  1. 《游戏引擎实现原理》工程与实战 目录
  2. 《游戏引擎实现原理》9.3 选型与自研的判断标准
  3. 《游戏引擎实现原理》9.2 同一个特性在不同引擎里的实现路径