笔记04 技术美术百人计划 图形 1.1~1.3
和《Unity Shader 入门精要》有所重叠,所以速通。
图形 1.1 渲染流水线
一、应用阶段(Application Stage)
CPU在本阶段的具体的工作内容和优化目的:
准备场景数据的细化
- 场景物体:不仅包括网格数据,还需准备其变换数据(位置、旋转、缩放)。
- 摄像机:需要设置视锥体参数(如FOV、远近裁切平面),这决定了哪些物体能被看见。
- 光源与阴影:这是重要的补充。需要设置光源类型(平行光、点光源等)及其参数,并配置阴影信息(如是否投射阴影、阴影强度、级联参数)。CPU会指挥GPU为需要的光源预先渲染阴影贴图(Shadow Map)。
粗粒度剔除与加速算法
- 目的:在发出Draw Call前,尽可能剔除不可见的物体,以极大减轻GPU负担。
- 常见技术:文章提到了遮挡剔除(Occlusion Culling) 和利用空间加速结构(如八叉树、BSP树、BVH)进行的可见性裁剪。这解释了“为什么在GPU有裁剪后,CPU还要做剔除”——为了更早、更高效地丢弃整组物体。
设置渲染状态的上下文
- 渲染顺序:需明确不透明物体通常从前往后画(利用深度测试快速丢弃),而半透明物体通常从后往前画(以实现正确的颜色混合)。这补充了设置“渲染状态”时的具体考量。
- 渲染路径(Rendering Path):文章提到了 Forward(前向渲染) 和 Deferred(延迟渲染) 这两种核心模式。这是现代游戏渲染中至关重要的选择,决定了光照计算的方式和性能,是后续学习URP/HDRP管线的基础。
二、光栅化阶段(Rasterizer Stage)的抗锯齿
三角形遍历生成片元的阶段一个关键任务:抗锯齿(Anti-Aliasing)。
- 原因:由于像素是离散的,渲染斜线或曲线时会产生锯齿状的“楼梯”边缘。
- 常见技术:
- SSAA(Super Sampling Anti-Aliasing,超级采样抗锯齿):以更高分辨率渲染,再下采样到屏幕分辨率,效果最好但开销最大。
- MSAA(Multi-Sample Anti-Aliasing,多重采样抗锯齿):在光栅化阶段对每个像素的多个子样本进行覆盖测试,是效果和性能的折中方案,非常常用。
- FXAA/TXAA(Fast Approximate Anti-Aliasing / Temporal Anti-Aliasing,快速近似抗锯齿):属于后处理技术,通过对最终图像进行滤波来平滑边缘,速度快。
三、逐片元操作(Per-Fragment Operations)
此阶段按顺序通常包括:
- 像素着色器(Pixel Shader)/片元着色器:计算片元颜色。
- 透明度测试(Alpha Test):如果片元的Alpha值低于阈值,则直接丢弃该片元。这是一种硬裁剪。
- 模板测试(Stencil Test)。
- 深度测试(Depth Test)。
- 混合(Blending):对通过所有测试的片元,将其颜色与帧缓冲区中已有的颜色进行混合(半透明效果)。
四、渲染管线的延伸:后处理(Post-Processing)
- 定义:在整个渲染管线结束,得到一张完整的“场景图”后,对其进行的全屏幕图像处理。
- 操作对象:对最终的颜色缓冲区(或渲染纹理)进行像素操作。
- 常见效果:Bloom(泛光)、HDR色调映射、颜色校正、运动模糊、屏幕空间环境光遮蔽(SSAO),以及上文提到的FXAA等。
图形 1.2.1 向量基础 | 图形 1.2.2 矩阵运算 | 图形 1.2.3 MVP矩阵运算
参考 爱渲染的镜子 的 1.2 数学基础 —— 向量, 1.3 数学基础 —— 矩阵计算, 1.4 数学基础 —— MVP 矩阵 对读书笔记03《Unity Shader入门精要》进行补充。
一、向量部分的补充与不同视角
几何意义和严格定义:
- 向量的严格定义:特别强调向量没有位置,只有大小和方向。其坐标表示的是从原点(0, 0, 0)到该点的位移,因此向量可以平移而不变。
- 向量与点的深刻区分:
- 点:有绝对位置。
- 向量:描述相对位移。
- 联系:任何点可以看作从原点指向该点的向量。
- 零向量 (Zero Vector):是唯一大小为零、没有方向的向量。它表示“没有位移”,不是一个点。
- 对点积的强调:特别突出了点积在兰伯特光照模型中的应用,直观展示了
Normal · Light的值如何直接决定漫反射的明暗(1为最亮,-1为最暗)。这是对原有笔记中“投影”应用的具体化。
二、矩阵的背景与解释
矩阵的起源:矩阵最初是为了求解线性方程组而发明的。资料中展示了如何将方程组
ax + by = e; cx + dy = f写成A * X = B的矩阵形式,这有助于理解矩阵乘法的设计动机。复合变换顺序的直观解释:原有笔记中提到约定顺序是“先缩放,再旋转,最后平移”。
- 错误的顺序(如先平移后缩放) 会导致物体像“绕地球公转”一样绕原点旋转缩放,结果很不自然。
- 核心原理:缩放不改变原点;旋转改变轴向但原点不变;平移改变原点。按“缩放->旋转->平移”顺序,每一步变换都是在当前物体自身的局部坐标系中直观进行的。
三、MVP矩阵
MVP矩阵的定义与作用:
- M (模型矩阵, Model Matrix):负责将顶点从模型空间变换到世界空间。对应原有笔记中的“模型变换”。
- V (观察矩阵, View Matrix):负责将顶点从世界空间变换到观察(摄像机)空间。对应原有笔记中的“观察变换”。资料特别指出,观察空间通常使用右手坐标系(Z轴指向摄像机前方)。
- P (投影矩阵, Projection Matrix):负责将顶点从观察空间变换到裁剪空间。对应原有笔记中的“投影变换”。它的主要目的是判断顶点是否在可见范围内,为后续的透视除法做准备。
视图矩阵 (V) 的推导思路:
- 视图矩阵实际上是将“摄像机在世界空间中的变换”取逆,得到的矩阵。
- 如果摄像机在世界中的变换是先旋转(R),再平移(T),那么对应的视图矩阵就是:V = (T * R)⁻¹ = R⁻¹ * T⁻¹。即先反向平移,再反向旋转。
投影矩阵 (P) 的核心目的:
- 不是真正的投影,而是为投影做准备。
- 它对x, y, z分量进行缩放,并用齐次坐标的 w分量作为范围值。裁剪空间中的可见范围通常是
-w ≤ x, y, z ≤ w。这解释了为什么需要齐次坐标。
图形 1.3 纹理的秘密
参考 苏格拉没有底。 的 1.3 纹理的秘密 对读书笔记06《Unity Shader入门精要》进行补充。
一、纹理的本质定义
纹理是可以供Shader读写的结构化存储形式(一个容器)。
- 二维纹理:
(i, j, k)——(i, j)定位像素位置,k对应 RGBA 通道。- 纹理不仅包含存储的数据,还包含纹理采样的设置(寻址模式、过滤模式等)。
现代GPU视角(引自《Games101》):
Texture = 一块内存 + 滤波/范围查询
这一定义揭示了纹理的本质:它不只是“一张图”,而是一套支持快速范围查询的数据结构。Mipmap、各向异性过滤等,都是这套“查询”能力的体现。
二、纹理管线模型
1 | 模型空间位置 |
关键概念补充:
投影函数
- 摄像机投影无关,它是建模师在DCC软件中展UV时使用的函数(平面、圆柱、球形投影)。
- 渲染管线中它已“固化”为顶点数据中的UV坐标,不再实时计算。
- 特例:环境贴图等特殊渲染方式会使用其他投影函数。
通讯函数
- 对应原有笔记中
_MainTex_ST对UV的缩放和平移操作。 - 它是Shader开发者唯一需要关心的纹理管线阶段。
- 对应原有笔记中
依赖纹理读取(重要性能概念)
- 定义:在片元着色器中,不是直接使用顶点着色器传过来的UV,而是经过计算(哪怕是简单的UV交换)再采样。
- 后果:破坏GPU缓存一致性,造成性能损失。
- 最佳实践:将UV偏移计算放在顶点着色器,让插值后的UV直接用于片元采样。
三、Shader 中三种变量类型
底层图形API(OpenGL)的变量语义,有助于理解数据如何在CPU与Shader、顶点与片元之间流动:
| 变量类型 | 作用域 | 生命周期/修改者 | 典型用途 |
|---|---|---|---|
| Uniform | Vertex & Fragment | 外部Application设置,Shader只读 | 变换矩阵、光照参数、纹理对象(如 _MainTex) |
| Attribute | 仅Vertex Shader | 每个顶点不同,由Vertex Buffer提供 | 顶点位置、法线、切线、UV |
| Varying | Vertex → Fragment 插值传递 | Vertex Shader写入,Fragment Shader读取 | 经过插值的世界坐标、UV、法线 |
与Unity的对应:
- Unity将Attribute和Varying封装,你直接在Vertex Shader输入结构中看到的是顶点数据,输出结构中的变量自动成为Varying。
sampler2D类型的纹理变量属于Uniform。
四、纹理采样设置的原理
【情况A:纹理太小 → 需要放大(Magnification)】
| 模式 | 采样方式 | 画面表现 | 性能 | 备注 |
|---|---|---|---|---|
| 最邻近 | 取最近的1个纹素 | 像素风格,锯齿硬边 | 最快 | 硬件内置 |
| 双线性插值 | 取周围4个纹素,二维线性插值 | 平滑,但放大仍模糊 | 中等 | 硬件内置 |
| 立方卷积插值 | 取周围16个纹素,考虑变化率 | 比双线性更锐利 | 慢 | 又称“双向三次插值” |
| Q光滑曲线插值 | 使用光滑曲线对2×2纹素组插值 | 介于双线性与立方卷积之间 | 较慢 | 不是硬件选项,是着色器手写算法,解决硬件24.8定点数插值精度不足产生的色带问题 |
【情况B:纹理太大 → 需要缩小(Minification)】
| 方案 | 原理 | 问题 | 本质 |
|---|---|---|---|
| 最邻近/双线性缩小 | 直接对一个像素覆盖的多个纹素之一或混合采样 | 严重走样(闪烁、摩尔纹) | 点查询,不满足范围查询需求 |
| Mipmap | 预生成分辨率减半的图像金字塔,根据距离选择层级 | 过度模糊(Overblur),斜视角尤其明显 | 范围查询,快但不准,仅支持正方形区域 |
| 各向异性过滤 | 查询矩形区域(非正方形) | 性能开销随“几X”成倍增加 | 各向异性过滤是一类技术的总称,非单一方法 |
| 积分图(Summed-Area Table) | 预计算积分图,常数时间查询任意矩形区域 | 内存开销巨大 | 各向异性过滤的一种实现方式 |
| EWA过滤 | 查询椭圆区域 | 计算最重 | 最高质量过滤 |
Mipmap 层级选择机制(GPU内部):
- GPU 不是逐像素计算Mipmap等级,而是将像素组织成 2×2 的块并行执行。
- 通过计算这个2×2块在纹理空间覆盖的最长边的长度,决定使用哪一级Mipmap。
- 这正是片元着色器中可以访问
ddx/ddy(导数指令)的原因——它们用于估算像素在屏幕空间的变化率。
Mipmap 存储开销的直观理解(Games101):
- 比原图多1/3。
- 想象一个田字格:将初始纹理放在左上、右上、左下三格(蓝色),下一级纹理放在右下格(绿色)。依此类推,所有层级共占4个大格,初始图占3格,额外占1格 = 1/3。
各向异性过滤的硬件实现:
- 现代硬件并未预生成RipMap,而是重用已有的Mipmap硬件。
- 方法:将屏幕像素反向投影到纹理空间,得到一个不规则四边形。
- 通过该四边形的最短边确定Mipmap层级(标准Mipmap用最长边,此方法使采样区域更小、更清晰)。
- 沿较长边方向创建一条各向异性轴,按照过滤层级沿该轴多次采样,最后混合结果。
- “几X”表示沿长边的采样次数(如4X、8X、16X)。
(我也听不懂。《RTR4》中也有提到)
五、纹理性能优化
| 瓶颈位置 | 根本问题 | 优化思路 | 具体方法 |
|---|---|---|---|
| CPU侧 | GPU渲染速度快于CPU提交命令速度,Draw Call成为瓶颈 | 减少Draw Call | • 纹理图集(Texture Atlas) • 纹理数组(Texture Array) • 约束纹理 |
| GPU侧 | 纹理太大,显存带宽成为瓶颈 | 减少单次传输数据量 | • 纹理压缩(Texture Compression) - 移动端:ASTC、PVRTC - PC端:DXT/BC系列 |
纹理压缩的核心认知:
- 压缩纹理不能直接在CPU端解压为精确RGB值。
- GPU可以直接采样压缩后的数据,大幅降低传输压力。
- 前提:纹理长宽通常是2的幂,非2的幂纹理无法被硬件压缩格式有效处理。
六、其他常见纹理类型
| 纹理类型 | 存储内容 | 是否改变顶点位置 | 特点与用途 |
|---|---|---|---|
| 立方体贴图(Cubemap) | 6张正方形纹理,模拟无限远环境 | 否 | 解决球面环境映射的扭曲问题,用于天空盒、环境反射 |
| 凹凸贴图(Bump Mapping) | 相对高度(灰度图) | 否 | 通过高度差重新计算法线,扰动光照,顶点位置不变 |
| 法线贴图(Normal Mapping) | 法线方向(压缩为RGB) | 否 | 凹凸贴图的现代替代方案,直接存储法线 |
| 位移贴图(Displacement Mapping) | 相对高度(与凹凸贴图同源) | 是 | 真正移动顶点位置,产生轮廓阴影变化,常配合曲面细分使用 |
区分技巧:
观察阴影——位移贴图会因顶点真实移动产生正确的阴影轮廓变化,凹凸贴图不会。
动态曲面细分:
DirectX中,可以先使用粗糙三角形网格,在应用位移贴图时检测是否需要将三角形拆分得更细,以匹配纹理细节。这是后续高级课程的内容。
- 标题: 笔记04 技术美术百人计划 图形 1.1~1.3
- 作者: 铁名_IronName
- 创建于 : 2026-02-11 14:15:47
- 更新于 : 2026-02-24 10:10:32
- 链接: https://blog.ironname.top/2026/02/11/笔记04-技术美术百人计划/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。