文章

Unity2021.3.21默认法线贴图显示Bug

Unity2021.3.21默认法线贴图显示Bug

Unity2021.3.21默认法线贴图显示Bug

00 背景说明

在 Unity 着色器中, 如果声明了法线贴图却未赋值, 系统会自动使用内置的“UnityNormalMap”进行替代采样. Unity 支持两种法线贴图编码模式, 可在 Player Settings 中切换:

  • XYZ
  • DXT5nm-style(移动端以外平台的默认模式, 质量较高但解码开销更大)

在 Unity 2021.3.21f1 版本中, 将 Editor 平台切换至 Android 后, 法线贴图编码(Unity的法线贴图编码模式可以在PlayerSetting中设置, 有XYZDXT5nm-style)仍会保持为 DXT5nm-style.

image-20250911181025313

image-20250911181234084

关于DXT5nm-style的说明

DXT5nm-style法线贴图编码.

这是非移动平台上的默认法线贴图编码方式.

相较于NormalMapEncoding.XYZ, 此类法线贴图质量更高, 但在着色器中解码时计算成本更高.

简单来说, 质量可能更高, 但GPU消耗更大.

01 Bug描述

触发环境

  • 引擎版本: Unity 2021.3.21f1(及之前版本)
  • 平台设置: Android
  • 法线贴图编码: DXT5nm-style
  • 编辑器渲染: 默认 DX11

复现步骤

  • 创建一份简单着色器(手写或 Shader Graph 均可).
  • 在着色器中声明法线贴图, 默认值设为 "bump", 并生成材质.
  • 将该材质赋予场景中的物体, 同时保持法线贴图留空.
  • 在满足上述环境条件时, 即可观察到法线贴图无效或异常效果.

image-20250911182435154

02 原因分析

Unity 内置的“UnityNormalMap”始终以 RGBA32 格式存储, 不会随法线贴图编码设置而自动转换;而采样器则会根据平台及编码模式切换采样逻辑, 导致使用默认纹理时格式不匹配, 从而引发显示错误.

03 解决方案

  • 升级引擎 将 Unity 升至 2021.3.45f1 或更高版本, 该版本已修复此问题.
  • 强制使用 GLES 渲染 在 GLES 模式下不会出现上述异常, 但可能对部分项目兼容性产生影响.
  • 修改法线贴图编码(推荐) 将法线贴图编码切换为 XYZ:
    • 可彻底避免该 Bug;
    • 降低 GPU 解码开销;
    • 虽然会略微降低法线精度, 但在视觉效果上并不明显, 且对美术工作流程更友好.
  • 强制使用OpenGLES渲染方式
    • 在UnityHub的对应工程启动参数中添加-force-gles
参考网页
本文由作者按照 CC BY 4.0 进行授权