关于翻录

一些论坛:

1、https://cs.rin.ru/forum/viewtopic.php?t=100672
这个帖子是用来查询和请求解压虚幻文件的AES KEY。
2、https://www.gildor.org/smf/index.php
这个是Umoder下兴者自己建立的论坛,主要是用来讨论 (寻找方法)解决一些有特殊加密的虚幻文件
3、https://forum.xentax.com/index.php
这是一个论坛,主要是解决各种非“通用”引擎的游戏文件
4、https://discord.gg/7yixAVhS
这是个Discord聊天群,主要用来解决一些有特殊加密的Unity3D的文件

 

Shader "Omnee/Unlit/AnimCloud"
{
    Properties
    {
        [NoScaleOffset] _MainTex ("序列帧图集", 2D) = "white" {}
        _HorizontalAmount ("列数", float) = 4
        _VerticalAmount ("行数", float) = 4
        _Speed ("动画速度", float) = 1
        
        [Header(Color)]
        _Color("颜色", Color) = (1,1,1,1)
        _Brightness("亮度", float) = 1
        _Contrast("对比度", float) = 1
        
        [Header(MVNO)]
        [NoScaleOffset] _MVNOTex ("MVNO map", 2D) = "white" {}
        _MVIntensity("MV Intensity", float) = -0.01

        [Header(Vertex)]
        [Toggle] _FollowCamera("跟随摄像机", float) = 1
    }
    SubShader
    {
        Tags
        {
            "RenderType" = "Transparent"
            "RenderPipeline" = "UniversalPipeline"
            "Queue" = "Transparent"
        }
        LOD 100

        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite Off

            HLSLPROGRAM
            #pragma vertex UnlitPassVertex
            #pragma fragment UnlitPassFragment
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            #pragma shader_feature_vertex _ _FOLLOWCAMERA_ON

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            TEXTURE2D(_MVNOTex);
            SAMPLER(sampler_MVNOTex);

            CBUFFER_START(UnityPerMaterial)
                half4 _Color;
                float _HorizontalAmount;
                float _VerticalAmount;
                float _Speed;
                float _MVIntensity;
                float _Brightness;
                float _Contrast;
            CBUFFER_END

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            float3 RotateAboutAxisRadians(float3 In, float3 Axis, float Rotation)
            {
                float s = sin(Rotation);
                float c = cos(Rotation);
                float one_minus_c = 1.0 - c;

                Axis = normalize(Axis);

                float3x3 rot_mat = {
                    one_minus_c * Axis.x * Axis.x + c, one_minus_c * Axis.x * Axis.y - Axis.z * s, one_minus_c * Axis.z * Axis.x + Axis.y * s,
                    one_minus_c * Axis.x * Axis.y + Axis.z * s, one_minus_c * Axis.y * Axis.y + c, one_minus_c * Axis.y * Axis.z - Axis.x * s,
                    one_minus_c * Axis.z * Axis.x - Axis.y * s, one_minus_c * Axis.y * Axis.z + Axis.x * s, one_minus_c * Axis.z * Axis.z + c
                };

                float3 Out = mul(rot_mat, In);
                return Out;
            }

            Varyings UnlitPassVertex(Attributes input)
            {
                Varyings output = (Varyings)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);
                #if _FOLLOWCAMERA_ON
                float3 objDir = TransformWorldToObjectDir((-1 * mul((float3x3)UNITY_MATRIX_M, transpose(mul(UNITY_MATRIX_I_M, UNITY_MATRIX_I_V))[2].xyz)).xyz, true);
                float angle = atan2(objDir.x, objDir.z);
                float3 positionOS = RotateAboutAxisRadians(input.positionOS.xyz, float3(0, 1, 0), angle);
                #else
                float3 positionOS = input.positionOS.xyz;
                #endif

                output.positionCS = TransformObjectToHClip(positionOS);
                output.uv = input.uv;

                return output;
            }

            half4 UnlitPassFragment(Varyings input) : SV_Target0
            {
                UNITY_SETUP_INSTANCE_ID(input);

                float2 _SubUV = float2(_HorizontalAmount, _VerticalAmount);
                float2 diviceUV = input.uv / _SubUV;
                float timeCell = _SubUV.x * _SubUV.y * min(frac(_Time.x * _Speed), float(0.9999));
                float cellIndex = floor(timeCell);
                float2 uvMvno1 = diviceUV + float2(cellIndex, _SubUV.y - floor(cellIndex / _SubUV.y)) / _SubUV;
                float4 mvno1 = SAMPLE_TEXTURE2D(_MVNOTex, sampler_MVNOTex, uvMvno1);

                float timeCellFrac = frac(timeCell);
                float2 uvBaseColor1 = uvMvno1 + timeCellFrac * _MVIntensity * (mvno1.rg * 2 - 1) / _SubUV;
                float4 baseColor1 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uvBaseColor1);

                float nextCellIndex = cellIndex + 1;
                float2 uvMvno2 = diviceUV + float2(nextCellIndex, _SubUV.y - floor(nextCellIndex / _SubUV.y)) / _SubUV;
                float4 mvno2 = SAMPLE_TEXTURE2D(_MVNOTex, sampler_MVNOTex, uvMvno2);

                float2 uvBaseColor2 = uvMvno2 - (1 - timeCellFrac) * _MVIntensity * (mvno2.rg * 2 - 1) / _SubUV;
                float4 baseColor2 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uvBaseColor2);

                float4 lerpBaseColor = lerp(baseColor1, baseColor2, timeCellFrac);
                half3 baseColor = pow(lerpBaseColor.rgb * _Color.rgb * _Brightness, _Contrast);

                half4 color;
                color.rgb = baseColor;
                color.a = lerpBaseColor.a;
                return color;
            }
            ENDHLSL
        }
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
}

Shader "Omnee/Unlit/CircleMask"
{
    Properties
    {
        _Progress ("Progress", Range(0, 1)) = 0
        _Feather ("Feather Width", Range(0, 0.5)) = 0.1
    }
    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
            "Queue" = "Geometry"
        }
        LOD 100

        Pass
        {
            HLSLPROGRAM
            #pragma vertex UnlitPassVertex
            #pragma fragment UnlitPassFragment
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"


            CBUFFER_START(UnityPerMaterial)
                float _Progress;
                float _Feather;
            CBUFFER_END

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            Varyings UnlitPassVertex(Attributes input)
            {
                Varyings output = (Varyings)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);

                output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
                output.uv = input.uv;

                return output;
            }

            half4 UnlitPassFragment(Varyings input) : SV_Target0
            {
                UNITY_SETUP_INSTANCE_ID(input);

                float2 uv = input.uv;
                float dis = distance(uv, float2(0.5, 0.5));
                //float mask = step(dis, _Progress);
                float mask = smoothstep(dis, dis + _Feather, _Progress * 0.5);
                
                half4 color;
                color.rgb = mask;
                color.a = 1;
                return color;
            }
            ENDHLSL
        }
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
}

Shader "Omnee/Unlit/Frame Animation"
{
    Properties
    {
        _MainTex ("Sprite Sequence", 2D) = "white" {} // 序列帧图集
        _HorizontalAmount ("Horizontal (Columns)", Float) = 4 // 图片中有多少列
        _VerticalAmount ("Vertical (Rows)", Float) = 4 // 图片中有多少行
        _CurFrame ("Current Frame", float) = 0 //当前帧
    }
    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
            "Queue" = "Geometry"
        }
        LOD 100

        Pass
        {
            HLSLPROGRAM
            #pragma vertex UnlitPassVertex
            #pragma fragment UnlitPassFragment
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"


            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);

            CBUFFER_START(UnityPerMaterial)
                float _HorizontalAmount;
                float _VerticalAmount;
                float _CurFrame;
            CBUFFER_END

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            Varyings UnlitPassVertex(Attributes input)
            {
                Varyings output = (Varyings)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);

                output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
                output.uv = input.uv;

                return output;
            }

            half4 UnlitPassFragment(Varyings input) : SV_Target0
            {
                UNITY_SETUP_INSTANCE_ID(input);

                float curFrameInt = round(_CurFrame);
                float row = floor(curFrameInt / _HorizontalAmount);
                float column = curFrameInt % _HorizontalAmount;
                half2 uv = (input.uv + half2(column, row)) * rcp(half2(_HorizontalAmount, _VerticalAmount));
                half4 c = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
                return c;
            }
            ENDHLSL
        }
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
}

Shader "Omnee/Unlit/Frozen"
{
    Properties
    {
        [Header(Base)]
        _BaseMap("Base Map", 2D) = "white" {}
        [HDR] _BaseColor("Color", Color) = (1, 1, 1, 1)
        
        [Header(Normal)]
        _IceBumpMap ("Ice Normal map", 2D) = "bump" {}
        _IceBumpScale("Ice Normal Scale", Range(0,2)) = 1
        
        [Header(Reflection)]
        [HDR] _IceReflectColor ("Ice Reflection Color", Color) = (1,1,1,1)
        [NoScaleOffset] _IceReflectMatcap ("Ice Reflection Matcap", 2D) = "black" { }
        _FresnelBias("Fresnel Bias", Range(0,1)) = 0
        _FresnelPower("Fresnel Power", float) = 1
    }
    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
            "Queue" = "Geometry"
        }
        LOD 100
        
        //Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            HLSLPROGRAM
            #pragma vertex UnlitPassVertex
            #pragma fragment UnlitPassFragment
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            //#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);
            
            TEXTURE2D(_IceBumpMap);
            SAMPLER(sampler_IceBumpMap);
            
            TEXTURE2D(_IceReflectMatcap);
            SAMPLER(sampler_IceReflectMatcap);

            CBUFFER_START(UnityPerMaterial)
                float4 _BaseMap_ST;
                half4 _BaseColor;
                float4 _IceReflectColor;
                float4 _IceBumpMap_ST;
                float _IceBumpScale;
                float _FresnelBias;
                float _FresnelPower;
            CBUFFER_END

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
                float3 normalOS : NORMAL;
                float4 tangentOS : TANGENT;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;
                float3 positionWS : TEXCOORD1;
                float3 normalWS : TEXCOORD2;
                float3 tangentWS : TEXCOORD3;
                float3 bitangentWS : TEXCOORD4;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            Varyings UnlitPassVertex(Attributes input)
            {
                Varyings output = (Varyings)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);

                VertexPositionInputs posInputs = GetVertexPositionInputs(input.positionOS.xyz);
                output.positionCS = posInputs.positionCS;
                output.positionWS = posInputs.positionWS;
                
                output.uv = input.uv;
                
                VertexNormalInputs normalInputs = GetVertexNormalInputs(input.normalOS, input.tangentOS);
                output.normalWS = normalInputs.normalWS;
                output.tangentWS = normalInputs.tangentWS;
                output.bitangentWS = normalInputs.bitangentWS;
                
                return output;
            }
            

            half4 UnlitPassFragment(Varyings input) : SV_Target0
            {
                UNITY_SETUP_INSTANCE_ID(input);

                float3 NModel = normalize(input.normalWS);
                float3 T = normalize(input.tangentWS);
                float3 B = normalize(input.bitangentWS);
                float3x3 TBN = float3x3(T, B, NModel);
                
                half4 iceNormalMap = SAMPLE_TEXTURE2D(_IceBumpMap, sampler_IceBumpMap, input.uv * _IceBumpMap_ST.xy + _IceBumpMap_ST.zw);
                float3 normalTS = UnpackNormalScale(iceNormalMap, _IceBumpScale);
                float3 N = TransformTangentToWorld(normalTS, TBN, true);
                
                half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv * _BaseMap_ST.xy + _BaseMap_ST.zw);
                half3 baseColor = baseMap.rgb * _BaseColor.rgb;
                half alpha = baseMap.a * _BaseColor.a;

                float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);
                
                float3 viewVS = TransformWorldToViewDir(N, true);
                float2 uvMatcap = viewVS.xy * 0.5 + 0.5;
                half4 refMatcapMap = SAMPLE_TEXTURE2D(_IceReflectMatcap, sampler_IceReflectMatcap, uvMatcap);
                float NoV = abs(dot(N,V));
                float fresnel = saturate(_FresnelBias + 1 - pow(NoV, _FresnelPower));
                half3 reflectionColor = _IceReflectColor.rgb * refMatcapMap.rgb;
                
                float4 color;
                color.rgb = lerp(baseColor, reflectionColor, fresnel);
                color.a = 1;
                
                return color;;
            }
            ENDHLSL
        }
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
}

Shader "Omnee/Unlit/Sand Dissolve"
{
    Properties
    {
        [MainTexture] _BaseMap("Texture", 2D) = "gray" {}
        
        [Header(Dissolve)]
        [Toggle] _AutoPlay("Auto Play?", float) = 0
        _DissolveAmount("溶解控制", Range(0, 1)) = 0
        _DissolveNoiseMap("溶解噪声图", 2D) = "white" {}
        _DissolveNoiseStrength("溶解噪声强度", float) = 0.2
        
        [Header(Sand)]
        _Height("模型高度", float) = 1
        _GroundPosY("地面位置", float) = 0.01
        
        [HDR] _SandColor("沙子颜色", Color) = (0,0,0,0)
        _SandNoiseMap("沙子噪声图", 2D) = "white" {}
        _SandFallSpeed("沙子下落速度", float) = 2
        _SandSpreadSpeed("沙子下落时向四周扩散的速度", float) = 0.2
        _SandNoiseStrength("沙子噪声强度", float) = 0.6
        _SandClipOffset("沙子裁剪偏移值", float) = 0

        [Header(Hit Highlight)]
        _HitHighlight("命中高亮强度", Range(0, 1)) = 0
        [HDR] _HitHighlightColor("命中高亮颜色", Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
            "Queue" = "AlphaTest"
        }
        LOD 100
        Cull Off

        Pass
        {
            HLSLPROGRAM
            #pragma vertex UnlitPassVertex
            #pragma fragment UnlitPassFragment
            #pragma multi_compile  _ _AUTOPLAY_ON
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);
            TEXTURE2D(_DissolveNoiseMap);
            SAMPLER(sampler_DissolveNoiseMap);
            TEXTURE2D(_SandNoiseMap);
            SAMPLER(sampler_SandNoiseMap);

            CBUFFER_START(UnityPerMaterial)
            float _DissolveAmount;
            float4 _DissolveNoiseMap_ST;
            float _DissolveNoiseStrength;

            float _Height;
            float _GroundPosY;
            
            half4 _SandColor;
            float4 _SandNoiseMap_ST;
            float _SandNoiseStrength;
            float _SandFallSpeed;
            float _SandSpreadSpeed;
            float _SandClipOffset;

            half _HitHighlight;
            half4 _HitHighlightColor;
            CBUFFER_END

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
                float3 normalOS : NORMAL;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;
                float3 positionWS : TEXCOORD1;
                float3 centerPosWS : TEXCOORD2;
                float3 normalWS : TEXCOORD3;
                float3 sh : TEXCOORD4;

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            float GetGradient(float centerPosY, float posY)
            {
                float changeAmount;
                #if _AUTOPLAY_ON
                changeAmount  = frac(_Time.x * 12);
                #else
                changeAmount = _DissolveAmount;
                #endif
                
                float positionRate = (centerPosY - posY) / _Height;
                float gradient = positionRate - changeAmount * 2 + 1.5;
                return gradient;
            }
            
            Varyings UnlitPassVertex(Attributes input)
            {
                Varyings output = (Varyings)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);

                float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
                float3 centerPosWS = TransformObjectToWorld(float3(0,0,0));
                float gradient = GetGradient(centerPosWS.y, positionWS.y); 
                float3 newPositionWS = positionWS;
                float posOffsetValue = max(0.5 - gradient, 0);
                newPositionWS.y = max(_GroundPosY, newPositionWS.y - posOffsetValue * _SandFallSpeed); //向下落
                
                float3 fromCenterDir = positionWS - centerPosWS;
                fromCenterDir.y = 0;
                fromCenterDir = normalize(fromCenterDir);
                newPositionWS += posOffsetValue * fromCenterDir * _SandSpreadSpeed; //向四周扩散
                
                output.positionCS = TransformWorldToHClip(newPositionWS);
                output.uv = input.uv;
                output.positionWS = positionWS;
                output.centerPosWS = centerPosWS;
                output.normalWS = TransformObjectToWorldNormal(input.normalOS);
                output.sh = SampleSH(output.normalWS);

                return output;
            }
            
            half4 UnlitPassFragment(Varyings input) : SV_Target0
            {
                UNITY_SETUP_INSTANCE_ID(input);

                float3 N = normalize(input.normalWS);

                half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv);
                half3 albedo = baseMap.rgb;
                
                // lighting
                Light mainLight = GetMainLight();
                float3 L = mainLight.direction;
                float NoL = max(dot(N,L), 0);
                half3 diffuse = albedo * NoL * mainLight.color;
                half3 envDiffuse = input.sh * albedo;
                half3 lighting = diffuse + envDiffuse;

                // gradient
                float gradient = GetGradient(input.centerPosWS.y, input.positionWS.y);
                half4 dissolveNoiseMap = SAMPLE_TEXTURE2D(_DissolveNoiseMap, sampler_DissolveNoiseMap, input.uv * _DissolveNoiseMap_ST.xy + _DissolveNoiseMap_ST.zw * _Time.x);
                gradient = gradient - _DissolveNoiseStrength * dissolveNoiseMap.r;
                
                // clip
                half4 sandNoiseMap = SAMPLE_TEXTURE2D(_SandNoiseMap, sampler_SandNoiseMap, input.uv * _SandNoiseMap_ST.xy + _SandNoiseMap_ST.zw * _Time.x);
                float clipValue = step(0.5, gradient + _SandClipOffset + _SandNoiseStrength * sandNoiseMap.r);
                clip(clipValue - 0.5);

                // final color
                float sandWeight = step(gradient, 0.5);
                half4 color;
                color.rgb = lerp(lighting, _SandColor.rgb, sandWeight);
                color.a = 1;

                color.rgb = lerp(color.rgb, _HitHighlightColor.rgb, _HitHighlight);
                
                return color;
            }
            ENDHLSL
        }
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
}

Shader "Omnee/Common/StencilValueWriter"
{
    Properties
    {
        _Stencil("Stencil ID", float) = 0
    }

    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
        }
        LOD 0

        Pass
        {
            ColorMask 0
            ZWrite Off
            Cull Off
            
            Stencil
            {
                Ref [_Stencil]
                Comp Always
                Pass Replace
            }
            
            HLSLPROGRAM
            // -------------------------------------
            // Material Keywords
            //#pragma multi_compile_fragment _CLIPBYWORLDPOS_ON
            
            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma instancing_options renderinglayer
            #pragma multi_compile _ DOTS_INSTANCING_ON

            #pragma vertex Vertex
            #pragma fragment Fragment

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct Attributes
            {
                float4 positionOS : POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };


            Varyings Vertex(Attributes input)
            {
                Varyings output = (Varyings)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);

                output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
                return output;
            }

            half4 Fragment(Varyings input) : SV_Target
            {
                UNITY_SETUP_INSTANCE_ID(input);
                return 0;
            }
            
            ENDHLSL
        }

    }
    
    FallBack "Hidden/Universal Render Pipeline/FallbackError"
}

Shader "Omnee/Role/Fur Lit"
{
    Properties
    {
        [Main(Base, _, off, off)] _Base ("基础贴图", float) = 0
        [Sub(Base)] [NoScaleOffset] _BaseMap("Albedo", 2D) = "white" {}
        [Sub(Base)] _BaseColor("Color", Color) = (1,1,1,1)
        [Sub(Base)] [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
        [Sub(Base)] _NormalScale("Normal Scale", float) = 1
        [Sub(Base)] [NoScaleOffset] _MaskMap("Mask(rgb:mro,a:有毛区域遮罩)", 2D) = "white" {}
        
        [Title(Base, pbr params)]
        [Sub(Base)] _MetallicOffset("金属度偏移", Range(-1, 1)) = 0
        [Sub(Base)] _RoughnessOffset("粗糙度偏移", Range(-1, 1)) = 0
        [Sub(Base)] _OcclusionOffset("环境光遮蔽偏移", Range(-1, 1)) = 0
        
        [Main(Fur, _, off, off)] _Fur ("", float) = 0
        //[Sub(Fur)] _FurColor("毛颜色", Color) = (1,1,1,1)
        [Sub(Fur)] _FurNoiseMap("毛噪声图", 2D) = "black" {}
        [Sub(Fur)] _FurDir("毛方向", Vector) = (0,0,0,0)
        [Sub(Fur)] _FurLayerPower("毛形状 %即为fur layer power,为1时为线性变化%", Range(0.1, 2)) = 2
        [Sub(Fur)] _FurLen("毛长度(厘米)", Range(0.1, 20)) = 1
        [Sub(Fur)] _FurEdgeFade("密度", Range(0, 3)) = 1
        //[Sub(Fur)] _FurRootOcclusion("毛根部ao", Range(0, 1)) = 0.5
        //[Sub(Fur)] _FurRoughness("毛粗糙度", Range(0, 1)) = 0.5
        
        [Main(RimColor, _USERIMCOLOR_ON, off)] _RimColorGroup ("毛边缘光", float) = 0
        [Sub(RimColor)] [HDR] _RimColor("Rim Color", Color) = (0.1,0.1,0.1,1)
        [Sub(RimColor)] _RimPower("Rim Power", float) = 5
        [Sub(RimColor)] _RimScale("Rim Scale", float) = 1
        [Sub(RimColor)] _RimBias("Rim Bias", float) = 0
    }

    SubShader
    {
        // Universal Pipeline tag is required. If Universal render pipeline is not set in the graphics settings
        // this Subshader will fail. One can add a subshader below or fallback to Standard built-in to make this
        // material work with both Universal Render Pipeline and Builtin Unity Pipeline
        Tags
        {
            "RenderType" = "Transparent"
            "RenderPipeline" = "UniversalPipeline"
            "UniversalMaterialType" = "Lit"
            "IgnoreProjector" = "True"
            "Queue" = "Transparent"
        }
        LOD 100

        // ------------------------------------------------------------------
        //  Forward pass. Shades all light in a single pass. GI + emission + Fog
        Pass
        {
            // Lightmode matches the ShaderPassName set in UniversalRenderPipeline.cs. SRPDefaultUnlit and passes with
            // no LightMode tag are also rendered by Universal Render Pipeline
            Name "ForwardLit"
            Tags
            {
                "LightMode" = "UniversalForward"
            }

            // -------------------------------------
            // Render State Commands
            Blend SrcAlpha OneMinusSrcAlpha, One One
            ZWrite On

            HLSLPROGRAM
            #pragma target 2.0

            // -------------------------------------
            // Shader Stages
            #pragma vertex LitPassVertex
            #pragma fragment LitPassFragment

            // -------------------------------------
            // Material Keywords
            /*
            #pragma shader_feature_local _NORMALMAP
            #pragma shader_feature_local _PARALLAXMAP
            #pragma shader_feature_local _RECEIVE_SHADOWS_OFF
            #pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
            #pragma shader_feature_local_fragment _SURFACE_TYPE_TRANSPARENT
            #pragma shader_feature_local_fragment _ALPHATEST_ON
            #pragma shader_feature_local_fragment _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
            #pragma shader_feature_local_fragment _EMISSION
            #pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
            #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
            #pragma shader_feature_local_fragment _OCCLUSIONMAP
            #pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_OFF
            #pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OFF
            #pragma shader_feature_local_fragment _SPECULAR_SETUP
            */
            #pragma shader_feature_local_fragment _USERIMCOLOR_ON

            // -------------------------------------
            // Universal Pipeline keywords
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
            #pragma multi_compile _ EVALUATE_SH_MIXED EVALUATE_SH_VERTEX
            #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
            #pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
            #pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
            #pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
            #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
            #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
            #pragma multi_compile_fragment _ _LIGHT_COOKIES
            #pragma multi_compile _ _LIGHT_LAYERS
            #pragma multi_compile _ _FORWARD_PLUS
            #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"


            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            #pragma multi_compile _ SHADOWS_SHADOWMASK
            #pragma multi_compile _ DIRLIGHTMAP_COMBINED
            #pragma multi_compile _ LIGHTMAP_ON
            #pragma multi_compile _ DYNAMICLIGHTMAP_ON
            #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
            #pragma multi_compile_fog
            #pragma multi_compile_fragment _ DEBUG_DISPLAY

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma instancing_options renderinglayer
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            #include "FurLitInput.hlsl"
            #include "FurLitForwardPass.hlsl"
            ENDHLSL
        }

        Pass
        {
            Name "ShadowCaster"
            Tags
            {
                "LightMode" = "ShadowCaster"
            }

            // -------------------------------------
            // Render State Commands
            ZWrite On
            ZTest LEqual
            ColorMask 0
            //Cull[_Cull]

            HLSLPROGRAM
            #pragma target 2.0

            // -------------------------------------
            // Shader Stages
            #pragma vertex ShadowPassVertex
            #pragma fragment ShadowPassFragment

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_local _ALPHATEST_ON
            #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            // -------------------------------------
            // Universal Pipeline keywords

            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE

            // This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
            #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW

            // -------------------------------------
            // Includes
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
            ENDHLSL
        }

        Pass
        {
            Name "DepthOnly"
            Tags
            {
                "LightMode" = "DepthOnly"
            }

            // -------------------------------------
            // Render State Commands
            ZWrite On
            ColorMask R
            //Cull[_Cull]

            HLSLPROGRAM
            #pragma target 2.0

            // -------------------------------------
            // Shader Stages
            #pragma vertex DepthOnlyVertex
            #pragma fragment DepthOnlyFragment

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_local _ALPHATEST_ON
            #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            // -------------------------------------
            // Includes
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
            ENDHLSL
        }

        // This pass is used when drawing to a _CameraNormalsTexture texture
        Pass
        {
            Name "DepthNormals"
            Tags
            {
                "LightMode" = "DepthNormals"
            }

            // -------------------------------------
            // Render State Commands
            ZWrite On
            //Cull[_Cull]

            HLSLPROGRAM
            #pragma target 2.0

            // -------------------------------------
            // Shader Stages
            #pragma vertex DepthNormalsVertex
            #pragma fragment DepthNormalsFragment

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_local _NORMALMAP
            #pragma shader_feature_local _PARALLAXMAP
            #pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
            #pragma shader_feature_local _ALPHATEST_ON
            #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE

            // -------------------------------------
            // Universal Pipeline keywords
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            // -------------------------------------
            // Includes
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitDepthNormalsPass.hlsl"
            ENDHLSL
        }

    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
    //CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.LitShader"
    CustomEditor "LWGUI.LWGUI"
}

FurLitForwardPass.hlsl
#ifndef UNIVERSAL_FORWARD_LIT_PASS_INCLUDED
#define UNIVERSAL_FORWARD_LIT_PASS_INCLUDED

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
//#include "SweaterLighting.hlsl"
#if defined(LOD_FADE_CROSSFADE)
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LODCrossFade.hlsl"
#endif

struct Attributes
{
    float4 positionOS : POSITION;
    float3 normalOS : NORMAL;
    float4 tangentOS : TANGENT;
    float2 texcoord : TEXCOORD0;
    float4 color : COLOR;
    UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct Varyings
{
    float4 positionCS : SV_POSITION;
    float2 uv : TEXCOORD0;
    float3 positionWS : TEXCOORD1;
    float3 normalWS : TEXCOORD2;
    half4 tangentWS : TEXCOORD3; // xyz: tangent, w: sign
    float4 bitangentWS : TEXCOORD4; // xyz: bitangent, w: fogFactor
    float4 color : TEXCOORD5;

    UNITY_VERTEX_INPUT_INSTANCE_ID
};

InputData InitializeInputData(Varyings input, half3 normalTS)
{
    InputData inputData = (InputData)0;

    inputData.positionWS = input.positionWS;

    half3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS);
    half3x3 tangentToWorld = half3x3(input.tangentWS.xyz, input.bitangentWS.xyz, input.normalWS.xyz);

    inputData.tangentToWorld = tangentToWorld;
    inputData.normalWS = TransformTangentToWorld(normalTS, tangentToWorld);

    inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
    inputData.viewDirectionWS = viewDirWS;

    inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
    inputData.fogCoord = InitializeInputDataFog(float4(input.positionWS, 1.0), input.bitangentWS.w);

    inputData.bakedGI = SampleSH(inputData.normalWS);

    inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
    inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV);

    return inputData;
}

///////////////////////////////////////////////////////////////////////////////
//                  Vertex and Fragment functions                            //
///////////////////////////////////////////////////////////////////////////////

// Used in Standard (Physically Based) shader
Varyings LitPassVertex(Attributes input)
{
    Varyings output = (Varyings)0;

    UNITY_SETUP_INSTANCE_ID(input);
    UNITY_TRANSFER_INSTANCE_ID(input, output);

    // 毛顶点偏移
    float3 positionOS = input.positionOS.xyz;
    positionOS += input.normalOS * _FurLen * input.color.r * 0.01;

    VertexPositionInputs vertexInput = GetVertexPositionInputs(positionOS);

    // normalWS and tangentWS already normalize.
    // this is required to avoid skewing the direction during interpolation
    // also required for per-vertex lighting and SH evaluation
    VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);

    half fogFactor = 0;
    #if !defined(_FOG_FRAGMENT)
    fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
    #endif

    output.uv = input.texcoord;

    // already normalized from normal transform to WS.
    output.normalWS = normalInput.normalWS;
    real sign = input.tangentOS.w * GetOddNegativeScale();
    output.tangentWS = half4(normalInput.tangentWS.xyz, sign);
    output.bitangentWS.xyz = normalInput.bitangentWS;
    output.bitangentWS.w = fogFactor;

    output.positionWS = vertexInput.positionWS;
    output.positionCS = vertexInput.positionCS;

    output.color = input.color;

    return output;
}

half3 CalcRimColor(float3 N, float3 V)
{
    float NoV = saturate(dot(N, V));
    float rim = pow(1-NoV, _RimPower) * _RimScale + _RimBias;
    return _RimColor * rim * _MainLightColor.rgb;
}

// Used in Standard (Physically Based) shader
half4 LitPassFragment(
    Varyings input
    #ifdef _WRITE_RENDERING_LAYERS
    , out float4 outRenderingLayers : SV_Target1
    #endif
) : SV_Target0
{
    UNITY_SETUP_INSTANCE_ID(input);
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

    float furPointMask;
    SurfaceData surfaceData = InitializeStandardLitSurfaceData(input.uv, input.color, furPointMask);

    #ifdef LOD_FADE_CROSSFADE
    LODFadeCrossFade(input.positionCS);
    #endif

    InputData inputData = InitializeInputData(input, surfaceData.normalTS);

    #ifdef _DBUFFER
    ApplyDecalToSurfaceData(input.positionCS, surfaceData, inputData);
    #endif

    half4 color = UniversalFragmentPBR(inputData, surfaceData);

    // 边缘光
    #if _USERIMCOLOR_ON
    half3 rimColor = CalcRimColor(inputData.normalWS, inputData.viewDirectionWS);
    color.rgb += rimColor * furPointMask;
    #endif

    color.rgb = MixFog(color.rgb, inputData.fogCoord);

    #ifdef _WRITE_RENDERING_LAYERS
    uint renderingLayers = GetMeshRenderingLayer();
    outRenderingLayers = float4(EncodeMeshRenderingLayer(renderingLayers), 0, 0, 0);
    #endif

    return color;
}

#endif


FurLitInput.hlsl
#ifndef UNIVERSAL_LIT_INPUT_INCLUDED
#define UNIVERSAL_LIT_INPUT_INCLUDED

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
//#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ParallaxMapping.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DBuffer.hlsl"

// NOTE: Do not ifdef the properties here as SRP batcher can not handle different layouts.
CBUFFER_START(UnityPerMaterial)
    half4 _BaseColor;
    float _NormalScale;

    float _MetallicOffset;
    float _RoughnessOffset;
    float _OcclusionOffset;

    half _FurLen, _FurLayerPower, _FurEdgeFade;
    half4 _FurNoiseMap_ST, _FurDir;

    half4 _RimColor;
    float _RimPower, _RimScale, _RimBias;
CBUFFER_END

TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
TEXTURE2D(_BumpMap);
SAMPLER(sampler_BumpMap);
TEXTURE2D(_MaskMap);
SAMPLER(sampler_MaskMap);
TEXTURE2D(_FurNoiseMap);
SAMPLER(sampler_FurNoiseMap);

// 参考:https://www.xbdev.net/directx3dx/specialX/Fur/index.php
SurfaceData InitializeStandardLitSurfaceData(float2 uv, half4 color, inout float furPointMask)
{
    SurfaceData outSurfaceData = (SurfaceData)0;

    half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv);
    half4 bumpMap = SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, uv);
    half4 maskMap = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, uv);

    float3 normalTS = UnpackNormalScale(bumpMap, _NormalScale);

    // fur
    float furLayer = color.r;
    float furLayerPow2 = pow(furLayer, _FurLayerPower);
    float2 uvFurNoise = (uv + _FurDir.xy * furLayerPow2) * _FurNoiseMap_ST.xy;
    float4 furNoiseMap = SAMPLE_TEXTURE2D(_FurNoiseMap, sampler_FurNoiseMap, uvFurNoise);
    float furPointAlpha = max(furNoiseMap.r * 2 - furLayerPow2 * _FurEdgeFade, 0);
    float isFurPoint = step(0.01, furLayer); //是否为毛的尖部,即不为第一层,第一层是模型

    //half3 albedo = lerp(baseMap.rgb * _BaseColor.rgb, _FurColor.rgb, isFurPoint);
    half3 albedo = baseMap.rgb * _BaseColor.rgb;
    float furMask = maskMap.a; //是否在毛的区域,根据遮罩图,有些区域无毛
    
    furPointMask = isFurPoint * furMask;

    // 有毛区域参数
    //float furAreaOcclusion = lerp(_FurRootOcclusion, 1, furLayer);
    float furAreaAlpha = lerp(1, furPointAlpha, isFurPoint);
    //float furAreaRoughness = lerp(maskMap.g, _FurRoughness, isFurPoint);
    //float furAreaMetallic = lerp(maskMap.r, 0, isFurPoint);

    // 无毛区域参数
    //float noFurAreaOcclusion = maskMap.b;
    float noFurAreaAlpha = lerp(1, 0, isFurPoint);
    //float noFurAreaRoughness = maskMap.g;
    //float noFurAreaMetallic = maskMap.r;

    // 最终参数
    float occlusion = saturate(maskMap.b + _OcclusionOffset); //lerp(noFurAreaOcclusion, furAreaOcclusion, furMask);
    float alpha = lerp(noFurAreaAlpha, furAreaAlpha, furMask);
    float roughness = saturate(maskMap.g + _RoughnessOffset); //lerp(noFurAreaRoughness, furAreaRoughness, furMask);
    float metallic = saturate(maskMap.r + _MetallicOffset); //lerp(noFurAreaMetallic, furAreaMetallic, furMask);

    outSurfaceData.albedo = albedo;
    outSurfaceData.alpha = alpha;
    outSurfaceData.metallic = metallic;
    outSurfaceData.specular = half3(0.0, 0.0, 0.0);
    outSurfaceData.smoothness = 1 - roughness;
    outSurfaceData.normalTS = normalTS;
    outSurfaceData.occlusion = occlusion;
    outSurfaceData.emission = 0;

    outSurfaceData.clearCoatMask = half(0.0);
    outSurfaceData.clearCoatSmoothness = half(0.0);

    return outSurfaceData;
}

#endif // UNIVERSAL_INPUT_SURFACE_PBR_INCLUDED


HairLighting.hlsl
#ifndef UNIVERSAL_LIGHTING_INCLUDED
#define UNIVERSAL_LIGHTING_INCLUDED

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/BRDF.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/Debugging3D.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/GlobalIllumination.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/AmbientOcclusion.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DBuffer.hlsl"


struct HairBRDFData
{
    float3 HairDirectionWS;
    half3 Specular1Tint;
    float Specular1Exponent;
    float Specular1AnisoShift;
    half3 Specular2Tint;
    float Specular2Exponent;
    float Specular2AnisoShift;
};

real RoughnessToBlinnPhongSpecularExponent(real roughness)
{
    return clamp(2 * rcp(roughness * roughness) - 2, FLT_EPS, rcp(FLT_EPS));
}

HairBRDFData InitializeHairBRDFData(float2 uv, float3 hairDirWS, float aniso, float kajiyaWeight)
{
    HairBRDFData hairBRDF;
    hairBRDF.HairDirectionWS = hairDirWS;
    
    hairBRDF.Specular1Tint = _Specular1Tint * kajiyaWeight;
    hairBRDF.Specular2Tint = _Specular2Tint * kajiyaWeight;
    
    hairBRDF.Specular1Exponent = RoughnessToBlinnPhongSpecularExponent(_Specular1Roughness);
    hairBRDF.Specular2Exponent = RoughnessToBlinnPhongSpecularExponent(_Specular2Roughness);
    
    hairBRDF.Specular1AnisoShift = _Specular1Shift + aniso;
    hairBRDF.Specular2AnisoShift = _Specular2Shift + aniso;
    
    return hairBRDF;
}

///////////////////////////////////////////////////////////////////////////////
//                      Lighting Functions                                   //
///////////////////////////////////////////////////////////////////////////////
half3 LightingLambert(half3 lightColor, half3 lightDir, half3 normal)
{
    half NdotL = saturate(dot(normal, lightDir));
    return lightColor * NdotL;
}

half3 LightingSpecular(half3 lightColor, half3 lightDir, half3 normal, half3 viewDir, half4 specular, half smoothness)
{
    float3 halfVec = SafeNormalize(float3(lightDir) + float3(viewDir));
    half NdotH = half(saturate(dot(normal, halfVec)));
    half modifier = pow(NdotH, smoothness);
    // NOTE: In order to fix internal compiler error on mobile platforms, this needs to be float3
    float3 specularReflection = specular.rgb * modifier;
    return lightColor * specularReflection;
}

half3 LightingPhysicallyBased(BRDFData brdfData, Light light, half3 normalWS, half3 viewDirectionWS, HairBRDFData hairBRDF)
{
    half3 lightColor = light.color;
    half3 lightDirectionWS = light.direction;
    half lightAttenuation = light.distanceAttenuation * light.shadowAttenuation;
    
    half NdotL = saturate(dot(normalWS, lightDirectionWS));
    half3 radiance = lightColor * (lightAttenuation * NdotL);

    half3 brdf = brdfData.diffuse;
    //brdf += brdfData.specular * DirectBRDFSpecular(brdfData, normalWS, lightDirectionWS, viewDirectionWS);
    
    // kaijiya-kay model
    float3 H = normalize(lightDirectionWS + viewDirectionWS);
    half3 t1 = ShiftTangent(hairBRDF.HairDirectionWS, normalWS, hairBRDF.Specular1AnisoShift);
    brdf += hairBRDF.Specular1Tint * D_KajiyaKay(t1, H, hairBRDF.Specular1Exponent);

    #if _USESECONDSPECULAR_ON
    half3 t2 = ShiftTangent(hairBRDF.HairDirectionWS, normalWS, hairBRDF.Specular2AnisoShift);
    brdf += hairBRDF.Specular2Tint * D_KajiyaKay(t2, H, hairBRDF.Specular2Exponent);
    #endif
    
    return brdf * radiance;
}

half3 VertexLighting(float3 positionWS, half3 normalWS)
{
    half3 vertexLightColor = half3(0.0, 0.0, 0.0);

#ifdef _ADDITIONAL_LIGHTS_VERTEX
    uint lightsCount = GetAdditionalLightsCount();
    uint meshRenderingLayers = GetMeshRenderingLayer();

    LIGHT_LOOP_BEGIN(lightsCount)
        Light light = GetAdditionalLight(lightIndex, positionWS);

#ifdef _LIGHT_LAYERS
    if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
#endif
    {
        half3 lightColor = light.color * light.distanceAttenuation;
        vertexLightColor += LightingLambert(lightColor, light.direction, normalWS);
    }

    LIGHT_LOOP_END
#endif

    return vertexLightColor;
}

struct LightingData
{
    half3 giColor;
    half3 mainLightColor;
    half3 additionalLightsColor;
    half3 vertexLightingColor;
    half3 emissionColor;
};

half3 CalculateLightingColor(LightingData lightingData, half3 albedo)
{
    half3 lightingColor = 0;

    if (IsOnlyAOLightingFeatureEnabled())
    {
        return lightingData.giColor; // Contains white + AO
    }

    if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_GLOBAL_ILLUMINATION))
    {
        lightingColor += lightingData.giColor;
    }

    if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_MAIN_LIGHT))
    {
        lightingColor += lightingData.mainLightColor;
    }

    if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_ADDITIONAL_LIGHTS))
    {
        lightingColor += lightingData.additionalLightsColor;
    }

    if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_VERTEX_LIGHTING))
    {
        lightingColor += lightingData.vertexLightingColor;
    }

    lightingColor *= albedo;

    if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_EMISSION))
    {
        lightingColor += lightingData.emissionColor;
    }

    return lightingColor;
}

half4 CalculateFinalColor(LightingData lightingData, half alpha)
{
    half3 finalColor = CalculateLightingColor(lightingData, 1);

    return half4(finalColor, alpha);
}

half4 CalculateFinalColor(LightingData lightingData, half3 albedo, half alpha, float fogCoord)
{
    #if defined(_FOG_FRAGMENT)
        #if (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))
        float viewZ = -fogCoord;
        float nearToFarZ = max(viewZ - _ProjectionParams.y, 0);
        half fogFactor = ComputeFogFactorZ0ToFar(nearToFarZ);
    #else
        half fogFactor = 0;
        #endif
    #else
    half fogFactor = fogCoord;
    #endif
    half3 lightingColor = CalculateLightingColor(lightingData, albedo);
    half3 finalColor = MixFog(lightingColor, fogFactor);

    return half4(finalColor, alpha);
}

LightingData CreateLightingData(InputData inputData, SurfaceData surfaceData)
{
    LightingData lightingData;

    lightingData.giColor = inputData.bakedGI;
    lightingData.emissionColor = surfaceData.emission;
    lightingData.vertexLightingColor = 0;
    lightingData.mainLightColor = 0;
    lightingData.additionalLightsColor = 0;

    return lightingData;
}

half3 CalculateBlinnPhong(Light light, InputData inputData, SurfaceData surfaceData)
{
    half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
    half3 lightDiffuseColor = LightingLambert(attenuatedLightColor, light.direction, inputData.normalWS);

    half3 lightSpecularColor = half3(0,0,0);
    #if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
    half smoothness = exp2(10 * surfaceData.smoothness + 1);

    lightSpecularColor += LightingSpecular(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, half4(surfaceData.specular, 1), smoothness);
    #endif

#if _ALPHAPREMULTIPLY_ON
    return lightDiffuseColor * surfaceData.albedo * surfaceData.alpha + lightSpecularColor;
#else
    return lightDiffuseColor * surfaceData.albedo + lightSpecularColor;
#endif
}

///////////////////////////////////////////////////////////////////////////////
//                      Fragment Functions                                   //
//       Used by ShaderGraph and others builtin renderers                    //
///////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// PBR lighting...
////////////////////////////////////////////////////////////////////////////////
half4 UniversalFragmentPBR(InputData inputData, SurfaceData surfaceData, HairBRDFData hairBRDF)
{
    BRDFData brdfData;

    // NOTE: can modify "surfaceData"...
    InitializeBRDFData(surfaceData, brdfData);

    // Clear-coat calculation...
    BRDFData brdfDataClearCoat = CreateClearCoatBRDFData(surfaceData, brdfData);
    half4 shadowMask = CalculateShadowMask(inputData);
    AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData, surfaceData);
    uint meshRenderingLayers = GetMeshRenderingLayer();
    Light mainLight = GetMainLight(inputData, shadowMask, aoFactor);

    // NOTE: We don't apply AO to the GI here because it's done in the lighting calculation below...
    MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI);

    LightingData lightingData = CreateLightingData(inputData, surfaceData);

    lightingData.giColor = GlobalIllumination(brdfData, brdfDataClearCoat, surfaceData.clearCoatMask,
                                              inputData.bakedGI, aoFactor.indirectAmbientOcclusion, inputData.positionWS,
                                              inputData.normalWS, inputData.viewDirectionWS, inputData.normalizedScreenSpaceUV);
#ifdef _LIGHT_LAYERS
    if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers))
#endif
    {
        lightingData.mainLightColor = LightingPhysicallyBased(brdfData, mainLight, inputData.normalWS, inputData.viewDirectionWS, hairBRDF);
    }
    
    #if defined(_ADDITIONAL_LIGHTS)
    uint pixelLightCount = GetAdditionalLightsCount();

    LIGHT_LOOP_BEGIN(pixelLightCount)
        Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);

#ifdef _LIGHT_LAYERS
        if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
#endif
        {
            lightingData.additionalLightsColor += LightingPhysicallyBased(brdfData, light, inputData.normalWS, inputData.viewDirectionWS, hairBRDF);
        }
    LIGHT_LOOP_END
    #endif

#if REAL_IS_HALF
    // Clamp any half.inf+ to HALF_MAX
    return min(CalculateFinalColor(lightingData, surfaceData.alpha), HALF_MAX);
#else
    return CalculateFinalColor(lightingData, surfaceData.alpha);
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// Phong lighting...
////////////////////////////////////////////////////////////////////////////////
half4 UniversalFragmentBlinnPhong(InputData inputData, SurfaceData surfaceData)
{
    #if defined(DEBUG_DISPLAY)
    half4 debugColor;

    if (CanDebugOverrideOutputColor(inputData, surfaceData, debugColor))
    {
        return debugColor;
    }
    #endif

    uint meshRenderingLayers = GetMeshRenderingLayer();
    half4 shadowMask = CalculateShadowMask(inputData);
    AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData, surfaceData);
    Light mainLight = GetMainLight(inputData, shadowMask, aoFactor);

    MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, aoFactor);

    inputData.bakedGI *= surfaceData.albedo;

    LightingData lightingData = CreateLightingData(inputData, surfaceData);
#ifdef _LIGHT_LAYERS
    if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers))
#endif
    {
        lightingData.mainLightColor += CalculateBlinnPhong(mainLight, inputData, surfaceData);
    }

    #if defined(_ADDITIONAL_LIGHTS)
    uint pixelLightCount = GetAdditionalLightsCount();

    #if USE_FORWARD_PLUS
    for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++)
    {
        FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK

        Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
#ifdef _LIGHT_LAYERS
        if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
#endif
        {
            lightingData.additionalLightsColor += CalculateBlinnPhong(light, inputData, surfaceData);
        }
    }
    #endif

    LIGHT_LOOP_BEGIN(pixelLightCount)
        Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
#ifdef _LIGHT_LAYERS
        if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
#endif
        {
            lightingData.additionalLightsColor += CalculateBlinnPhong(light, inputData, surfaceData);
        }
    LIGHT_LOOP_END
    #endif

    #if defined(_ADDITIONAL_LIGHTS_VERTEX)
    lightingData.vertexLightingColor += inputData.vertexLighting * surfaceData.albedo;
    #endif

    return CalculateFinalColor(lightingData, surfaceData.alpha);
}

// Deprecated: Use the version which takes "SurfaceData" instead of passing all of these arguments...
half4 UniversalFragmentBlinnPhong(InputData inputData, half3 diffuse, half4 specularGloss, half smoothness, half3 emission, half alpha, half3 normalTS)
{
    SurfaceData surfaceData;

    surfaceData.albedo = diffuse;
    surfaceData.alpha = alpha;
    surfaceData.emission = emission;
    surfaceData.metallic = 0;
    surfaceData.occlusion = 1;
    surfaceData.smoothness = smoothness;
    surfaceData.specular = specularGloss.rgb;
    surfaceData.clearCoatMask = 0;
    surfaceData.clearCoatSmoothness = 1;
    surfaceData.normalTS = normalTS;

    return UniversalFragmentBlinnPhong(inputData, surfaceData);
}

////////////////////////////////////////////////////////////////////////////////
/// Unlit
////////////////////////////////////////////////////////////////////////////////
half4 UniversalFragmentBakedLit(InputData inputData, SurfaceData surfaceData)
{
    #if defined(DEBUG_DISPLAY)
    half4 debugColor;

    if (CanDebugOverrideOutputColor(inputData, surfaceData, debugColor))
    {
        return debugColor;
    }
    #endif

    AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData, surfaceData);
    LightingData lightingData = CreateLightingData(inputData, surfaceData);

    if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_AMBIENT_OCCLUSION))
    {
        lightingData.giColor *= aoFactor.indirectAmbientOcclusion;
    }

    return CalculateFinalColor(lightingData, surfaceData.albedo, surfaceData.alpha, inputData.fogCoord);
}

// Deprecated: Use the version which takes "SurfaceData" instead of passing all of these arguments...
half4 UniversalFragmentBakedLit(InputData inputData, half3 color, half alpha, half3 normalTS)
{
    SurfaceData surfaceData;

    surfaceData.albedo = color;
    surfaceData.alpha = alpha;
    surfaceData.emission = half3(0, 0, 0);
    surfaceData.metallic = 0;
    surfaceData.occlusion = 1;
    surfaceData.smoothness = 1;
    surfaceData.specular = half3(0, 0, 0);
    surfaceData.clearCoatMask = 0;
    surfaceData.clearCoatSmoothness = 1;
    surfaceData.normalTS = normalTS;

    return UniversalFragmentBakedLit(inputData, surfaceData);
}

#endif


Shader "Omnee/Role/Hair Lit"
{
    Properties
    {
        // base
        [Main(Base, _, off, off)] _BaseGroup ("基础设置", float) = 0

        [Sub(Base)] [NoScaleOffset] _BaseMap("Albedo Map", 2D) = "white" {}
        [Sub(Base)] _BaseColor("Color", Color) = (1,1,1,1)

        [Sub(Base)] [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
        [Sub(Base)] _BumpScale("Normal Scale", Float) = 1.0

        [Sub(Base)] [NoScaleOffset] _MaskMap("MaskMap(R:Aniso, G:roughness, B:occulsion)", 2D) = "black" {}

        [Title(Base, pbr params)]
        [Sub(Base)] _RoughnessOffset("粗糙度偏移", Range(-1, 1)) = 0
        [Sub(Base)] _OcclusionOffset("环境光遮蔽偏移", Range(-1, 1)) = 0

        // kajiya
        [Helpbox(Vertex color R channel is kajiya strength)]
        [Main(Kajiya, _, off, off)] _KajiyaGroup ("Kajiya 高光", float) = 0
        [Sub(Kajiya)] _Specular1Roughness("Specular 1 Roughness", Range(0,1)) = 0.5
        [Sub(Kajiya)] _Specular1Tint("Specular 1 Tint", Color) = (0.1,0.1,0.1,0)
        [Sub(Kajiya)] _Specular1Shift("Specular 1 Shift", Range(-2,2)) = 0

        [Title(Kajiya, Specular2)]
        [SubToggle(Kajiya, _USESECONDSPECULAR_ON)] _UseSecondSpecular("Use Second Specular", float) = 0
        [Sub(Kajiya_USESECONDSPECULAR_ON)] _Specular2Roughness("Specular 2 Roughness", Range(0,1)) = 0.5
        [Sub(Kajiya_USESECONDSPECULAR_ON)] _Specular2Tint("Specular 2 Tint", Color) = (0.1,0.1,0.1,0)
        [Sub(Kajiya_USESECONDSPECULAR_ON)] _Specular2Shift("Specular 2 Shift", Range(-2,2)) = 0

        [Main(Preset, _, off, off)] _PresetGroup ("渲染设置", float) = 0
        [Preset(Preset, LWGUI_Preset_BlendMode)] _BlendMode ("Blend Mode", float) = 0
        [SubEnum(Preset, UnityEngine.Rendering.BlendMode)] _SrcBlend ("SrcBlend", Float) = 1
        [SubEnum(Preset, UnityEngine.Rendering.BlendMode)] _DstBlend ("DstBlend", Float) = 0
        [SubEnum(Preset, UnityEngine.Rendering.CullMode)] _Cull ("Cull", Float) = 2
        [SubToggle(Preset)] _ZWrite ("ZWrite ", Float) = 1
    }

    SubShader
    {
        // Universal Pipeline tag is required. If Universal render pipeline is not set in the graphics settings
        // this Subshader will fail. One can add a subshader below or fallback to Standard built-in to make this
        // material work with both Universal Render Pipeline and Builtin Unity Pipeline
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
            "UniversalMaterialType" = "Lit"
            "IgnoreProjector" = "True"
            //"Queue" = "Transparent"
        }
        LOD 300

        // ------------------------------------------------------------------
        //  Forward pass. Shades all light in a single pass. GI + emission + Fog
        Pass
        {
            // Lightmode matches the ShaderPassName set in UniversalRenderPipeline.cs. SRPDefaultUnlit and passes with
            // no LightMode tag are also rendered by Universal Render Pipeline
            Name "ForwardLit"
            Tags
            {
                "LightMode" = "UniversalForward"
            }

            Blend [_SrcBlend] [_DstBlend]
            Cull [_Cull]
            ZWrite [_ZWrite]

            // -------------------------------------
            // Render State Commands
            HLSLPROGRAM
            #pragma target 2.0

            // -------------------------------------
            // Shader Stages
            #pragma vertex LitPassVertex
            #pragma fragment LitPassFragment

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_fragment _USESECONDSPECULAR_ON

            // -------------------------------------
            // Universal Pipeline keywords
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
            #pragma multi_compile _ EVALUATE_SH_MIXED EVALUATE_SH_VERTEX
            #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
            #pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
            #pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
            #pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
            #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
            #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
            #pragma multi_compile_fragment _ _LIGHT_COOKIES
            #pragma multi_compile _ _LIGHT_LAYERS
            #pragma multi_compile _ _FORWARD_PLUS
            #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"


            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            #pragma multi_compile _ SHADOWS_SHADOWMASK
            #pragma multi_compile _ DIRLIGHTMAP_COMBINED
            #pragma multi_compile _ LIGHTMAP_ON
            #pragma multi_compile _ DYNAMICLIGHTMAP_ON
            #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
            #pragma multi_compile_fog
            #pragma multi_compile_fragment _ DEBUG_DISPLAY

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma instancing_options renderinglayer
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            #include "HairLitInput.hlsl"
            #include "HairLitForwardPass.hlsl"
            ENDHLSL
        }

        Pass
        {
            Name "ShadowCaster"
            Tags
            {
                "LightMode" = "ShadowCaster"
            }

            // -------------------------------------
            // Render State Commands
            ZWrite On
            ZTest LEqual
            ColorMask 0
            Cull[_Cull]

            HLSLPROGRAM
            #pragma target 2.0

            // -------------------------------------
            // Shader Stages
            #pragma vertex ShadowPassVertex
            #pragma fragment ShadowPassFragment

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_local _ALPHATEST_ON
            #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            // -------------------------------------
            // Universal Pipeline keywords

            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE

            // This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
            #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW

            // -------------------------------------
            // Includes
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            //#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"

            float3 _LightDirection;
            float3 _LightPosition;

            struct Attributes
            {
                float4 positionOS : POSITION;
                float3 normalOS : NORMAL;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            float4 GetShadowPositionHClip(Attributes input)
            {
                float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
                float3 normalWS = TransformObjectToWorldNormal(input.normalOS);

                #if _CASTING_PUNCTUAL_LIGHT_SHADOW
                float3 lightDirectionWS = normalize(_LightPosition - positionWS);
                #else
                float3 lightDirectionWS = _LightDirection;
                #endif

                float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, lightDirectionWS));

                #if UNITY_REVERSED_Z
                positionCS.z = min(positionCS.z, UNITY_NEAR_CLIP_VALUE);
                #else
                positionCS.z = max(positionCS.z, UNITY_NEAR_CLIP_VALUE);
                #endif

                return positionCS;
            }

            Varyings ShadowPassVertex(Attributes input)
            {
                Varyings output;
                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);

                output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);

                output.positionCS = GetShadowPositionHClip(input);
                return output;
            }

            half4 ShadowPassFragment(Varyings input) : SV_TARGET
            {
                UNITY_SETUP_INSTANCE_ID(input);

                half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv);
                half alpha = baseMap.a * _BaseColor.a;
                clip(alpha - 0.5);
                return 0;
            }
            ENDHLSL
        }
        
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
    //CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.LitShader"
    CustomEditor "LWGUI.LWGUI"
}

Shader "Omnee/Role/Hair Lit (2 Pass)"
{
    Properties
    {
        // base
        [Main(Base, _, off, off)] _BaseGroup ("基础设置", float) = 0

        [Sub(Base)] [NoScaleOffset] _BaseMap("Albedo Map", 2D) = "white" {}
        [Sub(Base)] _BaseColor("Color", Color) = (1,1,1,1)
        [Sub(Base)] _Cutoff("Cutoff", Range(0, 1)) = 0.5

        [Sub(Base)] [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
        [Sub(Base)] _BumpScale("Normal Scale", Float) = 1.0

        [Sub(Base)] [NoScaleOffset] _MaskMap("MaskMap(R:Aniso, G:roughness, B:occulsion)", 2D) = "black" {}

        [Title(Base, pbr params)]
        [Sub(Base)] _RoughnessOffset("粗糙度偏移", Range(-1, 1)) = 0
        [Sub(Base)] _OcclusionOffset("环境光遮蔽偏移", Range(-1, 1)) = 0

        // kajiya
        [Helpbox(Vertex color R channel is kajiya strength)]
        [Main(Kajiya, _, off, off)] _KajiyaGroup ("Kajiya 高光", float) = 0
        [Sub(Kajiya)] _Specular1Roughness("Specular 1 Roughness", Range(0,1)) = 0.5
        [Sub(Kajiya)] _Specular1Tint("Specular 1 Tint", Color) = (0.1,0.1,0.1,0)
        [Sub(Kajiya)] _Specular1Shift("Specular 1 Shift", Range(-2,2)) = 0

        [Title(Kajiya, Specular2)]
        [SubToggle(Kajiya, _USESECONDSPECULAR_ON)] _UseSecondSpecular("Use Second Specular", float) = 0
        [Sub(Kajiya_USESECONDSPECULAR_ON)] _Specular2Roughness("Specular 2 Roughness", Range(0,1)) = 0.5
        [Sub(Kajiya_USESECONDSPECULAR_ON)] _Specular2Tint("Specular 2 Tint", Color) = (0.1,0.1,0.1,0)
        [Sub(Kajiya_USESECONDSPECULAR_ON)] _Specular2Shift("Specular 2 Shift", Range(-2,2)) = 0
    }

    SubShader
    {
        // Universal Pipeline tag is required. If Universal render pipeline is not set in the graphics settings
        // this Subshader will fail. One can add a subshader below or fallback to Standard built-in to make this
        // material work with both Universal Render Pipeline and Builtin Unity Pipeline
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
            "UniversalMaterialType" = "Lit"
            "IgnoreProjector" = "True"
            //"Queue" = "Transparent"
        }
        LOD 300

        // ------------------------------------------------------------------
        //  Forward pass. Shades all light in a single pass. GI + emission + Fog
        Pass
        {
            // Lightmode matches the ShaderPassName set in UniversalRenderPipeline.cs. SRPDefaultUnlit and passes with
            // no LightMode tag are also rendered by Universal Render Pipeline
            Name "ForwardLitTransparent"
            Tags
            {
                "LightMode" = "UniversalForward"
            }

            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off
            ZWrite Off

            // -------------------------------------
            // Render State Commands
            HLSLPROGRAM
            #pragma target 2.0

            // -------------------------------------
            // Shader Stages
            #pragma vertex LitPassVertex
            #pragma fragment LitPassFragmentTransparent

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_fragment _USESECONDSPECULAR_ON

            // -------------------------------------
            // Universal Pipeline keywords
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
            #pragma multi_compile _ EVALUATE_SH_MIXED EVALUATE_SH_VERTEX
            #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
            #pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
            #pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
            #pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
            #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
            #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
            #pragma multi_compile_fragment _ _LIGHT_COOKIES
            #pragma multi_compile _ _LIGHT_LAYERS
            #pragma multi_compile _ _FORWARD_PLUS
            #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"


            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            #pragma multi_compile _ SHADOWS_SHADOWMASK
            #pragma multi_compile _ DIRLIGHTMAP_COMBINED
            #pragma multi_compile _ LIGHTMAP_ON
            #pragma multi_compile _ DYNAMICLIGHTMAP_ON
            #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
            #pragma multi_compile_fog
            #pragma multi_compile_fragment _ DEBUG_DISPLAY

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma instancing_options renderinglayer
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            #include "HairLitInput.hlsl"
            #include "HairLitForwardPass.hlsl"
            ENDHLSL
        }

        Pass
        {
            // Lightmode matches the ShaderPassName set in UniversalRenderPipeline.cs. SRPDefaultUnlit and passes with
            // no LightMode tag are also rendered by Universal Render Pipeline
            Name "ForwardLitOpaque"
            Tags
            {
                "LightMode" = "UniversalForwardOnly"
            }

            Cull Off
            ZWrite Off

            // -------------------------------------
            // Render State Commands
            HLSLPROGRAM
            #pragma target 2.0

            // -------------------------------------
            // Shader Stages
            #pragma vertex LitPassVertex
            #pragma fragment LitPassFragmentOpaque

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_fragment _USESECONDSPECULAR_ON

            // -------------------------------------
            // Universal Pipeline keywords
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
            #pragma multi_compile _ EVALUATE_SH_MIXED EVALUATE_SH_VERTEX
            #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
            #pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
            #pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
            #pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
            #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
            #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
            #pragma multi_compile_fragment _ _LIGHT_COOKIES
            #pragma multi_compile _ _LIGHT_LAYERS
            #pragma multi_compile _ _FORWARD_PLUS
            #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"


            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            #pragma multi_compile _ SHADOWS_SHADOWMASK
            #pragma multi_compile _ DIRLIGHTMAP_COMBINED
            #pragma multi_compile _ LIGHTMAP_ON
            #pragma multi_compile _ DYNAMICLIGHTMAP_ON
            #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
            #pragma multi_compile_fog
            #pragma multi_compile_fragment _ DEBUG_DISPLAY

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma instancing_options renderinglayer
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            #include "HairLitInput.hlsl"
            #include "HairLitForwardPass.hlsl"
            ENDHLSL
        }

        Pass
        {
            Name "ShadowCaster"
            Tags
            {
                "LightMode" = "ShadowCaster"
            }

            // -------------------------------------
            // Render State Commands
            ZWrite On
            ZTest LEqual
            ColorMask 0
            Cull[_Cull]

            HLSLPROGRAM
            #pragma target 2.0

            // -------------------------------------
            // Shader Stages
            #pragma vertex ShadowPassVertex
            #pragma fragment ShadowPassFragment

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_local _ALPHATEST_ON
            #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            // -------------------------------------
            // Universal Pipeline keywords

            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE

            // This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
            #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW

            // -------------------------------------
            // Includes
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            //#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"

            float3 _LightDirection;
            float3 _LightPosition;

            struct Attributes
            {
                float4 positionOS : POSITION;
                float3 normalOS : NORMAL;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            float4 GetShadowPositionHClip(Attributes input)
            {
                float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
                float3 normalWS = TransformObjectToWorldNormal(input.normalOS);

                #if _CASTING_PUNCTUAL_LIGHT_SHADOW
                float3 lightDirectionWS = normalize(_LightPosition - positionWS);
                #else
                float3 lightDirectionWS = _LightDirection;
                #endif

                float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, lightDirectionWS));

                #if UNITY_REVERSED_Z
                positionCS.z = min(positionCS.z, UNITY_NEAR_CLIP_VALUE);
                #else
                positionCS.z = max(positionCS.z, UNITY_NEAR_CLIP_VALUE);
                #endif

                return positionCS;
            }

            Varyings ShadowPassVertex(Attributes input)
            {
                Varyings output;
                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);

                output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);

                output.positionCS = GetShadowPositionHClip(input);
                return output;
            }

            half4 ShadowPassFragment(Varyings input) : SV_TARGET
            {
                UNITY_SETUP_INSTANCE_ID(input);

                half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv);
                half alpha = baseMap.a * _BaseColor.a;
                clip(alpha - 0.5);
                return 0;
            }
            ENDHLSL
        }

    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
    //CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.LitShader"
    CustomEditor "LWGUI.LWGUI"
}


HairLitForwardPass.hlsl
#ifndef UNIVERSAL_FORWARD_LIT_PASS_INCLUDED
#define UNIVERSAL_FORWARD_LIT_PASS_INCLUDED

#include "HairLighting.hlsl"
#if defined(LOD_FADE_CROSSFADE)
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LODCrossFade.hlsl"
#endif

// keep this file in sync with LitGBufferPass.hlsl

struct Attributes
{
    float4 positionOS : POSITION;
    float3 normalOS : NORMAL;
    float4 tangentOS : TANGENT;
    float2 texcoord : TEXCOORD0;
    float4 color : COLOR;
    UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct Varyings
{
    float4 positionCS : SV_POSITION;
    float2 uv : TEXCOORD0;
    float3 positionWS : TEXCOORD1;
    float3 normalWS : TEXCOORD2;
    half4 tangentWS : TEXCOORD3; // xyz: tangent, w: sign
    float4 bitangentWS : TEXCOORD4; // xyz: bitangent, w: Fog Factor
    float4 color : COLOR; 

    UNITY_VERTEX_INPUT_INSTANCE_ID
};

InputData InitializeInputData(Varyings input, half3 normalTS)
{
    InputData inputData = (InputData)0;

    inputData.positionWS = input.positionWS;

    half3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS);

    half3x3 tangentToWorld = half3x3(input.tangentWS.xyz, input.bitangentWS.xyz, input.normalWS.xyz);

    inputData.tangentToWorld = tangentToWorld;
    inputData.normalWS = TransformTangentToWorld(normalTS, tangentToWorld);

    inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
    inputData.viewDirectionWS = viewDirWS;

    inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
    inputData.fogCoord = InitializeInputDataFog(float4(input.positionWS, 1.0), input.bitangentWS.w);

    inputData.bakedGI = SampleSH(inputData.normalWS);//SAMPLE_GI(input.staticLightmapUV, input.vertexSH, inputData.normalWS);

    inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
    inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV);
    
    return inputData;
}

///////////////////////////////////////////////////////////////////////////////
//                  Vertex and Fragment functions                            //
///////////////////////////////////////////////////////////////////////////////

// Used in Standard (Physically Based) shader
Varyings LitPassVertex(Attributes input)
{
    Varyings output = (Varyings)0;

    UNITY_SETUP_INSTANCE_ID(input);
    UNITY_TRANSFER_INSTANCE_ID(input, output);
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);

    VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);

    // normalWS and tangentWS already normalize.
    // this is required to avoid skewing the direction during interpolation
    // also required for per-vertex lighting and SH evaluation
    VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);

    half fogFactor = 0;
    #if !defined(_FOG_FRAGMENT)
    fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
    #endif

    output.uv = input.texcoord;

    // already normalized from normal transform to WS.
    output.normalWS = normalInput.normalWS;

    output.tangentWS.xyz = normalInput.tangentWS;
    output.tangentWS.w = input.tangentOS.w * GetOddNegativeScale();

    output.bitangentWS.xyz = normalInput.bitangentWS;
    output.bitangentWS.w = fogFactor;

    output.positionWS = vertexInput.positionWS;
    output.positionCS = vertexInput.positionCS;
    output.color = input.color;

    return output;
}

half4 CalcHairColor(Varyings input)
{
    UNITY_SETUP_INSTANCE_ID(input);

    float aniso;
    SurfaceData surfaceData = InitializeStandardLitSurfaceData(input.uv, aniso);

    InputData inputData = InitializeInputData(input, surfaceData.normalTS);

    HairBRDFData hairBRDF = InitializeHairBRDFData(input.uv, input.bitangentWS, aniso, input.color.r);

    half4 color = UniversalFragmentPBR(inputData, surfaceData, hairBRDF);
    color.rgb = MixFog(color.rgb, inputData.fogCoord);
    return color;
}

// Used in Standard (Physically Based) shader
half4 LitPassFragment(Varyings input) : SV_Target0
{
    return CalcHairColor(input);
}

half4 LitPassFragmentTransparent(Varyings input) : SV_Target0
{
    half4 color = CalcHairColor(input);
    clip(_Cutoff - color.a);
    return color;
}

half4 LitPassFragmentOpaque(Varyings input) : SV_Target0
{
    half4 color = CalcHairColor(input);
    clip(color.a - _Cutoff);
    return color;
}

#endif
View Code

 

posted @ 2023-07-04 13:38  太乙_真人  阅读(239)  评论(0)    收藏  举报