当前位置: 首页 > news >正文

Unity URP 法线贴图如何生成 用什么工具创建

从零理解法线贴图的原理,掌握从 Photoshop、Blender 到 Substance 的多种生成工具,并在 URP 管线中正确实现法线贴图的采样与光照计算。

一、什么是法线贴图

法线贴图(Normal Map)是一种特殊的纹理,它不存储颜色信息,而是逐像素地编码了表面的法线方向。在渲染时,GPU 读取法线贴图中的法线向量,替代模型原本的顶点插值法线,从而在不增加几何复杂度的情况下模拟出丰富的表面凹凸细节。

核心要点:法线贴图通过在像素着色器中逐片元替换表面法线,让光线在"假凹凸"上产生正确的反射方向。眼睛看到的是细节,而三角形数量并没有增加。这是现代实时渲染中最重要的"障眼法"之一。

二、法线贴图的工作原理

2.1 切线空间(Tangent Space)

绝大多数的法线贴图都使用切线空间。切线空间是一个以模型表面为参考的局部坐标系,由三个正交轴构成:

  • T(Tangent)— 切线方向,沿 UV 的 U 轴方向
  • B(Bitangent / Binormal)— 副切线方向,沿 UV 的 V 轴方向
  • N(Normal)— 顶点法线方向,垂直于表面

在切线空间中,一个完全平坦的表面法线是(0, 0, 1),在法线贴图中的颜色就是(128, 128, 255)即浅蓝色。这就是为什么法线贴图整体看起来偏蓝。

2.2 解码公式

在着色器中,法线贴图的采样值从[0, 1]范围映射到[-1, 1]

// 从法线贴图采样得到的颜色值 (0~1) float4 normalTex = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, IN.uv); // 解码:从 [0,1] 映射到 [-1,1] float3 tangentNormal = normalTex.xyz * 2.0 - 1.0; // 或者使用 Unity 内置函数(处理 DXT5nm 压缩格式) float3 tangentNormal = UnpackNormal(normalTex);

注意 DXT5nm 压缩:使用UnpackNormal()是最安全的做法。Unity 在构建时可能将法线贴图压缩为 DXT5nm 格式,此时 R 通道被丢弃,法线的 X 存于 A 通道,Y 存于 G 通道。直接* 2 - 1会得到错误结果。

三、工具矩阵:用什么生成法线贴图

创建法线贴图主要有两条路径:从 2D 纹理转换(高度图 → 法线贴图),和从高模烘焙到低模。下面逐一介绍主流工具。

四、工具推荐对比

工具类型价格上手难度推荐场景
Substance Designer2D 节点式$$$专业程序化纹理制作
Substance Painter高模烘焙$$$中高3D 资产纹理绘制
Blender Bake高模烘焙免费独立开发者、预算有限
Photoshop2D 滤镜$$快速转换、UI 纹理
NormalMap-Online在线 2D免费极低快速原型、学习测试
xNormal高模烘焙免费轻量专业烘焙
Materialize2D 转换免费从照片生成 PBR 材质

五、实战:用 Photoshop 从高度图生成法线贴图

这是最快捷的创建方式,适合有现成高度图或灰度纹理的场景。

  1. 准备高度图

    准备一张灰度图。白色 = 凸起(最高),黑色 = 凹陷(最低)。确保图片是 2 的幂尺寸(512、1024、2048 等),这是 GPU 纹理的基本要求。

  2. 应用法线贴图滤镜

    打开 Photoshop → 菜单栏 →滤镜 → 3D → 生成法线贴图(Filter → 3D → Generate Normal Map)。如果没有 3D 菜单,检查首选项中是否启用了图形处理器。

  3. 调节参数

    在弹出的对话框中调节以下关键参数:模糊(Blur)一般设为 0~1 避免细节丢失;细节缩放(Detail Scale)控制凹凸强度,默认 10,砖墙类可调至 15~20;反转 Y— Unity 使用 OpenGL 法线格式(Y+ 向上),确保不勾选 Invert Y。

  4. 保存并导入 Unity

    导出为 PNG 或 TGA。导入 Unity 后,在 Inspector 中将纹理类型设为Normal Map,勾选Create from Grayscale如果还没做法线转换。确保 Texture Shape 为 2D。

六、实战:用 Blender 从高模烘焙法线贴图

这是游戏资产制作的黄金标准流程,适合已有高模雕刻和低模拓扑的场景。

  1. 准备高低模

    低模:正确展开 UV、所有面朝外、面法线方向一致。高模:雕刻好细节,与低模对齐位置。两个模型应重叠在同一世界位置。

  2. 创建烘焙用材质

    选中低模,在 Shader Editor 中新建一个 Image Texture 节点,新建一张图片(如 2048×2048),保持该节点选中状态(橙色高亮边框)。这是关键一步,烘焙结果就输出到这个节点。

  3. 配置烘焙参数

    Render Properties → Bake → Bake Type 选择Normal。关键参数:Extrusion(挤出距离/ Cage)— 设为 0.01~0.05m 防止漏烘;Max Ray Distance— 通常 0.1m 足够;Space 保持Tangent

  4. 先选高模再选低模

    在 Object Mode 下先选中高模,然后 Shift 加选低模(低模为最后选中 = Active)。顺序不能错。

  5. 执行烘焙

    点击Bake按钮,等待完成。完成后在 UV Editor 中查看结果:蓝色为主色调,细节处有红绿变化,即表示成功。

  6. 导出

    Image → Save As → 导出为 PNG。导入 Unity,Texture Type 设为Normal Map

七、在 URP 中使用法线贴图

7.1 Unity URP Lit Shader

使用 URP 内置的 Lit Shader 是最简单的方式。将生成的法线贴图拖入材质的Normal Map槽位即可。URP Lit 内部已经完成了 TBN 矩阵构建、采样、解码和光照计算的全流程。

7.2 材质参数说明

参数作用建议值
Normal Map法线贴图纹理导入的 PNG/TGA
Normal Scale法线强度系数 (0~1)0.5~1.0,默认 1.0
Base Map基础颜色(Albedo)对应的漫反射贴图
Smoothness表面光滑度0.3~0.7(多数非金属)
Metallic金属度0(非金属)或 1(金属)

7.3 手动编写 URP 法线贴图 Shader

如果需要自定义光照或特殊效果,可以手写 Shader。以下是一个完整的 URP 法线贴图片段着色器:

Shader "Custom/URP_NormalLit" { Properties { _BaseMap("Base Map", 2D) = "white" {} _BaseColor("Base Color", Color) = (1,1,1,1) _NormalMap("Normal Map", 2D) = "bump" {} _NormalScale("Normal Scale", Range(0,2)) = 1 _Smoothness("Smoothness", Range(0,1)) = 0.5 } SubShader { Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" } Pass { Name "ForwardLit" Tags { "LightMode"="UniversalForward" } HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float4 tangentOS : TANGENT; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; float3 positionWS : TEXCOORD1; float3 normalWS : TEXCOORD2; float4 tangentWS : TEXCOORD3; }; TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); TEXTURE2D(_NormalMap); SAMPLER(sampler_NormalMap); CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; float4 _BaseColor; float4 _NormalMap_ST; float _NormalScale; float _Smoothness; CBUFFER_END Varyings vert(Attributes IN) { Varyings OUT; OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz); OUT.positionWS = TransformObjectToWorld(IN.positionOS.xyz); OUT.normalWS = TransformObjectToWorldNormal(IN.normalOS); OUT.tangentWS = float4( TransformObjectToWorldDir(IN.tangentOS.xyz), IN.tangentOS.w); OUT.uv = IN.uv; return OUT; } float4 frag(Varyings IN) : SV_Target { // 采样基底色 float4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv); float3 albedo = baseMap.rgb * _BaseColor.rgb; // 采样并解码切线空间法线 float4 normalTex = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, IN.uv); float3 tangentNormal = UnpackNormalScale(normalTex, _NormalScale); // 构建 TBN 矩阵,将法线从切线空间转换到世界空间 float3 N = normalize(IN.normalWS); float3 T = normalize(IN.tangentWS.xyz); float3 B = normalize(cross(N, T) * IN.tangentWS.w); float3x3 TBN = float3x3(T, B, N); float3 worldNormal = normalize(mul(tangentNormal, TBN)); // URP 主光照计算 Light mainLight = GetMainLight(); float NdotL = saturate(dot(worldNormal, mainLight.direction)); float3 diffuse = albedo * mainLight.color * NdotL; // 环境光 float3 ambient = SampleSH(worldNormal) * albedo; // 简易高光(Blinn-Phong) float3 viewDir = GetWorldSpaceViewDir(IN.positionWS); float3 halfDir = SafeNormalize(mainLight.direction + viewDir); float spec = pow(saturate(dot(worldNormal, halfDir)), 32.0); float3 specular = mainLight.color * spec * _Smoothness; return float4(diffuse + ambient + specular, 1.0); } ENDHLSL } } }

代码关键步骤:
UnpackNormalScale()— 解码法线贴图并乘以缩放系数
TBN 矩阵— 由世界空间的 T、B、N 三向量构建,将切线空间法线转换到世界空间
GetMainLight()— URP 内置函数,获取场景主方向光

八、常见问题与解决方案

问题 1:法线贴图导入后显示为灰色而非蓝色
原因:Unity 没有识别为法线贴图。
解决:Inspector 中将Texture Type设为Normal Map

问题 2:凹凸方向反了(凸的变凹)
原因:法线贴图的 Y 通道方向与 Unity 不匹配。Unity 使用 OpenGL 标准(Y+ = 向上),如果你的贴图是 DirectX 标准(Y+ = 向下),需要反转。
解决:在法线贴图的 Inspector 中勾选Flip Y Channel,或在 Photoshop 生成时不勾选 Invert Y。

问题 3:法线贴图在某些面上看起来是黑的
原因:模型的某些面法线方向反了,或者 UV 镜像导致切线空间的 winding order 不一致。
解决:检查模型面法线方向(Blender:Shift+N重新计算)、确保 UV 无镜像重叠。

问题 4:使用 UnpackNormal 报错
原因:没有包含正确的头文件。
解决:确保 include 了Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl

九、法线贴图的纹理导入设置

在 Unity 中正确导入法线贴图至关重要。以下是在 Inspector 中的推荐设置:

设置项推荐值说明
Texture TypeNormal Map必须设置,Unity 才会正确解码
Texture Shape2D标准 2D 纹理
sRGB (Color Texture)❌ 取消勾选法线贴图是数据纹理,不是颜色纹理,必须线性空间
Non-Power of 2ToNearest非 2 的幂尺寸自动缩放
CompressionNormal Quality / High Quality选择 Normal 压缩以使用 DXT5nm
Max Size2048 或根据需求多数情况 1024 或 2048 足够
Generate Mip Maps✅ 勾选生成多级渐远纹理,避免远处摩尔纹

关键:关闭 sRGB。法线贴图存储的是方向数据而非颜色数据。勾选 sRGB 会导致 Gamma 校正被应用到法线值上,使法线方向偏移,产生错误的光照结果。这是最常见的导入错误。

十、总结与最佳实践

  • 选对工具:简单转换用 Photoshop 或 NormalMap-Online;专业资产用 Substance Painter 烘焙;预算有限用 Blender。
  • 关闭 sRGB:法线贴图导入 Unity 后务必取消 sRGB 勾选。
  • 使用 UnpackNormal:永远用UnpackNormal()UnpackNormalScale()解码,不要手动*2-1
  • 注意 Y 轴方向:Unity 使用 OpenGL 法线格式(Y+ 向上),确保生成工具的输出格式匹配。
  • 法线贴图尺寸:通常 1024 或 2048 足够,过高分辨率对移动端性能影响显著。
  • 配合其他贴图:法线贴图与粗糙度贴图(Roughness)、AO 贴图配合使用,能产生更真实的材质效果。
  • 移动端优化:如果目标平台是移动端,考虑使用 ASTC 压缩格式,并在低端设备上将法线贴图降到 512。
http://www.zskr.cn/news/1513920.html

相关文章:

  • 流体智能体强化学习:动态群体协作的新范式
  • 儿童增高床垫品牌哪家好?自己用过才敢说 - 深圳市民HLL
  • 【毕业设计】基于 SpringBoot 的个性化旅游行程规划系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • 如何训练使用——焊接焊缝缺陷检测数据集,5类,1400张。
  • 68HC908LJ12深度解析:8位MCU的Flash管理与低功耗设计实战
  • 嵌入式安全实践:基于IEC 60730标准的MCU硬件特性与软件自检设计
  • 南京日语培训班哪家强 2026年实力机构选择参考 - 品牌排行榜
  • LanzouAPI:一键获取蓝奏云直链的智能解析工具
  • 影刀RPA完全指南_团队共用RPA平台搭建流程管理监控与任务调度
  • Rust 异步 TCP 与自定义协议解析:从字节流到结构化消息
  • 【小白也能轻松用】保姆级零基础教学,OpenClaw 零代码一键部署全解析(含最新安装包)
  • 光伏风电并网逆变器在电网电压不平衡跌落时的正负序电流协同控制方法
  • 深入解析ARM7TDMI-S经典MCU:MAC71x6架构、外设实战与低功耗设计
  • 113、【Agent】【OpenCode】项目配置(package.json)
  • 基于MPC5748G的汽车以太网网关设计:硬件架构、安全实现与开发实践
  • 2026年PE给水管供应厂家:市政供水、农村饮水、DN300大口径、食品级耐低温热熔对接管品牌实力解析 - 品牌发掘
  • 2026年滤油机选购全维度分析:从技术路线到应用场景的调研报告 - 优质品牌商家
  • 腰肌劳损总睡不舒服,亲测好用的0干扰无弹簧床垫品牌整理 - 深圳市民HLL
  • 利用深度学习目标检测算法通用Yolov5训练电动车进电梯数据集 建立基于YOLOv5的电动车入梯识别系统 识别检测电梯进电动车的预警识别
  • 售前获客新玩法:AI售前智能体如何依托知识库提升转化
  • VC6平台MFC写的排序算法动态演示工具(冒泡/插入/希尔/堆排)
  • 前端微前端架构选型:Module Federation 与 qiankun 的对比实践
  • LLM 驱动的前端组件文档生成:从代码到 API 文档的自动化
  • 魔都购宠避雷王!浦东/闵行/徐汇三店直营,专治上海星期宠、皮肤病两大噩梦 - 萌宠俱乐部
  • 3步解锁原神帧率限制:免费提升游戏流畅度的完整指南
  • 解锁群晖Photos人脸识别:无需GPU的智能照片管理方案
  • 贝叶斯推断中的MNAR偏差:当缺失数据悄悄扭曲后验分布
  • 星露谷物语模组加载器SMAPI:让你的农场冒险无限扩展
  • 2026整体卫浴供应厂家专业实力考察:江苏上海山东源头企业,集成卫浴/酒店卫生间/旧改无障碍卫浴品牌精析 - 品牌发掘
  • 手把手实战CANN catlass算子模板库:从模板实例化到NPU性能调优