Unity法线贴图采样与解包深度解析

文章摘要

这段代码float3 normal = UnpackNormal(tex2D(_BumpMap, uv))是Unity中从法线贴图采样并还原切线空间法线的标准写法。tex2D采样法线贴图的颜色值,UnpackNormal将其转换为[-1,1]范围的切线空间法线向量。Unity内置的实现通过R、G通道计算XY分量,并用勾股定理还原Z分量。法线贴图需设置为Normal Map类型,推荐使用DXT5nm等专用压缩格式。解包后的法线需通过TBN矩阵转换到世界空间参与光照计算。该技术为PBR渲染提供精细的表面凹凸细节。

这行代码:

float3 normal = UnpackNormal(tex2D(_BumpMap, uv));

这是在Unity标准PBR Shader中从法线贴图中采样并还原切线空间法线的典型写法。下面我会详细剖析它的原理、源码实现和注意事项。


1. 作用说明

  • tex2D(_BumpMap, uv):用uv坐标从法线贴图采样,得到一个颜色值(通常是RGB)。
  • UnpackNormal(...):把采样到的颜色值(通常范围是[0,1])转换为切线空间的法线向量(范围[-1,1])。

2. Unity内置UnpackNormal源码

在Unity的内置头文件UnityCG.cginc中,UnpackNormal的实现如下:

inline float3 UnpackNormal( float4 packednormal )
{
    // 法线贴图的RGB通常存储在[0,1],需要还原到[-1,1]
    float3 normal;
    normal.xy = packednormal.xy * 2 - 1;
    // Z分量用勾股定理还原
    normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
    return normal;
}

解释:

  • 法线贴图的R、G分量分别代表X、Y方向,存储时是[0,1],解包后变成[-1,1]。
  • Z分量(垂直于表面)用z = sqrt(1 - x^2 - y^2)还原,保证法线长度为1。
  • 这样得到的normal切线空间法线,用于后续的PBR光照计算。

3. 法线贴图的存储格式

  • Unity默认的法线贴图是切线空间法线贴图(Tangent Space Normal Map)。
  • 贴图的R、G通道存储X、Y分量,B通道有时存储Z分量,有时不用(节省带宽)。
  • 采样后需要解包,还原为[-1,1]的向量。

4. 性能与注意事项

  • UnpackNormal的计算非常快,只有简单的乘法和开方。
  • 如果法线贴图压缩格式不对(如未设置为Normal Map类型),采样结果会出错,导致表面光照异常。
  • 在移动端,建议用DXT5nm或ETC2等专用法线贴图压缩格式,避免精度损失。

5. 实际案例

Shader片段:

sampler2D _BumpMap;
float2 uv = ...; // 当前像素的UV
float3 tangentNormal = UnpackNormal(tex2D(_BumpMap, uv));
// 后续将tangentNormal变换到世界空间或视空间参与光照计算

效果:

  • 让表面产生细致的凹凸感(bump),即使模型本身没有高模细节。

6. 进阶:法线空间变换

  • 切线空间法线需要通过TBN矩阵(Tangent, Bitangent, Normal)变换到世界空间或视空间,才能和光照方向正确计算。
  • Unity内置函数UnityObjectToWorldNormalUnityObjectToWorldDir等可辅助完成空间变换。

总结

  • UnpackNormal(tex2D(_BumpMap, uv))是Unity标准法线贴图采样与解包的标准写法。
  • 其本质是把贴图中的颜色值还原为切线空间的法线向量,为PBR等高级光照提供细节支持。

7、TBN矩阵推导、法线贴图压缩对比、世界空间法线贴图处理等更深入内容

下面我将分别详细讲解:


1. TBN矩阵推导

1.1 为什么需要TBN矩阵?

  • 法线贴图通常存储的是切线空间法线(Tangent Space Normal),即以模型表面为基准的局部坐标系。
  • 光照计算通常在世界空间视空间进行。
  • 所以需要把切线空间的法线变换到世界空间/视空间,这就需要TBN矩阵。

1.2 TBN矩阵的组成

  • T:Tangent(切线),沿着UV的U方向。
  • B:Bitangent(副切线/副法线),沿着UV的V方向。
  • N:Normal(法线),模型表面法线。

这三个向量在每个顶点都可以通过模型数据或顶点着色器计算得到,且三者正交。

1.3 TBN矩阵的推导

设有顶点P0、P1、P2及其UV坐标UV0、UV1、UV2。

  1. 计算三角形的两个边:

    Edge1 = P1 - P0
    Edge2 = P2 - P0
    DeltaUV1 = UV1 - UV0
    DeltaUV2 = UV2 - UV0
    
  2. 计算Tangent和Bitangent:

    float f = 1.0 / (DeltaUV1.x * DeltaUV2.y - DeltaUV2.x * DeltaUV1.y);
    
    Tangent = f * (DeltaUV2.y * Edge1 - DeltaUV1.y * Edge2);
    Bitangent = f * (-DeltaUV2.x * Edge1 + DeltaUV1.x * Edge2);
    
  3. 法线N通常由模型自带。

  4. 归一化T、B、N,组成TBN矩阵:

    | T.x  B.x  N.x |
    | T.y  B.y  N.y |
    | T.z  B.z  N.z |
    

1.4 在Shader中的应用

  • 顶点着色器传递T、B、N到片元着色器。
  • 片元着色器中用TBN矩阵将切线空间法线变换到世界空间:
    float3 worldNormal = mul(tangentSpaceNormal, float3x3(T, B, N));
    

2. 法线贴图压缩对比

2.1 常见压缩格式

  • DXT5nm(BC5):PC平台常用,R通道存X,A通道存Y,Z分量重建。
  • ETC2:移动端OpenGL ES 3.0+,支持两通道压缩,适合法线贴图。
  • RGBA8:无损,空间大,移动端慎用。
  • ASTC:高端移动端,支持多通道高质量压缩。

2.2 压缩对比

格式通道质量体积适用平台备注
DXT5nm2较高PC/主机需特殊导入设置
ETC22较高移动端OpenGL ES3
RGBA84无损全平台占用大
ASTC2-4极高可调高端移动/PC需硬件支持

2.3 Unity设置建议

  • 导入法线贴图时,Texture Type设为Normal Map,Unity会自动选择合适的压缩方式。
  • PC建议DXT5nm,移动端建议ETC2或ASTC。
  • 压缩会带来精度损失,极端情况下(如大面积蓝色/紫色)可能出现伪影。

3. 世界空间法线贴图处理

3.1 区别

  • 切线空间法线贴图:每个像素的法线是相对于表面切线空间的。
  • 世界空间法线贴图:每个像素的法线直接存储在世界空间,无需TBN变换。

3.2 使用场景

  • 世界空间法线贴图常用于三维体积贴图投影贴图特殊地形效果等。
  • 适合法线方向不随模型变形而变化的场景。

3.3 Shader处理方式

  • 切线空间法线贴图:采样后需TBN变换。
  • 世界空间法线贴图:采样后直接用,无需TBN。

示例:

// 切线空间法线
float3 tangentNormal = UnpackNormal(tex2D(_BumpMap, uv));
float3 worldNormal = mul(tangentNormal, float3x3(T, B, N));

// 世界空间法线
float3 worldNormal = UnpackNormal(tex2D(_WorldNormalMap, uv));

3.4 注意事项

  • 世界空间法线贴图在模型变形(如骨骼动画)时会出现法线错位。
  • 贴图制作时需保证法线方向与世界坐标系一致。

4. 总结与建议

  • TBN矩阵是切线空间法线转世界/视空间的桥梁,推导公式需掌握。
  • 法线贴图压缩要兼顾质量和平台,Unity自动处理大部分情况,但特殊需求需手动调整。
  • 世界空间法线贴图适合静态、特殊效果,动态模型优先用切线空间法线贴图。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你一身傲骨怎能输

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值