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

基础且直白的Unity渲染-进行URP和默认管线的shader相互 ...

[复制链接]
发表于 2022-10-1 14:31 | 显示全部楼层 |阅读模式
URP的多光照和默认管线的书写方法与些许不同。需要进行多次变体的指定。
书写一个可以支持环境光照和lightmapshader

首先需要哦明确我们要引用的属性和变体。
           //======================ShadowNewUse=====================
           #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
           #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
           #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
           #pragma multi_compile _ _SHDOWS_SOFT
           //=======================================================
           //=======================设置LIghtmap变体==================
           #pragma multi_compile _LIGHTMAP_ON
           #pragma multi_compile _DIRLIGHTMAP_COMBINED
           #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
           #pragma multi_compile _ SHADOWS _SHADOWMASK
           #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
           //========================================================
URP的许多功能都需要进行变体指定。例如Unity所提供的lightmap的烘焙方式也是需要进行指定才可以让shader进行调用 ,像以前在默认里根据需要进行手动的去指定会需要增加更多的代码。一般没有特殊需求没必要重写。  
接下来的环境光照GI获取要稍微麻烦一点儿。不像我们在在默认管线里直接调用一个简单的ShaderLab命令URP的HLSL需要手动指定一个TEXCOORD。看下简略的代码
        struct a2v
        {
            //获取模型本身的属性。
            float4 position:POSITION;
            float4 normal:NORMAL;
            float4 uv:TEXCOORD0;
            //获取Lightmap用UV信息。
            float4 LightmapUV: TEXCOORD1;

            float4 tangent:TANGENT;

        };

           v2f Vert(a2v i)
           {
               v2f o;
               VertexPositionInputs positionInputs = GetVertexPositionInputs(i.position.xyz);
               o.position = positionInputs.positionCS;
               o.worldposition = positionInputs.positionWS;
               
               VertexNormalInputs normalInput = (GetVertexNormalInputs(i.normal));
               o.worldnormal = NormalizeNormalPerVertex(normalInput.normalWS);

               o.uv = TRANSFORM_TEX(i.uv,_MainTex);

               #ifdef FOG
               o.fogFactor = ComputeFogFactor(o.position.z);
               #endif
               //======================LightmapOrSHRebuild=======================
               OUTPUT_LIGHTMAP_UV(i.LightmapUV, unity_LightmapST, o.lightmapUVOrVertexSH.xy);
               OUTPUT_SH(normalInput.normalWS.xyz, o.lightmapUVOrVertexSH.xyz);

               
               return o;
           }

           half4 Frag(v2f i):SV_TARGET
           {
               half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex,i.uv)*_BaseColor;
               half3 WorldNormal = NormalizeNormalPerVertex(i.worldnormal);
               float4 shadowCoord = TransformWorldToShadowCoord(i.worldposition);

               //=====================GIUSE==============================
               float3 SH = i.lightmapUVOrVertexSH.xyz;
               float3 bakeGI = SAMPLE_GI(i.lightmapUVOrVertexSH.xy, SH, WorldNormal);
               //========================================================
               Light mainLight = GetMainLight();
               mainLight.shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
               half3 mainLightResult = ShadeSingleLight(mainLight, WorldNormal, false, tex.rgb, bakeGI);

               float4 color = float4(mainLightResult,1);

               #ifdef FOG
               color = float4(MixFog(color.rgb,i.fogFactor),1);
               #endif   

               return color;

           }

在URP中GI的获取需要使用SAMPLE_GI来获取。SAMPLE_GI的详细运转原理可以自行拆包查看。源码实在是有点儿太长了(有空在慢慢研究。)

继续加入lightmap的调用:

URP的lightmap的调用方法和传统的也是有点儿区别:需要利用DECLARE_LIGHTMAP_OR_SH来获取一张texcood来储存lightmap或者SH.其他的调用命令则和之前的一样设置一下变体就可以。
Shader "Unlit/URPLambertShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BaseColor ("BaseColor", Color) = (1,1,1,1)
        _RealtimeShadowPower("RealtimeShadowPower", Range(0,1)) = 0.5
        [Toggle]_fogContal("FogContal", float) = 1
    }
    SubShader
    {
        Tags {  "RenderPipline" = "UniversalRenderPipline" "RenderType"="Opaque"}
        LOD 100
        HLSLINCLUDE

        #pragma multi_compile_fog
        #define FOG _fogContal
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
        #include"Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
                #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
                #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"





        ENDHLSL


        Pass
        {
           Name "UniversalForward"
           Tags{"LightMode" = "UniversalForward"}
           HLSLPROGRAM
           //非图片的变量尽量放到CBUFFER中。


           #pragma vertex Vert
           #pragma fragment Frag

           //加入所需要的变体。
           #pragma multi_compile _ADD_LIGHT_ON _ADD_LIGHT_OFF

           //======================ShadowNewUse=====================
           #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
           #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
           #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
           #pragma multi_compile _ _SHDOWS_SOFT
           //=======================================================
           //=======================设置LIghtmap变体==================
           #pragma multi_compile _ LIGHTMAP_ON
           #pragma multi_compile _ DIRLIGHTMAP_COMBINED
           #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
           #pragma multi_compile _ SHADOWS _SHADOWMASK
           #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
           //========================================================

           struct a2v
           {
               //获取模型本身的属性。
               float4 position:POSITION;
               float3 normal:NORMAL;
               float2 uv:TEXCOORD0;
               //获取Lightmap用UV信息。
               float2 lightmapUV: TEXCOORD1;
           
               float4 tangent:TANGENT;
           
           };
           CBUFFER_START(UnityPerMaterial)
           float4 _BaseColor;
           float4 _MainTex_ST;
           float _RealtimeShadowPower;
           
           CBUFFER_END
           
           TEXTURE2D(_MainTex);
           SAMPLER(sampler_MainTex);





           struct v2f
           {
               float4 position:SV_POSITION;
               float3 worldposition: TEXCOORD0;
               float2 uv:TEXCOORD1;
               half3 normalWS:TEXCOORD2;
               #ifdef FOG
               float fogFactor : TEXCOORD3;
               #endif

               //设置lighmap和SH的采样属性
               //=================利用变体命令===============
               //float2 lightmapUV : TEXCOORD4;
               //float3 vertexSH : TEXCOORD5;
               DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 4);
               //float3 Lightmaptest : TEXCOORD5;
               //=================手动设置采样命令============
               /*#if defined(LIGHTMAP_ON)
                   #define DECLARE_LIGHTMAP_OR_SH(lmName, shName, index) float2 lmName : TEXCOORD##index
                   #define OUTPUT_LIGHTMAP_UV(lightmapUV, lightmapScaleOffset, OUT) OUT.xy = lightmapUV.xy * lightmapScaleOffset.xy + lightmapScaleOffset.zw;
                   #define OUTPUT_SH(normalWS, OUT)
               #else
                   #define DECLARE_LIGHTMAP_OR_SH(lmName, shName, index) half3 shName : TEXCOORD##index
                   #define OUTPUT_LIGHTMAP_UV(lightmapUV, lightmapScaleOffset, OUT)
                   #define OUTPUT_SH(normalWS, OUT) OUT.xyz = SampleSHVertex(normalWS)
               #endif
               */
               /*#ifdef _LIGHTMAP_ON
                   DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 4);
                   float2 lightmapUV : TEXCOORD4;
                   OUTPUT_LIGHTMAP_UV(lightmapUV, unity_LightmapST, );

                */

               //================手动调用GI================
               //float3 lightmapUVOrVertexSH:TEXCOORD4;
               //================================
               //#ifdef _LIGHTMAP_ON
               //float2 LightmapUV : TEXCOORD5;
               //#endif
           };



           //设置简易光照计算。(real是动态的精度变量声明)
           real3 ShadeSingleLight(Light light, half3 worldnormal, bool isAdditionalLight, half3 MainColor, half3 GI)
           {
               half3 final;
               //BaseLambert
               half NdotL = clamp(saturate(dot(worldnormal, light.direction)),0.0f,1.0f);
               half3 diffuseColor = light.color  *(NdotL* light.distanceAttenuation+GI) * MainColor.rgb;

               half Atten = light.shadowAttenuation;
               half3 AttenColor = clamp(lerp(GI, Atten,clamp(Atten + _RealtimeShadowPower,0,1)),0,1);

               #ifdef LIGHTMAP_ON
                      final =  MainColor * GI;
               #else
                      final = final = diffuseColor * AttenColor;  
               #endif

               //返回最后的颜色合成
               return  final;
           }

           //Lighamp采样(手动处理)(OLD)
                   float4 SampleLightmapHD( float2 UV )
                   {
                              return SAMPLE_TEXTURE2D( unity_Lightmap, samplerunity_Lightmap, UV );
                   }
                   float4 URPDecodeInstruction( )
                   {
                           return float4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0, 0);
                   }
           //手动设置变体解算



                   //======================(解码)=====================
           /*half3 SampleLightmapNew(float2 lightmapUVbase, half3 WorldNormal)
           {
               #ifdef UNITY_LIGHTMAP_FULL_HDR
                      bool encodeLightmap = false;
               #else
                      bool encodeLightmap = true;
               #endif

                   half4 decodeInstructions = half4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0h, 0.0h);
                   half4 transformCoords = half4(1,1,0,0);

               #ifdef DIRLIGHTMAP_COMBINED
                   return SampleDirectionalLightmap(TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap), TEXTURE2D_ARGS(unity_LightmapInd, samplerunity_Lightmap), lightmapUVbase, transformCoords, WorldNormal, encodeLightmap, decodeInstructions);
               #elif defined(LIGHTMAP_ON)
                   return SampleSingleLightmap(TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap), lightmapUVbase, transformCoords, encodeLightmap, decodeInstructions);
               #else
                   return half3(0.0,0.0,0.0);
               #endif


           }*/
                                   
           v2f Vert(a2v i)
           {
               v2f o;
               VertexPositionInputs positionInputs = GetVertexPositionInputs(i.position.xyz);
               o.position = positionInputs.positionCS;
               o.worldposition = positionInputs.positionWS;

                           float3 WorldNormal = TransformObjectToWorldNormal(i.normal);
               
               //VertexNormalInputs normalInput = (GetVertexNormalInputs(WorldNormal));
               o.normalWS = NormalizeNormalPerVertex(WorldNormal);

               o.uv = TRANSFORM_TEX(i.uv,_MainTex);

               #ifdef FOG
               o.fogFactor = ComputeFogFactor(o.position.z);
               #endif
               //======================LightmapOrSHRebuild(OLD)=======================
               //OUTPUT_LIGHTMAP_UV(i.LightmapUV, unity_LightmapST, o.lightmapUVOrVertexSH.xy);
               //OUTPUT_SH(normalInput.normalWS.xyz, o.lightmapUVOrVertexSH.xyz);
               //============================(New)==========================================
               OUTPUT_LIGHTMAP_UV(i.lightmapUV, unity_LightmapST, o.lightmapUV);
               OUTPUT_SH(o.normalWS, o.vertexSH);
               //======================================================================
               //#ifdef _LIGHTMAP_ON
               //o.LightmapUV = i.LightmapUV * unity_LightmapST.xy + unity_LightmapST.zw;
               //#endif
               return o;
           }

           half4 Frag(v2f i):SV_TARGET
           {
               float4 color = float4(1,1,1,1);
               
               half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex,i.uv)*_BaseColor;
               half3 WorldNormal = i.normalWS;
               float4 shadowCoord = TransformWorldToShadowCoord(i.worldposition);


               Light mainLight = GetMainLight();
               mainLight.shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
               //loat2 lightmapUVFrag = i.lightmapUV;
               //=====================GIUSE(OLD)(手动处理)==============================
               //float3 SH = i.lightmapUVOrVertexSH.xyz;
               //float3 bakeGI = SAMPLE_GI(i.lightmapUVOrVertexSH.xy, SH, WorldNormal);
               //==========================GIUSE(New)==============================
               float3 bakeGI = SAMPLE_GI(i.lightmapUV, i.vertexSH, WorldNormal);
               MixRealtimeAndBakedGI(mainLight, WorldNormal, bakeGI, half4(0,0,0,0));
               //========================================================


               //=================获取LIghtmap采样。=======================
               //float4 SampleLightmap = SampleLightmapHD(i.LightmapUV );
               //float4 URPDecodeInstructions = URPDecodeInstruction();
               //float3 decodeLightMap = DecodeLightmap(SampleLightmap,URPDecodeInstructions);
               //========================================
               //half3 SampleLightmapbase = SampleLightmapNew(lightmapUVFrag, WorldNormal);
               //========================================
               half3 mainLightResult = ShadeSingleLight(mainLight, WorldNormal, false, tex.rgb, bakeGI);


               color = float4(mainLightResult,1);
               
               #ifdef FOG
               color = float4(MixFog(color.rgb,i.fogFactor),1);
               #endif   

               return color;

           }

           ENDHLSL
            

        }
        //使用Unity提供的shadowcaster;UsePass不知道为啥有时候会失效。和ASE提供的shadercaster似乎有冲突。
        UsePass "Universal Render Pipeline/Lit/ShadowCaster"


    }
}URP的LIghtmap相较于之前的默认管线会更加的自由和方便。如果想要自行修改的话还是的去看HLSL里的函数块的运算命令。然后根据需要进行必要的修改。

加入多光照的功能:

Urp计算中的多光照是在单一Pass中进行。和默认管线需要新增Pass来实现有些不同。但Urp也有了限制。同屏幕下最多可以支持8盏实时灯光。
Shader "Unlit/URPLambertShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BaseColor("BaseColor", Color) = (1,1,1,1)
        _BaseShadowContral("DarkPlaceContral", float) = 0.5
        _SelfShadowPower("SelfShadow", Range(0,1)) = 0.5
        _SelfShadowColor("SelfShadowColor", Color) = (1,1,1,1)
        //===================================================================
        _shadowColor("ShadowColor", Color) = (0,0,0,0)
        _shadowStepH("ShadowStepMax", float) = 1
        _shadowStepL("ShadowStepMin", float) = 0
        
    }
    SubShader
    {
        Tags { "RenderPipline" = "UniversalRenderPipline" "RenderType"="Opaque" }
        LOD 100
        //替换为HLSLINCLUDE
        HLSLINCLUDE
        //加入雾气
        #pragma multi_compile_fog
        #define FOG 1
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
        #include"Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"

        struct a2v
        {
            float4 positionOS:POSITION;
            float4 normalOS:NORMAL;
            float2 uv:TEXCOORD;
            float4 tangentOS : TANGENT;



        };

        struct v2f
        {
            float4 positionCS:SV_POSITION;
            float3 positionWS : TEXCOORD0;
            float2 uv:TEXCOORD1;
            float3 normalWS: TEXCOORD2;
            //float3 viewWS: TEXCOORD3;
            //URP的雾气需要手动去给一个TEXCOORD。
            #ifdef FOG
            float fogFactor : TEXCOORD4;
            #endif

            //URP的自阴影需要手动给一个TEXCOORD.

        };

        CBUFFER_START(UnityPerMaterial)
        float _BaseShadowContral;
        float4 _MainTex_ST;
        float4 _BaseColor;
        float _SelfShadowPower;
        float4 _SelfShadowColor,_shadowColor;
        float _shadowStepH,_shadowStepL;

        CBUFFER_END

        TEXTURE2D(_MainTex);
        SAMPLER(sampler_MainTex);
        ENDHLSL


        Pass
        {
           Name "Forward"
           Tags{"LightMode" = "UniversalForward"}
           HLSLPROGRAM
           
           #pragma vertex Vert
           #pragma fragment Frag

            
           //加入阴影
           #pragma multi_compile _ADD_LIGHT_ON _ADD_LIGHT_OFF
           #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
           #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
           #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
           #pragma multi_compile _ _SHDOWS_SOFT

           //加入新的光照结算(暂时停用)。
           real3 ShadeSingleLight(Light light, half3 normalWS, bool isAdditionalLight, half3 MainColor)
           {
               //半兰伯特计算。
               half NdotL = dot(normalWS, light.direction);

               half LightSmooth = smoothstep(_shadowStepL, _shadowStepH, NdotL);
               half halfLambert = saturate(LightSmooth *_BaseShadowContral+(1-_BaseShadowContral));
               //暗部颜色计算。
               half3 darkmul = (1-halfLambert) * _shadowColor;

               half3 diffuseColor = (halfLambert * light.distanceAttenuation) * MainColor.rgb+darkmul;

               half Atten = clamp(light.shadowAttenuation +_SelfShadowPower, 0,1);
               half3 AttenColor = _SelfShadowColor * (1-Atten) + Atten;
               //返回最后的颜色
               return diffuseColor * AttenColor;
            }

           //额外光照。
           real3 ShadeSingleLightAdd(Light light, half3 normalWS, bool isAdditionalLight)
           {
               //半兰伯特计算。
               half NdotL = dot(normalWS, light.direction);

               half LightSmooth = smoothstep(_shadowStepL, _shadowStepH, NdotL);
               half halfLambert = saturate(LightSmooth *_BaseShadowContral+(1-_BaseShadowContral));
               //暗部颜色计算。
               half3 darkmul = (1-halfLambert) * _shadowColor;

               half3 diffuseColor = (halfLambert * light.distanceAttenuation)*light.color;

               half Atten = clamp(light.shadowAttenuation +_SelfShadowPower, 0,1);
               half3 AttenColor = _SelfShadowColor * (1-Atten) + Atten;
               //返回最后的颜色
               return diffuseColor * AttenColor;
            }


           v2f Vert(a2v i)
           {
               v2f o;

               VertexPositionInputs positionInputs = GetVertexPositionInputs(i.positionOS.xyz);
               o.positionCS = positionInputs.positionCS;
               o.positionWS = positionInputs.positionWS;
               
               VertexNormalInputs normalInput = GetVertexNormalInputs(i.normalOS);
               o.normalWS = NormalizeNormalPerVertex(normalInput.normalWS);

               o.uv = TRANSFORM_TEX(i.uv,_MainTex);

               #ifdef FOG
               o.fogFactor = ComputeFogFactor(o.positionCS.z);
               #endif
               //加入自阴影绘制回调。
               return o;

           }

           half4 Frag(v2f i):SV_TARGET
           {
               half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex,i.uv)*_BaseColor;
               //设置需要的基础属性
               half3 normalWS = NormalizeNormalPerPixel(i.normalWS);
               //get shadow coordinate
               float4 shadowCoord = TransformWorldToShadowCoord(i.positionWS);

               Light mainLight = GetMainLight();
               mainLight.shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
               half3 mainLightResult = ShadeSingleLight(mainLight, normalWS, false,tex.rgb);
               //自阴影计算



               //AdditionLight
               half3 additionalLightsSumResult = 0;
               #if _ADD_LIGHT_ON
                   int additionalLightsCount = GetAdditionalLightsCount();
                   for(int lightIndex = 0; lightIndex < additionalLightsCount; ++ lightIndex)
                   {
                       Light additionalLight = GetAdditionalLight(lightIndex, i.positionWS);   
                       additionalLight.shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
                       //上方函数的shadowAttenuation固定为1,需要下方函数来获取正确的值
                       //Light additionalLight = GetAdditionalLight(lightIndex, i.positionWS, half4(1,1,1,1));         
                       additionalLightsSumResult += ShadeSingleLightAdd(additionalLight, normalWS, true);
                     
                       //int perObjectLightIndex = GetPerObjectLightIndex(lightIndex);
                       //Light additionalLight = GetAdditionalPerObjectLight(perObjectLightIndex, i.positionWS); // use original positionWS for lighting
                       //additionalLight.shadowAttenuation = AdditionalLightRealtimeShadow(perObjectLightIndex, i.positionWS); // use offseted positionWS for shadow test
                       //
                       //additionalLightsSumResult += ShadeSingleLightAdd(additionalLight, normalWS, viewDirWS, true);
                   }
                   Light testLight = GetAdditionalLight(0, i.positionWS);
                   half3 testResult = ShadeSingleLightAdd(testLight, normalWS, true);
               #endif


               //调用Lighting.hlsl中提供的函数体。
               float4 color = float4(mainLightResult+additionalLightsSumResult,1);               
               
               
               #ifdef FOG
               color = float4(MixFog(color.rgb,i.fogFactor),1);
               #endif





               return color;

           }
           ENDHLSL

        }
        //使用Unity提供的shadowcaster;UsePass不知道为啥会失效
        UsePass "Universal Render Pipeline/Lit/ShadowCaster"



    }
}简易的书写了一版代码其实没多少。Unity内部帮我们提供了很多方便的函数命令我们只需要调用就可以的。但是如果想要更自定义的去实现自己的效果就得去翻看源码自行修改函数内的调用和运算了。URP的多光照是利用了for循环和if命令在单个Pass内进行多盏灯光的运算,运算逻辑挺简单的但是unity底层应该是做了很完善的优化。找时间看看,如果是正式项目还是建议都扒底层看看运算方法,毕竟手机平台千千万,出了BUG也知道怎么修复。
完整的代码:




可以明显的发现多灯光的影响下PASS数量依旧只有1次。对drawcall有不错的提升。不过相对的shader的复杂度也会有提升。算是有得必有失吧。

Shader "Unlit/URPLambertShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BaseColor ("BaseColor", Color) = (1,1,1,1)
        _RealtimeShadowPower("RealtimeShadowPower", Range(0,1)) = 0.5
        [Toggle]_fogContal("FogContal", float) = 1
    }
    SubShader
    {
        Tags {  "RenderPipline" = "UniversalRenderPipline" "RenderType"="Opaque"}
        LOD 100
        HLSLINCLUDE

        #pragma multi_compile_fog
        #define FOG _fogContal
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
        #include"Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
                #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
                #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"





        ENDHLSL


        Pass
        {
           Name "UniversalForward"
           Tags{"LightMode" = "UniversalForward"}
           HLSLPROGRAM
           //非图片的变量尽量放到CBUFFER中。


           #pragma vertex Vert
           #pragma fragment Frag

           //加入所需要的变体。
           #pragma multi_compile _ADD_LIGHT_ON _ADD_LIGHT_OFF

           //======================ShadowNewUse=====================
           #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
           #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
           #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
           #pragma multi_compile _ _SHDOWS_SOFT
           //=======================================================
           //=======================设置LIghtmap变体==================
           #pragma multi_compile _ LIGHTMAP_ON
           #pragma multi_compile _ DIRLIGHTMAP_COMBINED
           #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
           #pragma multi_compile _ SHADOWS _SHADOWMASK
           #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
           //========================================================

           struct a2v
           {
               //获取模型本身的属性。
               float4 position:POSITION;
               float3 normal:NORMAL;
               float2 uv:TEXCOORD0;
               //获取Lightmap用UV信息。
               float2 lightmapUV: TEXCOORD1;
           
               float4 tangent:TANGENT;
           
           };
           CBUFFER_START(UnityPerMaterial)
           float4 _BaseColor;
           float4 _MainTex_ST;
           float _RealtimeShadowPower;
           
           CBUFFER_END
           
           TEXTURE2D(_MainTex);
           SAMPLER(sampler_MainTex);





           struct v2f
           {
               float4 position:SV_POSITION;
               float3 worldposition: TEXCOORD0;
               float2 uv:TEXCOORD1;
               half3 normalWS:TEXCOORD2;
               #ifdef FOG
               float fogFactor : TEXCOORD3;
               #endif

               //设置lighmap和SH的采样属性
               //=================利用变体命令===============
               //float2 lightmapUV : TEXCOORD4;
               //float3 vertexSH : TEXCOORD5;
               DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 4);
               //float3 Lightmaptest : TEXCOORD5;
               //=================手动设置采样命令============
               /*#if defined(LIGHTMAP_ON)
                   #define DECLARE_LIGHTMAP_OR_SH(lmName, shName, index) float2 lmName : TEXCOORD##index
                   #define OUTPUT_LIGHTMAP_UV(lightmapUV, lightmapScaleOffset, OUT) OUT.xy = lightmapUV.xy * lightmapScaleOffset.xy + lightmapScaleOffset.zw;
                   #define OUTPUT_SH(normalWS, OUT)
               #else
                   #define DECLARE_LIGHTMAP_OR_SH(lmName, shName, index) half3 shName : TEXCOORD##index
                   #define OUTPUT_LIGHTMAP_UV(lightmapUV, lightmapScaleOffset, OUT)
                   #define OUTPUT_SH(normalWS, OUT) OUT.xyz = SampleSHVertex(normalWS)
               #endif
               */
               /*#ifdef _LIGHTMAP_ON
                   DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 4);
                   float2 lightmapUV : TEXCOORD4;
                   OUTPUT_LIGHTMAP_UV(lightmapUV, unity_LightmapST, );

                */

               //================手动调用GI================
               //float3 lightmapUVOrVertexSH:TEXCOORD4;
               //================================
               //#ifdef _LIGHTMAP_ON
               //float2 LightmapUV : TEXCOORD5;
               //#endif
           };



           //设置简易光照计算。(real是动态的精度变量声明)
           real3 ShadeSingleLight(Light light, half3 worldnormal, bool isAdditionalLight, half3 MainColor, half3 GI)
           {
               half3 final;
               //BaseLambert
               half NdotL = clamp(saturate(dot(worldnormal, light.direction)),0.0f,1.0f);
               half3 diffuseColor = light.color  *(NdotL* light.distanceAttenuation+GI) * MainColor.rgb;

               half Atten = light.shadowAttenuation;
               half3 AttenColor = clamp(lerp(GI, Atten,clamp(Atten + _RealtimeShadowPower,0,1)),0,1);

               #ifdef LIGHTMAP_ON
                      final =  MainColor * GI;
               #else
                      final = final = diffuseColor * AttenColor;  
               #endif

               //返回最后的颜色合成
               return  final;
           }

           //Lighamp采样(手动处理)(OLD)
                   float4 SampleLightmapHD( float2 UV )
                   {
                              return SAMPLE_TEXTURE2D( unity_Lightmap, samplerunity_Lightmap, UV );
                   }
                   float4 URPDecodeInstruction( )
                   {
                           return float4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0, 0);
                   }
           //手动设置变体解算



                   //======================(解码)=====================
           /*half3 SampleLightmapNew(float2 lightmapUVbase, half3 WorldNormal)
           {
               #ifdef UNITY_LIGHTMAP_FULL_HDR
                      bool encodeLightmap = false;
               #else
                      bool encodeLightmap = true;
               #endif

                   half4 decodeInstructions = half4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0h, 0.0h);
                   half4 transformCoords = half4(1,1,0,0);

               #ifdef DIRLIGHTMAP_COMBINED
                   return SampleDirectionalLightmap(TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap), TEXTURE2D_ARGS(unity_LightmapInd, samplerunity_Lightmap), lightmapUVbase, transformCoords, WorldNormal, encodeLightmap, decodeInstructions);
               #elif defined(LIGHTMAP_ON)
                   return SampleSingleLightmap(TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap), lightmapUVbase, transformCoords, encodeLightmap, decodeInstructions);
               #else
                   return half3(0.0,0.0,0.0);
               #endif


           }*/
                                   
           v2f Vert(a2v i)
           {
               v2f o;
               VertexPositionInputs positionInputs = GetVertexPositionInputs(i.position.xyz);
               o.position = positionInputs.positionCS;
               o.worldposition = positionInputs.positionWS;

                           float3 WorldNormal = TransformObjectToWorldNormal(i.normal);
               
               //VertexNormalInputs normalInput = (GetVertexNormalInputs(WorldNormal));
               o.normalWS = NormalizeNormalPerVertex(WorldNormal);

               o.uv = TRANSFORM_TEX(i.uv,_MainTex);

               #ifdef FOG
               o.fogFactor = ComputeFogFactor(o.position.z);
               #endif
               //======================LightmapOrSHRebuild(OLD)=======================
               //OUTPUT_LIGHTMAP_UV(i.LightmapUV, unity_LightmapST, o.lightmapUVOrVertexSH.xy);
               //OUTPUT_SH(normalInput.normalWS.xyz, o.lightmapUVOrVertexSH.xyz);
               //============================(New)==========================================
               OUTPUT_LIGHTMAP_UV(i.lightmapUV, unity_LightmapST, o.lightmapUV);
               OUTPUT_SH(o.normalWS, o.vertexSH);
               //======================================================================
               //#ifdef _LIGHTMAP_ON
               //o.LightmapUV = i.LightmapUV * unity_LightmapST.xy + unity_LightmapST.zw;
               //#endif
               return o;
           }

           half4 Frag(v2f i):SV_TARGET
           {
               float4 color = float4(1,1,1,1);
               
               half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex,i.uv)*_BaseColor;
               half3 WorldNormal = i.normalWS;
               float4 shadowCoord = TransformWorldToShadowCoord(i.worldposition);


               Light mainLight = GetMainLight();
               mainLight.shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
               //loat2 lightmapUVFrag = i.lightmapUV;
               //=====================GIUSE(OLD)(手动处理)==============================
               //float3 SH = i.lightmapUVOrVertexSH.xyz;
               //float3 bakeGI = SAMPLE_GI(i.lightmapUVOrVertexSH.xy, SH, WorldNormal);
               //==========================GIUSE(New)==============================
               float3 bakeGI = SAMPLE_GI(i.lightmapUV, i.vertexSH, WorldNormal);
               MixRealtimeAndBakedGI(mainLight, WorldNormal, bakeGI, half4(0,0,0,0));
               //========================================================


               //=================获取LIghtmap采样。=======================
               //float4 SampleLightmap = SampleLightmapHD(i.LightmapUV );
               //float4 URPDecodeInstructions = URPDecodeInstruction();
               //float3 decodeLightMap = DecodeLightmap(SampleLightmap,URPDecodeInstructions);
               //========================================
               //half3 SampleLightmapbase = SampleLightmapNew(lightmapUVFrag, WorldNormal);
               //========================================
               half3 mainLightResult = ShadeSingleLight(mainLight, WorldNormal, false, tex.rgb, bakeGI);


               color = float4(mainLightResult,1);
               
               #ifdef FOG
               color = float4(MixFog(color.rgb,i.fogFactor),1);
               #endif   

               return color;

           }

           ENDHLSL
            

        }
        //使用Unity提供的shadowcaster;UsePass不知道为啥有时候会失效。和ASE提供的shadercaster似乎有冲突。
        UsePass "Universal Render Pipeline/Lit/ShadowCaster"


    }
}


                                                                                                                  记录日期: 2022/9/30

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

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

本版积分规则

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

GMT+8, 2024-7-4 09:13 , Processed in 0.091221 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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