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

线性混合 Linear Blending

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

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通道。
核心思想:根据基础法线亮度值选择乘法或屏幕混合。
优缺点

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

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

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分量缩放。
核心思想:简化偏导数计算,保留更多高频细节。
优缺点

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分量。
核心思想:牺牲少量细节换取性能提升。
优缺点

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)

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

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

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高精度渲染

版权声明

作者: Chaim

链接: https://chaim.eu.org/posts/%E6%B7%B7%E5%90%88%E6%B3%95%E7%BA%BF/

许可证: 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 快捷键