概念页
光栅化
Rasterization
光栅化(也叫扫描转换)把屏幕空间里带深度和着色数据的顶点,转换成三角形覆盖的像素(片元),交给像素处理阶段。它是几何处理和像素处理之间的同步点:三个顶点在这里组成三角形。
两个子阶段
- 三角形设置 (Triangle Setup),也叫图元装配:计算三角形的微分、边方程等数据,用于遍历和插值。由固定功能硬件完成。
- 三角形遍历 (Triangle Traversal):逐个检查像素中心(或采样点)是否被三角形覆盖,为重叠部分生成片元 (fragment)。片元的深度和其他着色数据由三个顶点的数据插值得到,透视校正插值也在这里完成。
点和线同样可以光栅化,只是三角形最常见,所以子阶段名字里带"三角形"。
怎样算"在三角形里"
取决于 GPU 管线的配置:
- 单点采样:像素中心在三角形内,就算这个像素在内。最简单。
- 多采样:每个像素多个采样点,即超采样 (SSAA) 或多重采样 (MSAA) 抗锯齿(RTR4 第 5.4.2 节)。
- 保守光栅化 (Conservative Rasterization):只要像素有一部分和三角形重叠就算在内(RTR4 第 23.1.2 节)。
在游戏开发中的意义
- 采样方式直接影响锯齿和抗锯齿方案的选择。
- 保守光栅化常用在需要"不漏掉任何覆盖"的场景,比如体素化等 GPU 算法。
- 光栅化成本和三角形覆盖的像素数量、三角形数量都有关,大量细小三角形会降低效率。
GEA 的视角:扫描线、片元与 quad(卷 II 11.3.10)
先用扫描线理解
GEA 先用经典扫描线算法讲光栅化:找出三角形最上和最下的顶点,过剩下那个顶点画一条水平线,把三角形分成平顶和平底两个子三角形;对每个子三角形从上到下逐行(扫描线)计算左右边界 、,得到这一行内部的一段连续像素(卷 II 11.3.10.1)。找到像素后可以填纯色(平面着色),也可以做更复杂的着色,甚至只记下覆盖关系留给之后用。
光栅化规则
网格中相邻三角形共享边,共享边上的像素不能画两次。OpenGL 和 DirectX 用左上规则:像素完全在三角形内,或恰好落在三角形的上边或左边时才算覆盖;某个三角形没画的右边、下边,会由把它当作上边、左边的邻居三角形画(卷 II 11.3.10.2)。(原书问题:Direct3D 明确规定左上规则(MS Learn "Rasterization Rules (Direct3D 11)");OpenGL 规范只要求共享边上的片元恰好由其中一个多边形产生,并未规定必须用左上规则,且 OpenGL 窗口坐标原点在左下(OpenGL 4.6 规范 14.6.1 "Basic Polygon Rasterization")。)边函数形式的判定见 硬件光栅化与透视校正插值。
画家算法为什么不够
- 把三角形从后往前排序再光栅化,近的覆盖远的,这就是画家算法。
- 问题在于"三角形的深度"没有定义:三角形上每个点深度都不同,用最近顶点、最远顶点还是重心都可能出错;三角形相互穿插时,任何排序都不对(卷 II 11.3.10.3)。
片元是点而不是小多边形
- 可以把光栅化看成把三角形拆成像素大小的碎片,即片元 (fragment);只要按片元而不是按三角形排序深度,穿插问题就迎刃而解。
- GEA 强调更准确的理解是:片元是三角形表面上的一个无穷小的点,每个片元有唯一深度;渲染结束后离相机最近的那些片元的位置,正是可见性问题的解(卷 II 11.3.10.4)。MSAA 更说明了"像素不是小方块",而是对连续二维信号的采样(见 抗锯齿)。
- 实际并不排序所有片元,而是用深度缓冲增量地解决,见 深度缓冲。
真实 GPU 怎么做
- GPU 不逐行扫描,而是计算像素在三角形平面上的重心坐标来判断内外,同一组坐标还能用于插值深度和其他属性(卷 II 11.3.10.6,见 硬件光栅化与透视校正插值)。
- 光栅化以 2×2 的 quad 为单位,以便用相邻片元的差分求纹理过滤所需的梯度。GEA 把它概括为两遍:先找三角形覆盖了哪些 quad,再算 quad 中四个像素的重心坐标,三个坐标都为正即在内部(卷 II 11.3.10.8)。这正是三角形接近像素大小时硬件光栅化效率低、Nanite 改用软件光栅化的原因(见 Nanite 虚拟化几何体)。
出处
- realtime_rendering_4ed.pdf 第 2 章 The Graphics Rendering Pipeline
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 11 章 11.3.10 节
相关页面
图形学渲染管线Rendering Pipeline渲染管线是实时图形的核心:给定虚拟相机、三维物体、光源等,把场景转换成一张二维图像。RTR4 把它粗分为四个功能阶段:应用、几何处理、光栅化、像素处理,各阶段并行执行,整体速度由最慢的阶段决定。图形学坐标空间Coordinate Spaces顶点从模型到屏幕要依次经过模型空间、世界空间、观察空间、裁剪空间、标准化设备坐标 (NDC)、窗口坐标。每一步变换都有明确目的,大部分可以用 4×4 矩阵表示并相乘合并。图形学深度缓冲Z-Buffer深度缓冲是几乎所有图形硬件用来解决可见性的算法:为每个像素存一个当前最近图元的深度值,新片元更近才写入颜色和深度。它简单、和图元数量成线性关系、允许大多数图元以任意顺序绘制,但不能直接处理半透明。图形学抗锯齿Antialiasing渲染本质上是采样,采样频率不足就会混叠(锯齿、闪烁的"萤火虫"、车轮倒转)。屏幕空间抗锯齿在每个像素取多个样本并加权求和:超采样最直接但最贵,MSAA 每像素只着色一次,时间抗锯齿 (TAA) 把样本分散到多帧,形态学方法 (FXAA/SMAA) 作为后处理重建边缘。没有一种方法在所有方面最好。图形学分簇着色Clustered Shading分簇着色把整个视锥(而不只是屏幕平面)划分为三维单元——簇 (cluster),按簇建立光源列表。与依赖场景几何深度的分块着色不同,簇的划分与几何无关,可只由视图和光源计算,因此对相机位置的性能波动更小、对深度不连续更稳健,并为不透明、透明、体积物体提供统一的光照方案。它同样可配合前向或延迟着色,并衍生出 z-binning、光源树等更省内存的变体。本页还汇总了各类多光源方案的对比。图形学硬件光栅化与透视校正插值Hardware Rasterization & Perspective-Correct InterpolationGPU 光栅化由三角形设置与三角形遍历组成。硬件用每条边一个边函数判断采样点是否在三角形内,利用其增量性质按瓦片分层遍历,用左上规则决定恰好落在边上的像素归属,用保护带避免大多数裁剪。边函数的值恰好是子三角形面积的两倍,因此遍历顺带得到重心坐标;透视投影下需要线性插值 a/w 与 1/w 再逐像素相除,得到透视校正插值。本页还介绍 2×2 quad 与辅助像素、保守光栅化。图形学多边形三角化Polygon Triangulation模型数据很少恰好是渲染需要的格式。图形 API 和硬件都针对三角形优化,所以复杂多边形要先剖分 (tessellation),最常见的是三角化 (triangulation)。本页讲三维数据的来源、三角化算法(耳切法、凸剖分、模板缓冲法)、四边形对角线选择与纹理扭曲,以及边缘裂缝和 T 型顶点。图形学像素着色器Pixel Shader像素着色器(OpenGL 里叫片元着色器)对光栅化产生的每个片元运行,用插值后的顶点数据算出颜色,也可以输出不透明度、修改深度或直接丢弃片元。多渲染目标让它一次输出多组数据,催生了延迟着色。它通常只能写自己所在的像素,但能通过 2×2 quad 拿到相邻像素的导数。图形学体素Voxels体素是"体积元素",表示均匀三维网格中的一块空间,位置由网格索引隐含。体素是存储体积数据的传统方式,可存占用位、密度、颜色、法线、有向距离等。数据量按分辨率立方增长,常用稀疏体素八叉树 (SVO) 等结构压缩;可由 GPU 体素化生成,并通过光线投射、转多边形、移动立方体或等值面/水平集光线追踪来渲染(RTR4 13.10 节)。游戏开发 · UE5Nanite 虚拟化几何体Nanite Virtualized GeometryNanite 是 UE5 的虚拟化几何体 (Virtualized Geometry) 系统:导入时把网格切成分层的三角形簇 (Cluster),渲染时按相机视角逐簇选择细节层次并无缝拼接,按需从磁盘流送,并在绕过传统绘制调用 (Draw Call) 的独立通道中渲染,使帧预算不再受多边形数、绘制调用和网格内存约束。图形学空间数据结构Spatial Data Structures空间数据结构把几何体按 n 维空间组织起来,通常是层次化的树,使"几何体是否重叠"一类查询从 O(n) 降到大约 O(\log n)。常见类型有包围体层次 (BVH)、BSP 树(轴对齐的 k-d 树与多边形对齐两种)、四叉树/八叉树(含松散八叉树),以及更偏向组织模型关系的场景图。它们是剔除、光线求交、碰撞检测等加速算法的基础。图形学纹理过滤与 MipmapTexture Filtering & Mipmap纹理在屏幕上被放大时需要插值,被缩小时一个像素覆盖许多纹素,必须预先滤波才能避免混叠。放大用最近邻、双线性或双三次;缩小的主流方案是 mipmap + 三线性插值,斜视角下用各向异性过滤减少过度模糊。注意:过滤纹理值只在输入与着色结果线性相关时等价于过滤最终颜色。