面光积分

多边形面积光源占据一个方向范围。固定接收点 pp 与观察方向 ωo\boldsymbol\omega_o,记光源覆盖范围与宏观接收半球的交集为 ΩP\Omega_P,需要计算

Lo=∫ΩPLi(ωi)fr(ωi,ωo)max⁡(0,n⋅ωi)V(p,ωi) dωi.L_o=\int_{\Omega_P}L_i(\boldsymbol\omega_i) f_r(\boldsymbol\omega_i,\boldsymbol\omega_o) \max(0,\mathbf n\cdot\boldsymbol\omega_i) V(p,\boldsymbol\omega_i)\,\mathrm d\omega_i.

随机采样光源可以估计它,但每个像素只用少量样本时会有噪声,阴影查询还会增加成本。Linearly Transformed Cosines,LTC 针对多边形光源的无阴影直接着色,将反射分布近似为一类容易积分的函数。

先设光源辐亮度为常数 LL,V=1V=1。将固定观察方向后的响应写为 K(ω)=fr(ω,ωo)max⁡(0,n⋅ω)K(\boldsymbol\omega)=f_r(\boldsymbol\omega,\boldsymbol\omega_o)\max(0,\mathbf n\cdot\boldsymbol\omega),则 Lo=L∫ΩPK dωL_o=L\int_{\Omega_P}K\,\mathrm d\omega。BRDF 原本依赖两个二维方向,固定其中一个后,待积分的瓣只随另一方向变化。

LTC 与环境 Split Sum 处理不同的积分域:前者每次使用当前多边形光源的边界,后者预过滤整个环境方向图。LTC 的拟合误差、阴影缺失与非均匀发光,也需要分别处理。

方向变换

以归一化的截断余弦分布为起点:

D0(ω0)=max⁡(0,ω0z)π.D_0(\boldsymbol\omega_0)=\frac{\max(0,\omega_{0z})}{\pi}.

选可逆矩阵 MM,将方向线性变换后重新归一化:

ω=Mω0∥Mω0∥,ω0=M−1ω∥M−1ω∥.\boldsymbol\omega=\frac{M\boldsymbol\omega_0}{\|M\boldsymbol\omega_0\|}, \qquad \boldsymbol\omega_0=\frac{M^{-1}\boldsymbol\omega}{\|M^{-1}\boldsymbol\omega\|}.

缩放改变瓣的宽度,不同轴的缩放形成各向异性,剪切使形状偏斜;归一化把结果重新放回单位球面。只有转方向而不变换密度,会改变总能量。

球面面积的 Jacobian 为

dω=∣det⁡M∣∥Mω0∥3 dω0.\mathrm d\omega= \frac{|\det M|}{\|M\boldsymbol\omega_0\|^3}\,\mathrm d\omega_0.

可以从小锥体理解这个因子:线性变换使三维体积乘 ∣det⁡M∣|\det M|,但该方向上的径向长度变为原来的 ∥Mω0∥\|M\boldsymbol\omega_0\| 倍;将径向体积重新归一到单位球面,需要除以这一长度的三次方。

按概率质量不变 D(ω)dω=D0(ω0)dω0D(\boldsymbol\omega)\mathrm d\omega=D_0(\boldsymbol\omega_0)\mathrm d\omega_0,得到

DLTC(ω)=D0 ⁣(M−1ω∥M−1ω∥)∣det⁡M−1∣∥M−1ω∥3.D_{\rm LTC}(\boldsymbol\omega)=D_0\!\left( \frac{M^{-1}\boldsymbol\omega}{\|M^{-1}\boldsymbol\omega\|}\right) \frac{|\det M^{-1}|}{\|M^{-1}\boldsymbol\omega\|^3}.

令 K≈ADLTCK\approx A D_{\rm LTC},AA 表示整体响应幅度,MM 表示方向形状。拟合有限形状族可以保留主要特征,但任意 BRDF 并不都能被一个矩阵精确变成余弦。LTC 作者研究页

光源换元

复杂反射瓣与多边形光源一起变换为余弦积分

左图是拟合后的方向瓣 DD 和光源 PP;右图恢复为简单余弦瓣 D0D_0,光源同时变成 P0=M−1PP_0=M^{-1}P。球面上黑色围出的区域表示相应光源占据的方向范围。只改反射瓣、保留原光源区域,会得到错误积分。

换元后

Lo≈LA∫ΩPDLTC(ω) dω=LA∫ΩP0D0(ω0) dω0.L_o\approx LA\int_{\Omega_P}D_{\rm LTC}(\boldsymbol\omega)\,\mathrm d\omega =LA\int_{\Omega_{P_0}}D_0(\boldsymbol\omega_0)\,\mathrm d\omega_0.

把每个光源顶点 xj\mathbf x_j 相对接收点的向量变到当前局部坐标,先保留宏观接收半球内的光源区域,再乘 M−1M^{-1}。在变换后的 z≥0z\ge0 半空间继续裁剪,最后将有效顶点归一化为 vj\mathbf v_j。前一条件排除物理背面的入射,后一条件对应拟合截断余弦的支持域;两者不能混为一份坐标下的判断,也不能仅检查光源中心是否在正面。

归一化顶点间的边在单位球面上形成大圆弧。利用球面积分到边界积分的关系,每条边贡献

Ij=12πθj(vj×vj+1)z∥vj×vj+1∥,θj=arccos⁡(clamp⁡(vj⋅vj+1,−1,1)).I_j=\frac1{2\pi}\theta_j \frac{(\mathbf v_j\times\mathbf v_{j+1})_z} {\|\mathbf v_j\times\mathbf v_{j+1}\|}, \quad \theta_j=\arccos(\operatorname{clamp}(\mathbf v_j\cdot\mathbf v_{j+1},-1,1)).

按一致顶点绕序求和 I=∑jIjI=\sum_jI_j,就是 ∫ΩP0D0 dω0\int_{\Omega_{P_0}}D_0\,\mathrm d\omega_0。这来自投影面积:球面区域的余弦积分等于该区域在法线平面上的有向面积,边界的大圆弧决定对应面积向量。Lambertian 情形 MM 为单位矩阵、A=ρA=\rho,便回到光源投影立体角乘 ρ/π\rho/\pi 的结果。

退化短边需用 θ/sin⁡θ→1\theta/\sin\theta\to1 的极限处理;接近反向的顶点、光源平面经过接收点等情况需要额外数值保护。单面光源先检查发光面朝向,非凸光源可以三角化并累加,不能靠最后取绝对值掩盖错误绕序或重复区域。

拟合与查表

如何得到 MM?离线对指定 BRDF、粗糙度和观察角拟合 LTC 分布,并存幅度及矩阵参数。各向同性材质的常见表按粗糙度与 n⋅ωo\mathbf n\cdot\boldsymbol\omega_o 索引;局部坐标的一个切向轴沿观察方向的表面投影,另一个轴由叉乘得到。观察方向正好沿法线时,需要稳定的备用切线。

运行时查询拟合表,变换光源顶点,裁剪并累加边界项。矩阵通常只需少量自由参数,并非每像素重新执行优化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 固定 BRDF 已离线拟合,光源具有均匀辐亮度且暂不计算阴影。
function evaluatePolygonLight(p, normal, view, roughness, vertices):
localFrame = makeViewAlignedFrame(normal, view)
inverseM, amplitude = lookupLtc(roughness, dot(normal, view))
localVertices = []
for vertex in vertices:
relative = worldToLocal(localFrame, vertex - p)
localVertices.append(relative)
localVertices = clipPolygonToPositiveZ(localVertices)
transformed = []
for relative in localVertices:
transformed.append(inverseM * relative)
transformed = clipPolygonToPositiveZ(transformed)
directions = normalizeEach(transformed)
integral = integrateCosinePolygonBoundary(directions)
return lightRadiance * amplitude * integral

星形和矩形面光源在表面上形成的直接反射

左图星形光源在地面形成对应反射结构,右图多个有色矩形灯在不同表面形成宽窄不同的反射。多边形积分让光源轮廓进入着色结果,而非始终将面光源当成一个中心点。图中的完整场景效果不能证明遮挡也是由 LTC 计算的,阴影需要其他方案。

更换 BRDF、增加反射瓣、使用各向异性或复杂 Fresnel 时,应相应拟合、分瓣和建表;一份 GGX 表不自动适用于所有 Disney 参数。贴图光源的 LiL_i 非常量,也不能直接提出积分号,需分片、采样或更复杂的积分扩展。离线渲染同样能使用 LTC,但已有高质量采样管线未必需要这一实时取舍。

材质控制

单一微面反射瓣难以表达所有测量材质。清漆木材既有底层颜色和散射,也有表层较清晰的反射;只调一份粗糙度,往往同时改变了本应分别控制的效果。直接让美术设置折射率等物理量,也未必便于按照外观工作。

Disney Principled BRDF 以测量材质为参考,将常见反射特征整理为一套相对统一的可控模型。其设计原则是:参数对应可观察效果,数量尽量少,合理范围映射到 [0,1][0,1],必要时允许越界,并尽量让不同参数组合保持稳健可信。这里的 Principled 强调设计准则,不意味着所有经验项都由严格物理推导得到。Disney 原始讲义

颜色参数 Base Color 在非金属时主要描述底层漫反射颜色,在金属时主要用于有色镜面反射。2012 版还有十个标量参数,不能将后来的同名 Principled 实现与这份参数表自动视为同一版本。

Disney材质各参数从0到1独立变化的球体矩阵

每行只改变左侧标出的一个参数,各列从 00 到 11,其他设置保持该行的参考值。不同颜色属于不同的演示材质,不能跨行把颜色差异都归到行名参数。Base Color 没有单独列在这幅十行图中。

参数 控制内容与图中变化
Subsurface 改变漫反射的方向形状,使明暗过渡接近简化的次表面散射外观;它不追踪光进入材质后从另一表面位置出来。BSSRDF 描述这种跨表面位置的光传输,不能由该参数替代。
Metallic 从电介质响应过渡到金属响应,减弱底层漫反射并让镜面反射带 Base Color;金色一行中环境反射逐渐主导外观。
Specular 控制电介质的正入射镜面反射强度,改变高光与环境反射的量;它不直接控制高光宽度。
Specular Tint 在中性电介质镜面色与带 Base Color 的镜面色之间调整,为艺术控制提供色调偏移。
Roughness 改变反射瓣宽度;蓝色一行中的清晰环境结构逐渐变宽、变模糊。
Anisotropic 使切线、次切线方向的粗糙度不同,形成方向相关的高光拉伸;还需有一致的表面切线方向。
Sheen 添加掠射方向的柔和反射,用于某些织物边缘的外观;不是完整纤维散射模型。
Sheen Tint 调整 Sheen 颜色向 Base Color 偏移的程度。
Clearcoat 控制额外清漆反射瓣的强度,可同时保留底层反射与较锐利的表层反射。
Clearcoat Gloss 控制清漆层的光泽和宽度,较高值通常对应更窄的清漆高光,不等于底层 Roughness。

这种统一模型便于材质制作与参数插值,但参数空间仍较大,不同组合也可能产生接近的外观。在材质反求中,“能拟合一种外观”不等于“参数解唯一”。是否满足能量守恒还需按具体版本、公式和参数域验证;不能把课堂答疑中的推测记成所有 Disney 模型的性质。

其多瓣结构并不妨碍实时使用,可以分瓣做环境预积分或面积光拟合。但表格维度、瓣间能量分配、各向异性方向以及预计算成本要随模型调整,不能直接套用单瓣近似就声称参数全覆盖。

风格化目标

非真实感渲染 Non-Photorealistic Rendering,NPR 以风格化表达为目标,包括线条、色块、笔触和用于说明结构的抽象。它可用于艺术、可视化、教学、技术说明、游戏与动画,并不限于卡通人物。

照片式渲染希望光照、材质和阴影共同形成接近摄影的结果;NPR 可以有意调整其中部分特征,以强调形状或信息。实时实现还需要低成本和帧间稳定:一条线在静止时正确、运动时反复出现和消失,仍会破坏表达。

可以先从目标图像观察具体特征。例如游戏风格中的粗轮廓、分段明暗和表面笔触,分别对应边缘检测、着色量化和纹理组织。接下来要回答“使用哪个几何或图像信号能得到这些特征”,再选择相应的着色步骤。

边缘分类

打开盒子上的边界、折痕、材质分界与视图轮廓

盒盖上只有一侧面相邻的边标为 BB,是开放的 Boundary。相邻面朝向不同形成的几何折痕标为 CC,即 Crease。盒侧彩色条带边界标为 MM,是 Material Edge,不必伴随几何突变。SS 是随视角变化的 Silhouette,即投影外轮廓。

标为 CSCS 的边在这个视角下同时是折痕和外轮廓;转动相机,它仍是折痕,但可能不再是外轮廓。光滑曲面也会形成 Silhouette,所以外轮廓并不总是折痕的子集。开放边界、材质边和几何轮廓需要不同信号,不能用一个判据无条件检测所有边。

法线描边

在平滑曲面的投影边缘,法线接近垂直于观察方向,可以用 ∣n⋅v∣<τ|\mathbf n\cdot\mathbf v|<\tau 判定需要加黑的区域。阈值越大,参与加黑的角度范围越宽;用 smoothstep 可以让边界有较平滑的过渡。

法线与视线接近垂直的区域加黑后形成轮廓

右图轮廓和若干内部结构比左图更重。法线变化缓慢的区域可能有较宽黑带,变化快的区域则较窄,所以这一角度阈值不保证恒定像素线宽。

这里使用的是 Shading Normal,它可以受法线插值或 Normal Map 影响。纹理中发生法线偏转也可能触发黑线,即使几何没有真正形成边缘;反之材质分界和开放边未必满足这个角度条件。需要纯几何轮廓时,应选择几何法线、网格邻接或其他信号。

背面膨胀

Backface Fattening / Inverted Hull 先正常绘制模型,再将外扩的背面绘成深色。正面覆盖内部区域,扩张背面只在投影轮廓外露出一圈。

边的平行外扩与沿顶点方向膨胀的差异

左侧两幅三角形显示角部延长与截断的差别,右图沿各顶点方向外扩多边形。锐角、法线不连续或非均匀缩放会改变外扩形状,不能认为任意网格沿顶点法线移动后都形成等宽边框。

一种实现顺序是先画普通正面,再在描边 Pass 中剔除正面,沿法线外扩顶点并用描边色画背面,保留合适的深度测试。也可先画膨胀壳再画正常模型,关键是剔除、深度与覆盖关系一致。

世界空间固定外扩距离 δ\delta 对应 x′=x+δn\mathbf x'=\mathbf x+\delta\mathbf n,远处投影线宽会变小。若追求固定屏幕线宽,可以在裁剪空间沿投影后的法线方向偏移,再按 ww、视口尺寸换算;这仍需处理法线接近视线、锐角和局部遮挡。

闭合网格与一致绕序便于这种方法工作;开放网格、薄片或局部自交可能露出不应有的黑面。它主要描绘投影轮廓,不会自动画出所有材质边和内部折痕。

图像描边

也可以对屏幕缓冲做边缘检测 Edge Detection。Sobel Operator 用两组 3×33\times3 核分别估计两个轴上的变化:

Kx=[−101−202−101],Ky=[−1−2−1000121].K_x=\begin{bmatrix}-1&0&1\\-2&0&2\\-1&0&1\end{bmatrix}, \qquad K_y=\begin{bmatrix}-1&-2&-1\\0&0&0\\1&2&1\end{bmatrix}.

将核与邻域对应值相乘并求和,得到梯度 gx,gyg_x,g_y。每个核的系数和为零,均匀区域中的正负贡献抵消;跨过边界时两侧不同,产生较大响应。可用 g=gx2+gy2g=\sqrt{g_x^2+g_y^2} 合成梯度强度,再阈值化形成线条。

Sobel输入、合成边缘及两个方向梯度

左上是原图,右上是组合后的边缘;左下与右下分别显示两个方向的响应。砖缝的竖向与横向结构在两幅梯度图中表现不同。下排为了显示正负梯度将零附近映为灰色,并不是所有位置都存在灰色边缘。

颜色梯度会检测到纹理与照明变化,未必是几何边;深度梯度能找到前后断层,但可能遗漏同深度折痕;法线差异能表现朝向变化,也可能受 Normal Map 干扰。可以分别检测并组合深度、法线、颜色或材质 ID,根据目标风格设置不同权重。

这种方法直接以像素邻域控制线宽,但远处细线、采样锯齿和相机运动会影响稳定性。将边缘掩码转为描边色后与原图混合,也要避免把用于分析的 HDR 值与最终显示颜色的阈值混用。

色阶量化

Hard Shading / Cel Shading 将连续光照响应分成若干档。例如 s=max⁡(0,n⋅l)s=\max(0,\mathbf n\cdot\mathbf l),以 0.50.5 和 0.850.85 为阈值,选择暗、中、亮三种颜色。

茶壶根据法线与光向余弦分成三档明暗

图中的最高档是 s≥0.85s\ge0.85,中档是 0.5≤s<0.850.5\le s<0.85,低档是 s<0.5s<0.5。图上两个“≥\ge”标签有范围重叠,实现必须按有序阈值判断,不能将同一位置同时加上两档。

1
2
3
4
5
6
7
8
9
10
// 亮、中、暗三档只是某种风格的选择,阈值与颜色由目标外观确定。
vec3 shadeInBands(float cosine, vec3 dark, vec3 middle, vec3 bright) {
if (cosine >= 0.85) {
return bright;
}
if (cosine >= 0.5) {
return middle;
}
return dark;
}

Posterization 则将已算出的颜色或明暗信号量化。对 [0,1][0,1] 的单个颜色分量,NN 档示意为 QN(c)=round⁡((N−1)c)/(N−1)Q_N(c)=\operatorname{round}((N-1)c)/(N-1)。它不必使用 n⋅l\mathbf n\cdot\mathbf l,因此能保留其他光照来源,但分档结果依赖选用的颜色空间和输入处理。

水果模型及多色阶、描边组合后的风格化结果

右图每种水果都包含不止两个颜色档,并保留白色高光和深色轮廓。左图给出几何模型,不是可以直接逐像素量化成右图颜色的完整输入。

漫反射、高光和轮廓可以分别风格化后组合,无需所有部分采用同一套阈值。

漫反射、高光、色块和描边的不同组合

上排各列从常规着色、高光强调、漫反射与高光分档,到专门线条效果;下排分别增加描边。第二列保持平滑高光,第三列高光本身也形成色块。风格选择改变了哪些信号被保留,而非只更换一份材质颜色。

笔触组织

手绘排线希望用笔触密度表示明暗,同时保持笔触贴着表面、在远近变化时连续。Tonal Art Maps,TAM 为不同 Tone 与尺度预先组织笔触纹理,运行时按着色明暗与纹理足迹选择。

不同明暗档与分辨率尺度下的笔触纹理

从左到右笔触增多,整体变暗;每列由小到大展示不同尺度层。同一明暗档在不同分辨率下应有相近的平均 Tone,同时让笔触在屏幕上保持合适大小。普通 mipmap 将细笔触缩成像素平均,可能只剩一片灰色,不能自动保证这种笔触效果。

构造 TAM 时,让较暗档尽量包含较亮档的笔触,再增加新的笔触,使明暗插值不至于将两套完全不同的线条同时淡入淡出;不同尺度也需维护对应关系。明暗、大小和布局的连贯性都需要设计,不能只准备几张互不相关的排线图片。

笔触与网格预处理后按明暗和尺度实时查询

图左的单笔触用于构造上方 TAM,网格用于生成下方 Lapped Textures:在表面覆盖相互重叠的局部纹理片,协调其方向和边界。右侧结果由这两份数据共同生成。手掌上的明暗靠笔触密度表达,方向随表面组织,而非始终沿屏幕水平轴。

预处理负责纹理层级和表面参数化,实时阶段先求连续的着色明暗,再查相邻 Tone、mip 层并混合。每帧完全重新随机生成笔触会闪烁,纹理缝、尺度切换和几何运动也需要连续性处理。

材质与风格

布料表面的方向高光、褶皱与颜色响应

这些抱枕的褶皱、掠射反射和方向性高光提供了材质辨识信息。做风格化时,可以保留这些响应的结构,再对亮暗、边缘或笔触作抽象;不必从一开始就丢掉材质规律。

不同角色、部位或用途可以使用不同规则。需要和美术明确哪些线必须出现、哪些阴影应保持稳定、哪些材质特征不能丢失,再选择能计算的信号。真实感材质模型提供反射基础,NPR 决定如何呈现这些信息;技术与艺术目标之间的对应,比套用一套固定效果更重要。