Unity URP法线贴图实现教程

前言

在Unity URP(Universal Render Pipeline)中实现法线贴图效果,可以通过以下步骤完成。法线贴图通过修改表面法线方向模拟凹凸细节,无需增加几何复杂度。

对惹,这里有一 个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!

完整实现步骤:

1. 准备法线贴图

  • 使用图像软件(如Photoshop或Substance)创建法线贴图,或从资源商店获取
  • 导入设置 :
    • 纹理类型:Default
    • 纹理形状:Texture2D
    • 勾选 Bump Map(自动切换为法线贴图模式)
    • 压缩格式:推荐 BC5(DXT5nm)或 BC7

2. 创建URP材质

  • 在Project窗口右键:Create > Material
  • 使用URP内置着色器:
    • 选择Shader:Universal Render Pipeline > Lit
    • 或 Universal Render Pipeline > Simple Lit(简化版)

3. 配置材质参数

  • 在Material Inspector中:
    • Surface Type:根据需求选 Opaque/Transparent
    • 将法线贴图拖拽到 Normal Map 插槽
    • 调整 Normal Scale(通常0.5-1.5)控制凹凸强度
    • 设置基础贴图(Albedo)和其他参数

4. 应用到模型

  • 将材质拖拽到场景中的模型上
  • 确保模型有UV坐标(可在导入设置中检查)

5. 自定义Shader(可选进阶)

如果需要特殊效果,可编写自定义Shader:

复制代码
Shader "Custom/NormalMapShader" {
    Properties {
        _MainTex("Albedo", 2D) = "white" {}
        _NormalMap("Normal Map", 2D) = "bump" {}
        _NormalScale("Normal Scale", Range(0,2)) = 1
    }
    
    SubShader {
        Tags { "RenderPipeline"="UniversalPipeline" }
        
        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        ENDHLSL
        
        Pass {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            struct Attributes {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
                float3 normalOS : NORMAL;
                float4 tangentOS : TANGENT;
            };
            
            struct Varyings {
                float4 positionCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 normalWS : TEXCOORD1;
                float4 tangentWS : TEXCOORD2;
            };
            
            sampler2D _MainTex;
            sampler2D _NormalMap;
            float _NormalScale;
            
            Varyings vert(Attributes IN) {
                Varyings OUT;
                // 顶点变换
                VertexPositionInputs posInput = GetVertexPositionInputs(IN.positionOS.xyz);
                OUT.positionCS = posInput.positionCS;
                OUT.uv = IN.uv;
                
                // 法线和切线计算
                VertexNormalInputs normInput = GetVertexNormalInputs(IN.normalOS, IN.tangentOS);
                OUT.normalWS = normInput.normalWS;
                OUT.tangentWS = float4(normInput.tangentWS, IN.tangentOS.w);
                
                return OUT;
            }
            
            half4 frag(Varyings IN) : SV_Target {
                // 采样法线贴图
                float4 normalSample = tex2D(_NormalMap, IN.uv);
                float3 tangentNormal = UnpackNormalScale(normalSample, _NormalScale);
                
                // 构建TBN矩阵
                float3 normalWS = IN.normalWS;
                float3 tangentWS = IN.tangentWS.xyz;
                float3 bitangentWS = cross(normalWS, tangentWS) * IN.tangentWS.w;
                float3x3 TBN = float3x3(tangentWS, bitangentWS, normalWS);
                
                // 转换到世界空间
                float3 finalNormal = mul(tangentNormal, TBN);
                
                // 光照计算(简单漫反射)
                Light mainLight = GetMainLight();
                float NdotL = saturate(dot(finalNormal, mainLight.direction));
                half3 albedo = tex2D(_MainTex, IN.uv).rgb;
                half3 diffuse = albedo * NdotL * mainLight.color;
                
                return half4(diffuse, 1);
            }
            ENDHLSL
        }
    }
}

关键注意事项:

  1. 切线空间要求:
  • 模型必须包含切线(Tangent)数据
  • 检查导入设置:Model > Normals & Tangents 设为 Calculate
  1. 性能优化:
  • 移动平台使用 Normal Quality 设置为 Low(16位精度)
  • 复杂场景启用 Batching 减少Draw Calls
  1. 常见问题排查:
  • 法线反向 :尝试调整 Normal Scale 为负值
  • 接缝问题:确保UV展开无重叠,检查模型拓扑
  • 光照无反应:确认场景中有URP灯光(Directional Light)

增强效果技巧:

  • 视差贴图 :在法线基础上添加高度偏移

    float2 parallaxUV = IN.uv + (tangentNormal.xy * _HeightScale);

  • 光滑度控制:将法线信息与粗糙度贴图结合

  • 双面渲染 :添加 Cull Off 指令支持双面法线

通过以上步骤,可在URP中高效实现法线贴图效果,显著提升模型表面细节表现力。

更多教学视

Unity3D​www.bycwedu.com/promotion_channels/2146264125

相关推荐
第九序言T7 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
龙亘川8 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
程序喵大人9 小时前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
小贺儿开发9 小时前
《流光绘忆》Unity 沉浸式光影互动
科技·unity·ai·程序员·工具·互动·光影
Raas1009 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
专注仿真10 小时前
线性回归和逻辑回归算法详解
开发语言·人工智能·python·大模型训练·控制算法
jimy111 小时前
C++ 中的 `T&&`:右值引用与转发引用
开发语言·c++
呆呆虫1211 小时前
用 orjson 加速 SerpBase 响应解析:基准对比与注意事项
开发语言·php
SmalBox11 小时前
07-02-打包系统-压缩与加密策略
unity3d·游戏开发
心疼你的一切11 小时前
Python自动发邮件实战定时发报表
大数据·开发语言·python