返回博客
教程

法线贴图约定:OpenGL 与 DirectX 详解

为什么你的法线贴图在虚幻引擎中看起来反向,但在 Unity 中却很好——用简洁的解释说明切线空间 Y 轴约定,并提供具体的修复方案。

Admin2026年4月23日1 分钟阅读11

你将法线贴图导入虚幻引擎,表面的光照看起来就像太阳从下方照射。你将同一个文件导入 Unity 或 Blender——看起来很棒。网格相同。纹理相同。这是怎么回事?

\n\n

两个行业,一个轴的分歧

\n

法线贴图在其 RGB 通道中存储表面方向。红 = X,绿 = Y,蓝 = Z。每个 PBR 引擎以相同的方式解码它们,只有一个例外:Y 的符号。

\n

OpenGL 约定 (Y+):较亮的绿色通道表示表面指向上方。由 Unity、Godot、Blender(Cycles 和 Eevee)、Substance Painter 的默认导出以及每个基于 WebGL 的引擎使用。

\n

DirectX 约定 (Y−):较亮的绿色表示表面指向下方。由虚幻引擎、旧版 Direct3D 工具链以及一些 CryEngine/Xbox 时代的资产使用。

\n

PNG 中的字节相同。物理含义相反。

\n\n

一览无遗的识别方法

\n

查看法线贴图中的半球形凹凸(如按钮或圆顶)。在 OpenGL 约定中,凹凸的底部将是较深的绿色,因为表面向 Y− 旋转,远离光源。在 DirectX 约定中,底部是较亮的绿色

\n

如果你的引擎中光照感觉方向相反——高光出现在应该是阴影的地方——那就是约定不匹配。

\n\n

修复只需 5 秒

\n

在虚幻引擎中,纹理导入对话框有一个翻转绿色通道复选框。打开它,引擎会在采样时反转 G 通道。无需重新导出源文件。

\n

在 Unity 中,将纹理类型设置为法线贴图,导入器会处理所有问题——Unity 期望 OpenGL,但如果文件看起来不对,它会警告你。在 Blender 中,使用分离颜色 → 反转 G → 合并颜色节点链,或者直接在法线贴图节点中选择 DirectX 风格的输入。

\n\n

为什么首先要有两个标准?

\n

在 20 世纪 90 年代,OpenGL 和 DirectX 定义了相反的纹理坐标空间——OpenGL 的 Y 向上增加,DirectX 的 Y 向下增加。当法线贴图在 2000 年代中期变得普遍时,每个工具链都将其空间烘焙到其输出中。分歧之所以坚持下来,是因为翻转已建立的管道代价很大。

\n\n

无混淆地生成法线贴图

\n

aukimi 法线贴图生成器让你在导出时明确选择约定。它在你的高度贴图的亮度上运行 Sobel 梯度,然后将 (−dx·s, −dy·s, 1) 打包到 RGB 中——当你选择 DirectX 时翻转 Y。你可以在生成后切换约定,并重新下载而不需要重新上传任何内容。

\n

在内部公式完全相同。唯一的区别是我们在写入绿色通道之前应用于 Y 分量的符号。知道这一点,你可以用任何图像编辑器在约定之间转换文件:打开 PNG,选择绿色通道,反转它,保存。这就是虚幻引擎中"翻转绿色通道"所做的全部。

\n\n

快速参考

\n
    \n
  • Unity、Godot、Blender、Substance Painter(默认):OpenGL (Y+)。
  • \n
  • 虚幻引擎、旧版 Direct3D:DirectX (Y−)。
  • \n
  • 在虚幻中看起来不对?在导入设置中启用翻转绿色通道。
  • \n
  • 在 Unity 中看起来不对?你可能从 DirectX 约定工具导出了——反转绿色通道或重新导出。
  • \n
\n\n

一旦你理解了这个约定,修复就很简单了。最难的部分是第一次识别它。

#normal-map#3d#pbr#shaders#opengl#directx

喜欢这篇文章吗?

ShareHN