找回密码
 立即注册
查看: 158|回复: 0

基础且直白的Unity衬着-进行URP和默认管线的shader彼此转换-----(Unit和单盏灯光的shader)

[复制链接]
发表于 2024-7-15 17:44 | 显示全部楼层 |阅读模式
正式记录之前想问大师一个问题。此刻大师的项目都是在用哪一个管线进行制作呢。如果可以的话但愿看到笔者文章的同志们能在答复给不才一个答复,谢谢啦。
首先不管是哪个管线其实都是基于SRP(Scriptable Render Pipeline)可编译管线进行的拓展和担任。我们经常说的URP其实是早些年Unity制作的LWRP的升级版。相较于之前的版赋性能,上手度,可拓展性都有了较大的提升(虽然我依旧是感觉其实就是改了改名字而已)HDRP则是专门为高精度衬着和高精度的游戏所筹备的一个超级功能调集体。可以说Unity现有的所有最先进的效果和技术城市在HDRP傍边。自然其复杂度也是成倍的提升。
URP的Shader基础书写格式:

相较于默认管线的shaderlab分歧。URP和HDRP使用的是HLSL的书写方式和方式。可能和咱们之前熟shaderlab有一些小区别。但其实内核都是相通的。只要掌握了此中规律很快就能学会书写的方式,更何况我们还有万能的知乎和youtube呢。
书写一个HLSL的Unit:(对比默认CGLAB的写法会发现部门格式有较大改动)
  1. Shader ”Unlit/URPUnitShader”
  2. {
  3.     Properties
  4.     {
  5.         _MainTex (”Texture”, 2D) = ”white” {}
  6.         _BaseColor(”BaseColor”, Color) = (1,1,1,1)
  7.     }
  8.     SubShader
  9.     {
  10.         Tags { ”RenderPipline” = ”UniversalRenderPipline” ”RenderType”=”Opaque” }
  11.         LOD 100
  12.         //替换为HLSLINCLUDE
  13.         HLSLINCLUDE
  14.         #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
  15.         #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
  16.         struct a2v
  17.         {
  18.             float4 positionOS:POSITION;
  19.             float4 normalOS:NORMAL;
  20.             float2 texcoord:TEXCOORD;
  21.         };
  22.         struct v2f
  23.         {
  24.             float4 positionCS:SV_POSITION;
  25.             float2 texcoord:TEXCOORD;
  26.         };
  27.         CBUFFER_START(UnityPerMaterial)
  28.         float4 _MainTex_ST;
  29.         float4 _BaseColor;
  30.         CBUFFER_END
  31.         TEXTURE2D(_MainTex);
  32.         SAMPLER(sampler_MainTex);
  33.         ENDHLSL
  34.         Pass
  35.         {
  36.            HLSLPROGRAM
  37.            #pragma vertex Vert
  38.            #pragma fragment Frag
  39.            v2f Vert(a2v i)
  40.            {
  41.                v2f o;
  42.                o.positionCS = TransformObjectToHClip(i.positionOS.xyz);
  43.                o.texcoord = TRANSFORM_TEX(i.texcoord,_MainTex);
  44.                return o;
  45.            }
  46.            half4 Frag(v2f i):SV_TARGET
  47.            {
  48.                half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex,i.texcoord)*_BaseColor;
  49.                return tex;
  50.            }
  51.            ENDHLSL
  52.         }
  53.     }
  54. }
复制代码
对比一些默认管线的shader。
  1. Shader ”Unlit/DefUnitShader”
  2. {
  3.     Properties
  4.     {
  5.         _MainTex (”Texture”, 2D) = ”white” {}
  6.     }
  7.     SubShader
  8.     {
  9.         Tags { ”RenderType”=”Opaque” }
  10.         LOD 100
  11.         Pass
  12.         {
  13.             CGPROGRAM
  14.             #pragma vertex vert
  15.             #pragma fragment frag
  16.             // make fog work
  17.             #pragma multi_compile_fog
  18.             #include ”UnityCG.cginc”
  19.             struct appdata
  20.             {
  21.                 float4 vertex : POSITION;
  22.                 float2 uv : TEXCOORD0;
  23.             };
  24.             struct v2f
  25.             {
  26.                 float2 uv : TEXCOORD0;
  27.                 UNITY_FOG_COORDS(1)
  28.                 float4 vertex : SV_POSITION;
  29.             };
  30.             sampler2D _MainTex;
  31.             float4 _MainTex_ST;
  32.             v2f vert (appdata v)
  33.             {
  34.                 v2f o;
  35.                 o.vertex = UnityObjectToClipPos(v.vertex);
  36.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
  37.                 UNITY_TRANSFER_FOG(o,o.vertex);
  38.                 return o;
  39.             }
  40.             fixed4 frag (v2f i) : SV_Target
  41.             {
  42.                 // sample the texture
  43.                 fixed4 col = tex2D(_MainTex, i.uv);
  44.                 // apply fog
  45.                 UNITY_APPLY_FOG(i.fogCoord, col);
  46.                 return col;
  47.             }
  48.             ENDCG
  49.         }
  50.     }
  51. }
复制代码
对比会发现其实答题的布局没有改变但是在声明变量的时候多了新的声明方式
  1.         CBUFFER_START(UnityPerMaterial)
  2.         float4 _MainTex_ST;
  3.         float4 _BaseColor;
  4.         CBUFFER_END
  5.         TEXTURE2D(_MainTex);
  6.         SAMPLER(sampler_MainTex);
  7.         ENDHLSL
复制代码
和默认的有斗劲大的区别。这里需要记一下。容易犯错。接下来给shader加上雾效。
  1. Shader ”Unlit/URPUnitShader”
  2. {
  3.     Properties
  4.     {
  5.         _MainTex (”Texture”, 2D) = ”white” {}
  6.         _BaseColor(”BaseColor”, Color) = (1,1,1,1)
  7.         
  8.     }
  9.     SubShader
  10.     {
  11.         Tags { ”RenderPipline” = ”UniversalRenderPipline” ”RenderType”=”Opaque” }
  12.         LOD 100
  13.         //替换为HLSLINCLUDE
  14.         HLSLINCLUDE
  15.         //插手雾气
  16.         #pragma multi_compile_fog
  17.         #define FOG 1
  18.         #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
  19.         #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
  20.         struct a2v
  21.         {
  22.             float4 positionOS:POSITION;
  23.             float4 normalOS:NORMAL;
  24.             float2 texcoord:TEXCOORD;
  25.         };
  26.         struct v2f
  27.         {
  28.             float4 positionCS:SV_POSITION;
  29.             float2 texcoord:TEXCOORD;
  30.             //URP的雾气需要手动去给一个TEXCOORD。
  31.             #ifdef FOG
  32.             float fogFactor : TEXCOORD1;
  33.             #endif
  34.         };
  35.         CBUFFER_START(UnityPerMaterial)
  36.         float4 _MainTex_ST;
  37.         float4 _BaseColor;
  38.         CBUFFER_END
  39.         TEXTURE2D(_MainTex);
  40.         SAMPLER(sampler_MainTex);
  41.         ENDHLSL
  42.         Pass
  43.         {
  44.            Name ”Forward”
  45.            Tags{”LightMode” = ”UniversalForward”}
  46.            HLSLPROGRAM
  47.            #pragma vertex Vert
  48.            #pragma fragment Frag
  49.            v2f Vert(a2v i)
  50.            {
  51.                v2f o;
  52.                o.positionCS = TransformObjectToHClip(i.positionOS.xyz);
  53.                o.texcoord = TRANSFORM_TEX(i.texcoord,_MainTex);
  54.                #ifdef FOG
  55.                o.fogFactor = ComputeFogFactor(o.positionCS.z);
  56.                #endif
  57.                return o;
  58.            }
  59.            half4 Frag(v2f i):SV_TARGET
  60.            {
  61.                half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex,i.texcoord)*_BaseColor;
  62.                #ifdef FOG
  63.                tex = float4(MixFog(tex.rgb,i.fogFactor),1);
  64.                #endif
  65.                return tex;
  66.            }
  67.            ENDHLSL
  68.         }
  69.     }
  70. }
复制代码
对比于默认管线的雾气书写方式更加自定义。(变体可以按照需要增加或者删减。)
给URP的shader增加简易的光照和影子:

了解了基本的书写格式后面可以开始进行进一步的书写。加上简单的光照和影子。其实和默认管线的写法类似。
  1. Shader ”Unlit/URPLambertShader”
  2. {
  3.     Properties
  4.     {
  5.         _MainTex (”Texture”, 2D) = ”white” {}
  6.         _BaseColor(”BaseColor”, Color) = (1,1,1,1)
  7.         
  8.     }
  9.     SubShader
  10.     {
  11.         Tags { ”RenderPipline” = ”UniversalRenderPipline” ”RenderType”=”Opaque” }
  12.         LOD 100
  13.         //替换为HLSLINCLUDE
  14.         HLSLINCLUDE
  15.         //插手雾气
  16.         #pragma multi_compile_fog
  17.         #define FOG 1
  18.         #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
  19.         #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
  20.         struct a2v
  21.         {
  22.             float4 positionOS:POSITION;
  23.             float4 normalOS:NORMAL;
  24.             float2 texcoord:TEXCOORD;
  25.         };
  26.         struct v2f
  27.         {
  28.             float4 positionCS:SV_POSITION;
  29.             float2 texcoord:TEXCOORD0;
  30.             float3 normal: TEXCOORD1;
  31.             //URP的雾气需要手动去给一个TEXCOORD。
  32.             #ifdef FOG
  33.             float fogFactor : TEXCOORD2;
  34.             #endif
  35.         };
  36.         CBUFFER_START(UnityPerMaterial)
  37.         float4 _MainTex_ST;
  38.         float4 _BaseColor;
  39.         CBUFFER_END
  40.         TEXTURE2D(_MainTex);
  41.         SAMPLER(sampler_MainTex);
  42.         ENDHLSL
  43.         Pass
  44.         {
  45.            Name ”Forward”
  46.            Tags{”LightMode” = ”UniversalForward”}
  47.            HLSLPROGRAM
  48.            #pragma vertex Vert
  49.            #pragma fragment Frag
  50.            v2f Vert(a2v i)
  51.            {
  52.                v2f o;
  53.                o.positionCS = TransformObjectToHClip(i.positionOS.xyz);
  54.                o.texcoord = TRANSFORM_TEX(i.texcoord,_MainTex);
  55.                o.normal = TransformObjectToWorldNormal(i.normalOS.xyz,true);
  56.                #ifdef FOG
  57.                o.fogFactor = ComputeFogFactor(o.positionCS.z);
  58.                #endif
  59.                return o;
  60.            }
  61.            half4 Frag(v2f i):SV_TARGET
  62.            {
  63.                half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex,i.texcoord)*_BaseColor;
  64.                //调用Lighting.hlsl中提供的函数体。
  65.                Light light = GetMainLight();
  66.                real4 lightColor = real4(light.color, 1);
  67.                float3 lightDir = normalize(light.direction);
  68.                float lightAtenuation = dot(lightDir, i.normal);
  69.                //Lambert
  70.                tex *= lightAtenuation*lightColor;
  71.                //HalfLambert
  72.                //tex *= lightAtenuation*lightColor*0.5+0.5
  73.                
  74.                #ifdef FOG
  75.                tex = float4(MixFog(tex.rgb,i.fogFactor),1);
  76.                #endif
  77.                return tex;
  78.            }
  79.            ENDHLSL
  80.         }
  81.     }
  82. }
复制代码
CBUFFER_START和CBUFFER_END,对于变量是单个材质独有的时候建议放在这里面,以提高性能。CBUFFER(常量缓冲区)的空间较小,不适合存放纹理贴图这种大量数据的数据类型。HLSL贴图的采样函数和采样器函数,TEXTURE2D (_MainTex)和SAMPLER(sampler_MainTex)。
继续加上自暗影:(暂时只加一盏灯光的。)
  1. Shader ”Unlit/URPLambertShader”
  2. {
  3.     Properties
  4.     {
  5.         _MainTex (”Texture”, 2D) = ”white” {}
  6.         _BaseColor(”BaseColor”, Color) = (1,1,1,1)
  7.         _BaseShadowContral(”DarkPlaceContral”, float) = 0.5
  8.         _SelfShadowPower(”SelfShadow”, Range(0,1)) = 0.5
  9.         _SelfShadowColor(”SelfShadowColor”, Color) = (1,1,1,1)
  10.         
  11.     }
  12.     SubShader
  13.     {
  14.         Tags { ”RenderPipline” = ”UniversalRenderPipline” ”RenderType”=”Opaque” }
  15.         LOD 100
  16.         //替换为HLSLINCLUDE
  17.         HLSLINCLUDE
  18.         //插手雾气
  19.         #pragma multi_compile_fog
  20.         #define FOG 1
  21.         #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
  22.         #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
  23.         #include”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl”
  24.         struct a2v
  25.         {
  26.             float4 positionOS:POSITION;
  27.             float4 normalOS:NORMAL;
  28.             float2 uv:TEXCOORD;
  29.             float4 tangentOS : TANGENT;
  30.         };
  31.         struct v2f
  32.         {
  33.             float4 positionCS:SV_POSITION;
  34.             float3 positionWS : TEXCOORD0;
  35.             float2 uv:TEXCOORD1;
  36.             float3 normalWS: TEXCOORD2;
  37.             //URP的雾气需要手动去给一个TEXCOORD。
  38.             #ifdef FOG
  39.             float fogFactor : TEXCOORD3;
  40.             #endif
  41.             //URP的自暗影需要手动给一个TEXCOORD.
  42.         };
  43.         CBUFFER_START(UnityPerMaterial)
  44.         float _BaseShadowContral;
  45.         float4 _MainTex_ST;
  46.         float4 _BaseColor;
  47.         float _SelfShadowPower;
  48.         float4 _SelfShadowColor;
  49.         CBUFFER_END
  50.         TEXTURE2D(_MainTex);
  51.         SAMPLER(sampler_MainTex);
  52.         ENDHLSL
  53.         Pass
  54.         {
  55.            Name ”Forward”
  56.            Tags{”LightMode” = ”UniversalForward”}
  57.            HLSLPROGRAM
  58.            
  59.            #pragma vertex Vert
  60.            #pragma fragment Frag
  61.             
  62.            //插手暗影
  63.            #pragma multi_compile _ADD_LIGHT_ON _ADD_LIGHT_OFF
  64.            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
  65.            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
  66.            #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
  67.            #pragma multi_compile _ _SHDOWS_SOFT
  68.            //插手新的光照结算(暂时停用)。
  69.            real3 ShadeSingleLight(Light light, half3 normalWS, bool isAdditionalLight, half3 MainColor)
  70.            {
  71.                //半兰伯特计算。
  72.                half NdotL = saturate(dot(normalWS, light.direction) *_BaseShadowContral+(1-_BaseShadowContral));
  73.                half3 diffuseColor = light.color * (NdotL * light.distanceAttenuation) * MainColor.rgb;
  74.                half Atten = clamp(light.shadowAttenuation +_SelfShadowPower, 0,1);
  75.                half3 AttenColor = _SelfShadowColor * (1-Atten) + Atten;
  76.                //返回最后的颜色
  77.                return diffuseColor * AttenColor;
  78.             }
  79.            v2f Vert(a2v i)
  80.            {
  81.                v2f o;
  82.                VertexPositionInputs positionInputs = GetVertexPositionInputs(i.positionOS.xyz);
  83.                o.positionCS = positionInputs.positionCS;
  84.                o.positionWS = positionInputs.positionWS;
  85.                
  86.                VertexNormalInputs normalInput = GetVertexNormalInputs(i.normalOS, i.tangentOS);
  87.                o.normalWS = NormalizeNormalPerVertex(normalInput.normalWS);
  88.                o.uv = TRANSFORM_TEX(i.uv,_MainTex);
  89.                #ifdef FOG
  90.                o.fogFactor = ComputeFogFactor(o.positionCS.z);
  91.                #endif
  92.                //插手自暗影绘制回调。
  93.                return o;
  94.            }
  95.            half4 Frag(v2f i):SV_TARGET
  96.            {
  97.                half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex,i.uv)*_BaseColor;
  98.                //设置需要的基础属性
  99.                half3 normalWS = NormalizeNormalPerPixel(i.normalWS);
  100.                //get shadow coordinate
  101.                float4 shadowCoord = TransformWorldToShadowCoord(i.positionWS);
  102.                Light mainLight = GetMainLight();
  103.                mainLight.shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
  104.                half3 mainLightResult = ShadeSingleLight(mainLight, normalWS, false,tex.rgb);
  105.                //自暗影计算
  106.                //调用Lighting.hlsl中提供的函数体。
  107.                float4 color = float4(mainLightResult,1);
  108.                
  109.                #ifdef FOG
  110.                color = float4(MixFog(color.rgb,i.fogFactor),1);
  111.                #endif
  112.                return color;
  113.            }
  114.            ENDHLSL
  115.         }
  116.         //使用Unity提供的shadowcaster;UsePass不知道为啥会掉效
  117.         UsePass ”Universal Render Pipeline/Lit/ShadowCaster”
  118.     }
  119. }
复制代码
URP的HLSL语言中大量运用了变体来开启或封锁功能。非常的便利。(终于可以直接拿现有的功能模块在shader中调用了)不外相对的。也会限制制作者的阐扬。有空的话最好还是从0开始本身全部实现一遍,斗劲项目需求千变万化。
多展灯光的记录后续再补充吧。下次吧shadow和shadowcaster自定义一遍便利后续进行特定改削。

                                                                                                            记录日期: 2022/9/15
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-17 02:47 , Processed in 0.098058 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表