参考:https://zhuanlan.zhihu.com/p/375764857

线性混合 Linear Blending

描述:直接对两张法线贴图的向量相加后归一化。
核心思想:法线视为普通向量,线性叠加后重新单位化。
优缺点

  • 优点:实现简单,计算开销低(SM3.0仅需5条指令)。
  • 缺点:导致法线“扁平化”,细节丢失严重;当一张为平面法线((0,0,1))时,结果偏向平均值而非保留另一张细节。
    适用场景:对精度要求低的快速原型开发或低端设备。
    代码实现
HLSL
float3 n1 = tex2D(texBase, uv).xyz * 2 - 1; // 解码法线
float3 n2 = tex2D(texDetail, uv).xyz * 2 - 1;
float3 r = normalize(n1 + n2); // 相加后归一化
return r * 0.5 + 0.5; // 编码回[0,1]范围
点击展开查看更多

叠加混合 Overlay Blending

描述:仿Photoshop叠加模式,独立处理RGB通道。
核心思想:根据基础法线亮度值选择乘法或屏幕混合。
优缺点

  • 优点:比线性混合保留更多对比度,美术可控性强。
  • 缺点:无理论依据,混合后法线方向物理错误;计算开销较高(SM3.0需9条指令)。
    适用场景:艺术导向的非PBR项目,如风格化渲染。
    代码实现
HLSL
float3 n1 = tex2D(texBase, uv).xyz; // 未解码的RGB值
float3 n2 = tex2D(texDetail, uv).xyz;
// 叠加公式
float3 r = (n1 < 0.5) ? 2 * n1 * n2 : 1 - 2 * (1 - n1) * (1 - n2);
r = normalize(r * 2 - 1); // 解码并归一化
return r * 0.5 + 0.5;
点击展开查看更多

偏导数混合 Partial Derivative Blending

描述:通过法线计算表面偏导数(梯度),相加后再转回法线。
核心思想:法线本质是表面梯度,混合应在偏导数空间进行。
优缺点

  • 优点:数学基础扎实,平坦法线混合时结果正确。
  • 缺点:高频细节易被平滑;需除法操作(n.xy / n.z),性能较差,不过也有等效替代。 适用场景:高度图混合或材质渐变过渡(如地形融合)。
    实现代码
HLSL
float3 n1 = tex2D(texBase, uv).xyz * 2 - 1; // 解码法线
float3 n2 = tex2D(texDetail, uv).xyz * 2 - 1;
// float3 r = normalize(float3(n1.xy/n1.z + n2.xy/n2.z, 1)); // 偏导
float3 r = normalize(float3(n1.xy * n2.z + n2.xy * n1.z, n1.z * n2.z)); // 避免显式除法:等效替代
return r * 0.5 + 0.5;
点击展开查看更多

Whiteout混合 Whiteout Blending

描述:SIGGRAPH 07提出,在偏导数混合基础上去除Z分量缩放。
核心思想:简化偏导数计算,保留更多高频细节。
优缺点

  • 优点:细节保留优于偏导数法;平坦法线混合结果正确。
  • 缺点:仍存在轻微扁平化;指令数较高(SM3.0需7条)。
    适用场景:需高频细节的场合(如布料褶皱叠加)。
    代码实现
HLSL
float3 n1 = tex2D(texBase, uv).xyz * 2 - 1; // 解码法线
float3 n2 = tex2D(texDetail, uv).xyz * 2 - 1;
float3 r = normalize(float3(n1.xy + n2.xy, n1.z * n2.z)); // XY直接相加,Z相乘
return r * 0.5 + 0.5;
点击展开查看更多

UDN混合 Unreal Developer Network

描述:Whiteout的简化版,仅用基础法线的Z分量。
核心思想:牺牲少量细节换取性能提升。
优缺点

  • 优点:指令数更低(SM3.0约5条),性能友好。
  • 缺点:基础法线被轻微压平,细节弱于Whiteout。
    适用场景:主机/移动端性能敏感场景(如开放世界大 terrain)。
    代码实现
HLSL
float3 n1 = tex2D(texBase, uv).xyz * 2 - 1; // 解码法线
float3 n2 = tex2D(texDetail, uv).xyz * 2 - 1;
float3 r = normalize(float3(n1.xy + n2.xy, n1.z)); // Z直接取自基础法线
return r * 0.5 + 0.5;
点击展开查看更多

重定向法线贴图 Reoriented Normal Mapping (RNM)

描述:将细节法线旋转至基础法线空间,保留两者强度。
核心思想:模拟切线空间变换,几何意义明确。
优缺点

  • 优点:细节保留最完整;平坦法线混合无副作用;数学严谨。
  • 缺点:计算稍复杂(SM3.0需7-8条指令)。
    适用场景:影视级渲染或PBR项目(如皮肤毛孔、高精度材质)。

四元数版本(主流引擎采用)

HLSL
float3 t = tex2D(texBase, uv).xyz * float3(2, 2, 2) + float3(-1, -1, 0);
float3 u = tex2D(texDetail, uv).xyz * float3(-2, -2, 2) + float3(1, 1, -1);
float3 r = t * dot(t, u) / t.z - u; // 重定向计算
return normalize(r) * 0.5 + 0.5;   // 需归一化
点击展开查看更多

Unity矩阵版本

HLSL
float3 n1 = tex2D(texBase, uv).xyz * 2 - 1;
float3 n2 = tex2D(texDetail, uv).xyz * 2 - 1;
// 构造旋转矩阵
float3x3 nBasis = float3x3(
    float3(n1.z, n1.y, -n1.x), // +Y旋转
    float3(n1.x, n1.z, -n1.y), // -X旋转
    float3(n1.x, n1.y, n1.z)   // 原始法线
);
float3 r = normalize(n2.x * nBasis[0] + n2.y * nBasis[1] + n2.z * nBasis[2]);
return r * 0.5 + 0.5;
点击展开查看更多

总结:方法选择建议

方法 细节保留 性能 物理正确性 典型用例
线性/叠加混合 ⭐⭐⭐⭐⭐ 低端设备快速实现
UDN混合 ⭐⭐ ⭐⭐⭐⭐ ⚠️ 主机/移动端开放世界
Whiteout混合 ⭐⭐⭐ ⭐⭐⭐ 高频细节叠加(布料/皱纹)
RNM重定向 ⭐⭐⭐⭐⭐ ⭐⭐ 影视/PBR高精度渲染

版权声明

作者: Cheyne Xie

链接: https://chaim.eu.org/posts/d24548ec/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键