如何将自定义Unity Shader转换为URP兼容版本?解决切换后失效问题
自定义World Shader适配URP的转换方法
原着色器基于Unity内置渲染管线的Surface Shader体系,URP不兼容这套传统实现,需通过以下修改完成适配:
核心转换要点
- 为SubShader添加URP专属标签,让渲染管线识别该着色器
- 替换CG语法为URP优先支持的HLSL语法,引入URP内置函数库
- 调整Surface Shader指令和输出结构体,适配URP的光照模型
- 修正世界空间法线的采样逻辑,避免模型变换导致的错误
修改后的完整着色器代码
Shader "World Shader/URP" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _TextureScale ("Texture Scale", float) = 1 //[NoScaleOffset] _BumpMap ("Normalmap", 2D) = "bump" {} } SubShader { Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" // 指定适配URP } LOD 250 HLSLPROGRAM #pragma surface surf Standard fullforwardshadows alpha:fade #pragma target 3.0 // 引入URP核心库与光照库 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" sampler2D _MainTex; float _TextureScale; //sampler2D _BumpMap; struct Input { float2 uv_MainTex; float3 worldPos; float3 worldNormal; INTERNAL_DATA // 用于正确获取世界空间法线 }; float myFmod(float a, float b) { float c = frac(abs(a / b)) * abs(b); return c; } void surf (Input IN, inout SurfaceOutputStandard o) { float x = IN.worldPos.x * _TextureScale; float y = IN.worldPos.y * _TextureScale; float z = IN.worldPos.z * _TextureScale; // 使用URP内置函数获取正确的世界空间法线 float isUp = abs(WorldNormalVector(IN, float3(0,1,0)).y); float2 offset = float2(myFmod(z + x * (1 - isUp), 0.0625), myFmod(y + x * isUp, 0.0625)); fixed4 c = tex2D(_MainTex, IN.uv_MainTex + offset); o.Albedo = c.rgb; o.Alpha = 1; o.Metallic = 0; // Standard输出结构体必填参数 o.Smoothness = 0; //o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex)); } ENDHLSL } FallBack "Hidden/Universal Render Pipeline/FallbackError" }
关键改动说明
- 渲染管线标识:在SubShader的Tags中添加
"RenderPipeline"="UniversalPipeline",这是URP识别着色器的必要条件 - 语法与库替换:将
CGPROGRAM/ENDCG改为HLSLPROGRAM/ENDHLSL,同时引入URP专属的核心库与光照库,替代传统内置库 - Surface指令调整:使用
#pragma surface surf Standard fullforwardshadows指定URP支持的Standard光照模型,确保光照计算符合URP逻辑 - 法线处理优化:在Input结构体的
worldNormal后添加INTERNAL_DATA,配合WorldNormalVector函数获取不受模型缩放/旋转影响的世界空间法线 - 输出结构体更新:将原
SurfaceOutput替换为SurfaceOutputStandard,这是URP中Standard光照模型对应的输出结构体,需显式指定Metallic和Smoothness参数(即使不需要金属质感,也需设为0) - 回退Shader调整:将原FallBack改为URP默认的错误回退Shader,确保在不兼容场景下给出明确提示
额外提示
- 若启用法线贴图,取消注释_BumpMap相关代码后,需确保
o.Normal赋值逻辑正确,且Input结构体的法线处理配置完整 - 若要适配SRP Batcher优化,需将着色器属性包裹在
CBUFFER_START(UnityPerMaterial)块中 - 测试前需确认Project Settings → Graphics中已正确指定URP的Render Asset
内容的提问来源于stack exchange,提问作者Errant Wanderer
相关产品推荐
相关产品推荐

