# 光栅化：游戏画面“快”的秘诀，也是它“假”的根源

从"每个三角形各画各的"出发，理解光栅化为什么快、以及为什么阴影/反射/折射这些跨物体效果很难做

> 光栅化 · 实时渲染原理 · 全局光照 · 约 5 分钟 · 07 月 08 日

## 本篇要点

1. 光栅化只有两步：把三角形投影到屏幕，然后判断哪些像素落在里面——操作简单所以极快。
2. 光栅化的核心假设是每个三角形独立处理，画完就丢——这恰好让它无法自然处理跨物体的光学现象。
3. 阴影、反射、折射、间接光在光栅化里需要额外 hack（阴影贴图、环境贴图等），效果有限且容易露馅。
4. 光线追踪翻过来从像素出发模拟光线路径，这些效果自然出现——但计算量爆炸，直到近年硬件加速才走进实时游戏。

---

如果你玩过近十年的 3A 大作，一定感受过画面质感的飞跃——但如果你仔细对比游戏和电影级 CG，会发现一个微妙但顽固的差异：游戏里的阴影总是偏"硬"、玻璃只有个大概的反光、墙角暗部永远不够自然。这背后不是技术团队偷懒，而是实时渲染三十年来一直用的一把利器——**光栅化**——在骨子里就决定了这些效果很难做。

## 光栅化到底在干什么？

要理解光栅化，先想一个问题：一个由几百万个三角形构成的 3D 场景，怎么变成你屏幕上那 1920×1080 个像素的颜色？

光栅化的回答很直接，只有两步：

**第一步，投影。** 把每个三角形的三个顶点从 3D 空间"拍扁"到 2D 屏幕上——就像用投影仪把幻灯片打到墙上。这个操作叫透视投影，就是模拟人眼的"近大远小"。

**第二步，填像素。** 对于每个投影后的 2D 三角形，判断屏幕上哪些像素的中心点落在它里面，然后给这些像素涂上颜色。这个过程叫"采样"——说白了就是问：这个像素算不算属于这个三角形？[1][2]

用伪代码表示就是：

```
for (每个三角形 in 场景) {
    把它的三个顶点投影到屏幕坐标
    for (每个像素 in 屏幕) {
        if (像素中心落在三角形内) {
            给这个像素涂上三角形的颜色
        }
    }
}
```

这就是最朴素的光栅化。[3]

![光栅化与传统光栅化渲染管线的流程示意](https://www.scratchapixel.com/images/rasterization/raytracing-raster2.png)

## 为什么它这么快？

对比一下另一种渲染方式——光线追踪——你就明白了。

光线追踪是"每个像素出发，向场景里射一条光线，看它撞到谁"。它的循环是：

```
for (每个像素 in 屏幕) {
    发射一条光线穿过这个像素
    for (每个三角形 in 场景) {
        检测光线是否与这个三角形相交
    }
    取最近的交点，涂颜色
}
```

两层循环完全颠倒。[3] 光线追踪的致命问题是：**每一条光线都要跟场景里所有三角形做相交测试**——场景有 100 万个三角形，每个像素就要算 100 万次。这还只算一次弹射，如果要算反射、折射，光线要弹好几下，计算量翻倍再翻倍。

而光栅化为什么快？因为它的操作极其简单：

- **投影**就是矩阵乘法，对每个顶点算一次，高效且可并行。
- **填像素**的核心是"点是否在三角形内"——用几何上的叉积就能判断，不需要复杂的"光线-几何体"相交计算。[2]
- 不需要和场景里其他三角形打交道：**每个三角形独立处理，画完就丢。**

所以 GPU 设计成"一次处理一大堆三角形"的并行架构，把光栅化跑得飞起——60 帧每秒，每帧几毫秒，轻松搞定。[1]

## 但"快"的代价是什么？

问题就出在"每个三角形独立处理"这句话上。

3D 场景里有一个茶壶、一堵墙、一盏灯，用光栅化渲染时，它们**各自画各自的**。茶壶不知道自己挡住了墙上的光，墙不知道自己应该反射茶壶的影子，暗处不知道自己应该接收从天花板弹过来的间接光。

但现实世界不是这样运作的。你在房间里看到的一切，都是光在物体之间不断弹射的结果——阳光照到地板，地板反射到天花板，天花板再反射到桌底——这叫**全局光照**。阴影、反射、折射、间接光照，所有这些"让画面突然变真"的效果，本质上都是**跨物体的光学现象**，需要知道"别的物体在干什么"。[4]

光栅化的逻辑是"先画完一个物体，再画下一个"，它天生没有机制去问："哎，这个像素的颜色，是不是受那个角落里的物体影响？"

## 你能看到的"假"

这个缺陷是万恶之源。游戏开发者不得不用各种"奇技淫巧"来补救：

- **阴影**：要额外从光源视角再渲染一遍场景（叫"阴影贴图"），然后把结果贴回主画面。但这样做出来的阴影很容易有锯齿、抖动，光源一动就露馅。[5]
- **反射**：没办法让物体自己反射周围环境，只能预先烘焙一张"环境贴图"贴在表面，或者用"屏幕空间反射"——只能反射屏幕里已经画好的东西，屏幕外的一概看不到。
- **间接光**：墙角暗部应该接收从周围墙壁弹过来的光，但光栅化根本不知道有这回事，只好粗暴地加一个"环境光"常数，让暗部不完全是黑的——但这显然不是物理正确的。
- **折射**：玻璃后面的物体会扭曲，这需要算光线穿过玻璃的路径，没法用填三角形的方式搞出来。

这些效果不是完全做不了，而是**每一种都要单独搞一套复杂的 hack**，而且效果还有限——画面"看上去还行"，但跟真实世界一比就露怯。[4][5]

## 所以画面"突然变真"的那一步是什么？

光线追踪把这套逻辑翻了过来：不是"逐个物体画到屏幕上"，而是"从每个像素出发，模拟光线在场景里的真实路径"。阴影、反射、折射、间接光，在这些光线路径中**自然出现**，不需要额外 hack。[3]

代价就是计算量爆炸——直到最近几年，GPU 硬件终于加入了专门的光线追踪加速单元（英伟达 RTX 系列），才让实时游戏里开始真正跑起光线追踪。

但那是下一篇的内容了。今天你只需要记住：**光栅化快，是因为"各画各的"；光线追踪真，是因为"模拟光线怎么走"——而"跨物体的光学效果"，正是区分这两者的分水岭。**

## 来源

1. [Scratchapixel — 光栅化算法完整介绍，含伪代码与核心原理](https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/overview-rasterization-algorithm.html)
2. [GAMES101 课程笔记 — 光栅化中三角形覆盖测试与采样](https://caterpillarstudygroup.github.io/GAMES101_mdbook/Rasterization/Rasterization.html)
3. [Scratchapixel — 同一页面中对比光线追踪与光栅化的循环结构](https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/overview-rasterization-algorithm.html)
4. [Scratchapixel — 全局光照、反射、折射等效果为何难以用光栅化实现](https://www.scratchapixel.com/lessons/3d-basic-rendering/rendering-3d-scene-overview/light-simulator.html)
5. [Imagination 技术博客 — 对比光栅化阴影贴图与光线追踪阴影的差异](https://blog.imaginationtech.com/hybrid-rendering-for-real-time-lighting/)

---

原文：https://pangzhengboyin.com/articles/rasterization-fast-but-fake-54be74fb

> **庞征博引** · 想学的，慢慢都会
>
> 庞征博引是把想学的东西写成连载的 AI 学习工具。说出想学什么，它会先了解你的基础，再把主题写成一篇篇 5–10 分钟能读完的文章；边读边问，接下来学什么跟着你走。这篇就是这样写出来的。
>
> 开始你自己的连载 → https://pangzhengboyin.com
