VCI - 13: 着色 (Shading)

课程: 北京大学视觉计算 (Visual Computing) 2025秋季 章节: 第13章 着色 内容: 光源、反射模型、照明方程、着色算法、可见性、阴影、非照相写实渲染

目录

  1. 着色概述
  2. 光源
  3. 反射与照明模型
  4. 着色算法
  5. 可见性问题
  6. 阴影
  7. 非照相写实渲染

1. 着色概述

1.1 什么是着色

着色 (Shading) 是对几何体进行着色,使其看起来像具有特定材质性质并在光照下反应的物体。

1.2 着色的三个关键要素

  1. 光传输 (Light Transport) — 光线如何从光源传播到表面
  2. 反射率 (Reflectance) — 材料表面如何反射光
  3. 感知 (Perception) — 人眼如何感知最终的图像

1.3 光栅化vs光线追踪

特性 光栅化 (Rasterization) 光线追踪 (Ray Tracing)
类比 绘画 — 逐一着色物体 摄影 — 追踪光线
方法 经验光照模型 物理光线交互
效率 高效 低效
真实性 较低 逼真
应用 实时渲染 离线渲染

2. 光源

2.1 环境光 (Ambient Light)

定义:全方向照射的光,强度相同

特点

  • 是一种hack,用来模拟多次反射产生的背景光
  • 没有方向
  • 均匀照亮场景

数学表示

\[I = k_a I_a\]

其中 $k_a$ 是环境反射率,$I_a$ 是环境光强度。

2.2 平行光 (Directional Light)

定义:光线方向相同的光源

应用场景

  • 太阳光 — 距离很远,可以近似为平行光
  • 舞台灯光

特点

  • 没有衰减
  • 光线方向已知且恒定
  • 适合远距离光源

2.3 点光源 (Point Light)

定义:从单一点发出的光线向四周散发

应用场景

  • 灯泡
  • 火焰

特点

  • 有衰减(反平方律)
  • 光线方向随位置变化

衰减函数

\[f_{att} = \frac{1}{d^2}\]

其中 $d$ 是光源到表面的距离。

2.4 聚光灯 (Spotlight)

定义:点光源加上方向性的衰减

参数

  • 位置
  • 主方向 $\vec{D}$
  • 强度衰减参数
\[I = I_0 \cdot (\vec{l} \cdot \vec{D})^{\text{falloff}}\]

2.5 面光源 (Area Light)

定义:发光的2D表面

特点

  • 产生软阴影(阴影边界模糊)
  • 计算复杂

实现方式

  • 分解为多个点光源
  • 使用重要性采样

3. 反射与照明模型

3.1 漫反射 (Diffuse Reflection)

Lambert定律

漫反射材料(哑光表面)的反射强度由表面法线和光线方向决定:

\[I_d = k_d I_l \cos\theta = k_d I_l (\vec{n} \cdot \vec{l})\]

参数

  • $I_d$ — 漫反射强度
  • $k_d$ — 漫反射系数 ($0 \leq k_d \leq 1$)
  • $I_l$ — 光源强度
  • $\theta$ — 法线与光线的夹角

特点

  • 从任何观察方向看亮度相同
  • 亮度只取决于入射光方向和表面法线
  • 常见于非光泽表面(纸张、布料、砖墙等)

环境光 + 漫反射

结合环境光项以避免完全黑色的阴影:

\[I_{a+d} = k_a I_a + k_d I_l \cos\theta\]

这是计算机图形学早期的标准做法,虽然物理上不准确,但在实时渲染中仍然广泛使用。

3.2 镜面反射 (Specular Reflection)

定义:光线在微观光滑的表面上形成的高光

特点

  • 观察角度相关 — 高光只在特定观察角度可见
  • 由光线和法线决定的反射方向
  • 常见于光泽表面(金属、抛光物体)

计算反射方向

给定入射光方向 $\vec{l}$ 和表面法线 $\vec{n}$,反射方向 $\vec{r}$:

\[\vec{r} = 2(\vec{n} \cdot \vec{l})\vec{n} - \vec{l}\]

Phong照明模型

Phong模型用于近似镜面反射的衰减:

\[I_s = k_s I_l \cos^{n_s}\phi\]

参数

  • $\phi$ — 反射光线与观察方向的夹角
  • $k_s$ — 镜面反射系数
  • $n_s$ — 镜面指数(控制高光锐利程度)

特点

  • $n_s$ 越大,高光越尖锐(更光滑的表面)
  • $n_s$ 越小,高光越宽(更粗糙的表面)
  • 没有物理基础,但在图形学中广泛使用
  • 值通常在 100-200 之间

3.3 完整的Phong照明方程

结合环境光、漫反射和镜面反射:

\[I = k_a I_a + f_{att} I_l [k_d \max(0, \cos\theta) + k_s \cos^{n_s}\phi]\]

对多个光源

  • 对每个光源重复计算漫反射和镜面反射项
  • 将所有光源的贡献求和
  • 环境光项只计算一次

材料特性的表达

  • 简单金属 — $k_a$ 和 $k_d$ 有材料颜色,$k_s$ 为白色
  • 简单塑料 — $k_s$ 也包含材料颜色

4. 着色算法

着色的关键问题:在表面的哪些点计算照明?这直接影响渲染效果。

4.1 平面着色 (Flat Shading)

方法

  • 计算每个基元(三角形)的一个照明值
  • 通常在重心处计算

优点

  • 快速
  • 简单

缺点

  • 明显的面段效应 — 多面体的面段清晰可见
  • 对于曲面外观不佳

4.2 Gouraud着色

方法

  1. 在每个顶点计算照明值
  2. 在三角形内部线性插值颜色

优点

  • 比平面着色更光滑
  • 仍然相对快速

缺点

  • 屏幕空间插值错误(应该在世界空间插值)
  • 高光可能被”吞掉”(高光位于三角形内部时)
  • 在不同细节级别间切换时会产生跳跃

4.3 Phong着色

方法

  1. 在每个顶点存储法线
  2. 在三角形内部插值法线(世界/模型空间)
  3. 在每个像素点计算照明(使用插值的法线)

优点

  • 非常光滑的外观
  • 高光更准确
  • 只在剪影边缘能看到多面体效应

特点

  • 比Gouraud着色计算量大(需要每像素着色)
  • 现代GPU非常高效,通常是默认选择

4.4 比较

方法 计算点数 视觉质量 速度
平面着色 每基元1点 最快
Gouraud着色 每顶点1点
Phong着色 每像素1点 较慢

5. 可见性问题

5.1 问题定义

可见性问题 (Visibility Problem):给定一个像素位置,哪个表面离观察者最近?

这是渲染中最基本的问题之一。

5.2 画家算法 (Painter’s Algorithm)

原理:像油画一样,从后往前绘制物体

步骤

  1. 按深度排序对象(后到前)
  2. 按此顺序投影和光栅化
  3. 前面的物体会覆盖后面的

优点

  • 概念简单
  • 处理透明度良好

缺点

  • 排序可能昂贵(不是线性时间)
  • 遇到循环遮挡时需要分割对象
  • 对非多边形物体困难

问题示例

两个对象A和B的深度关系可能是:
- A遮挡B (zmin(A) < zmin(B))
- B遮挡A (完全相反)
- 循环遮挡 (A部分遮挡B,B部分遮挡A)

5.3 Z-缓冲算法 (Z-Buffer Algorithm)

原理:维护每个像素的最小深度,只绘制更近的物体

算法

// 初始化
for each (x, y):
    zbuf[x,y] = infinity

// 绘制
for each object:
    for each pixel (x,y) in object:
        z = compute_depth(x, y)
        if z < zbuf[x,y]:
            zbuf[x,y] = z
            image[x,y] = shade(x, y)

优点

  • 简单,无需排序或分割
  • 易于混合不同几何体类型(多边形、球体等)
  • 标准硬件支持

缺点

  • 无法处理透明度(需要额外的技巧)
  • Z-缓冲分辨率不足会产生深度排序伪影
  • 需要浮点精度(防止Z-fighting)

5.4 后向面剔除 (Back-Face Culling)

原理:如果多边形法线指向远离观察者,则不渲染它

判断方法

\[\vec{v} \cdot \vec{n} \geq 0 \Rightarrow \text{back-facing}\]

其中 $\vec{v}$ 是观察方向,$\vec{n}$ 是表面法线。

优点

  • 可以消除大约一半的三角形
  • 对闭合物体有效

限制

  • 仅对凸物体或闭合网格有效
  • 非闭合表面可能产生错误

5.5 复杂场景的优化

空间数据结构

  • BSP树 — 二分空间划分,用于快速可见性查询
  • 八叉树 — 层次化空间分割
  • BVH — 包围体层次

几何简化

  • 远处物体使用更简单的代理模型
  • 细节级别 (LOD) — 自动选择合适的分辨率

6. 阴影

6.1 阴影的产生

定义:阴影发生在物体被挡住时,无法接收来自光源的光。

问题:该点是否能”看到”光源?

6.2 阴影映射 (Shadow Mapping)

基本思想

  1. 从光源视点渲染 — 计算从光源到各表面的深度
  2. 存储阴影贴图 — 记录光源能看到的最近表面距离
  3. 从相机着色 — 检查该点是否在阴影中

算法步骤

// 第一遍:从光源渲染
for each object:
    for each pixel (xL, yL) in light view:
        shadowZ[xL, yL] = min(shadowZ[xL, yL], z(xL, yL))

// 第二遍:从相机渲染
for each object:
    for each pixel (x, y):
        (xL, yL, zL) = TransformToLightSpace(x, y, z)
        in_shadow = (zL > shadowZ[xL, yL] + ε)
        image[x,y] = shade(x, y, in_shadow)

参数

  • $\epsilon$ — 偏差(防止自阴影伪影)

优点

  • 支持任意几何体
  • 可以预计算
  • 效率高

缺点

  • 阴影边界会”锯齿化”(走样)
  • 需要额外的纹理内存
  • 偏差参数难以调整

改进方法

  • 百分比更接近滤波 (PCF) — 对阴影贴图周围进行平均
  • 级联阴影映射 — 使用多个分辨率处理不同距离
  • 方差阴影映射 — 使用统计方法

7. 非照相写实渲染

7.1 概述

非照相写实渲染 (Non-Photorealistic Rendering, NPR) 致力于创建看起来像插图、素描或动画的图像,而不是照相现实。

应用

  • 动画和卡通风格游戏(Genshin Impact, Arcane)
  • 技术插图
  • 医学和生物插图

7.2 卡通着色 (Toon Shading / Cel Shading)

原理:使用离散的颜色级别而不是连续的光照变化,模拟漫画书的风格。

实现

  • 使用查找表或分段函数量化照明值
  • 通常 2-3 个颜色级别

例子

正常Phong着色: 亮度从0.0-1.0平滑变化
卡通着色:     亮度映射到 {0.2, 0.5, 1.0} 三个离散值

7.3 轮廓线提取

轮廓线是NPR中关键的视觉元素,表示物体的边界和特征。

轮廓线类型

  1. 不连续性 — 表面褶皱、自交点
  2. 补丁边界 — 表面块之间的边界
  3. 轮廓线和轮廓 — 在视线上与法线相切的点
  4. 抛物线 — 高斯曲率为0的点
  5. 等参线 — 常数参数线
  6. 曲率线 — 主曲率方向的线
  7. 阴影 — 阴影区域和光照区域的边界

轮廓提取方法

方法1:法线轮廓线

  • 使用着色法线检测视线接近与法线相切的位置
  • 优点:快速
  • 缺点:线宽难以控制

方法2:程序几何轮廓线

  • 渲染一个略微放大的模型以获得轮廓
  • 结合Z-缓冲得到轮廓线
  • 优点:精确、线宽可控
  • 缺点:额外的几何处理

方法3:图像处理边缘检测

  • 对渲染的深度/法线图进行边缘检测
  • 优点:后处理,不影响渲染流程
  • 缺点:可能检测到不期望的边缘

7.4 Gooch着色

原理:用冷暖色转换代替深浅转换,保持可读性同时增加艺术表现力。

颜色映射

\[I = \frac{1 + \vec{l} \cdot \vec{n}}{2} \cdot k_d + \left(1 - \frac{1 + \vec{l} \cdot \vec{n}}{2}\right) \cdot k_{cool}\]

其中:

  • 亮处使用温暖色调
  • 暗处使用冷色调
  • 平滑过渡

特点

  • 保留照明信息
  • 增加艺术表现力
  • 更易于阅读和辨别

7.5 金属着色

观察:技术插图中金属表面通常用交替的深色和浅色条纹表示,称为各向异性反射

实现

  • 沿最大曲率的参数轴映射20条条纹
  • 条纹强度随机变化(0.0-0.5)
  • 最接近光源的条纹设为白色
  • 在条纹中心间进行线性插值

效果:模仿车床加工金属表面的外观。

7.6 从技术插图学习

原则 (Tufte的最小有效差异原则):

使所有视觉区分尽可能微妙,但仍然清晰有效。

NPR设计启示

  • 用黑色曲线表示表面边界和轮廓
  • 哑光物体:用中等强度着色,根据法线显示冷暖色
  • 单一光源提供白色高光
  • 元素用简洁有效的方式表达

7.7 应用领域

医学和生物插图

  • 清晰展示解剖结构
  • 高度样式化,易于理解
  • 突出重点区域

建筑可视化

  • 草图风格表达设计意图
  • 保留必要细节,简化视觉信息

总结

着色是从几何和材料参数到最终图像的关键步骤:

  1. 照明模型 — 从物理直觉出发的简化模型(Phong)
  2. 着色算法 — 在效率和质量间权衡(平面、Gouraud、Phong)
  3. 可见性 — Z-缓冲是现代GPU的基础
  4. 阴影 — 阴影映射是实时渲染的标准技术
  5. NPR — 扩展渲染范围超越照相写实
  6. 实时性能 — 现代GPU使复杂着色成为可能

现代渲染通常采用正向延迟着色管线的混合,以平衡灵活性和性能。




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • notes of ML
  • notes of VCI
  • notes of AIP
  • notes of AI Math Fundamentals
  • notes of ICS