HDRP環境で使用できるMtoonみたいなshader

HDRP環境で使用できるMtoonみたいなshader
未完成なのでいい案ください

    Shader "Custom/HDRPMToon2024"
    {
        Properties
        {
            // Render Settings
            // Render Settings
            [Header(Rendering)]
            [Enum(Opaque,0,Cutout,1,Transparent,2,TransparentWithZWrite,3)] _RenderMode("Rendering Type", Float) = 0
            [Space]
            [Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull Mode", Float) = 2
            [HideInInspector] _SrcBlend("Source Blend", Float) = 1
            [HideInInspector] _DstBlend("Destination Blend", Float) = 0
            [HideInInspector] _ZWrite("ZWrite", Float) = 1.0
            [HideInInspector] _AlphaSrcBlend("Source Blend Alpha", Float) = 1
            [HideInInspector] _AlphaDstBlend("Destination Blend Alpha", Float) = 0
            [HideInInspector][ToggleUI] _TransparentZWrite("Transparent ZWrite", Float) = 0
            [HideInInspector] _ZTestDepthEqualForOpaque("ZTest Depth Equal For Opaque", Int) = 4
            [HideInInspector][ToggleUI] _TransparentBackfaceEnable("Transparent Backface Enable", Float) = 0
            
            // Main
            [MainTexture] _BaseMap("Lit Color, Alpha", 2D) = "white" {}
            [MainColor] _BaseColor("Lit Color, Alpha", Color) = (1,1,1,1)
            
            // Lighting
            _ShadeColor("Shade Color", Color) = (0.97, 0.81, 0.86, 1)
            [NoScaleOffset] _ShadeMap("Shade Map", 2D) = "white" {}
            _ShadeToony("Shade Toony", Range(0, 1)) = 0.9
            _ShadingShiftFactor("Shading Shift", Range(-1, 1)) = 0
            _ShadingToonyFactor("Shading Toony", Range(0, 1)) = 0.95
            _ShadingGradeRate("Shading Grade Rate", Range(0, 1)) = 1
            _ShadeShift("Shade Shift", Range(-1, 1)) = 0
            
            // Normal
            [Normal] _BumpMap("Normal Map", 2D) = "bump" {}
            _BumpScale("Normal Scale", Float) = 1.0
                    
            // MatCap
            [NoScaleOffset] _MatCapTex("MatCap", 2D) = "black" {}
            [HDR]_MatCapColor("MatCap Color", Color) = (1,1,1,1) // HDRカラーとして定義
            
            // Rim Light
            [HDR]_RimColor("Rim Color", Color) = (1,1,1,1)
            _RimLightingMix("Rim Lighting Mix", Range(0, 1)) = 0.0
            _RimFresnelPower("Rim Fresnel Power", Range(0, 100)) = 5.0
            _RimLift("Rim Lift", Range(0, 1)) = 0.0
            _RimDirectionLightContribution("Rim Direction Light Contribution", Range(0, 1)) = 1.0
            _RimLightMode("Rim Light Mode", Float) = 0
            _RimBlendStart("Rim Blend Start", Range(0, 1)) = 0
            _RimBlendEnd("Rim Blend End", Range(0, 1)) = 1
            
            // Emission
            [HDR]_EmissionColor("Emission Color", Color) = (0,0,0,1)
            [NoScaleOffset]_EmissionMap("Emission Map", 2D) = "white" {}
            
            // Outline
            _OutlineWidth("Outline Width", Range(0, 0.1)) = 0.001
            _OutlineColor("Outline Color", Color) = (0,0,0,1)
            [Enum(None,0,WorldCoordinates,1,ScreenCoordinates,2)] _OutlineWidthMode("Outline Width Mode", Float) = 0
            _OutlineScaledMaxDistance("Outline Scaled Max Distance", Float) = 1
            _OutlineLightingMix("Outline Lighting Mix", Range(0, 1)) = 1
            _OutlineWidthColorMode("Outline Width Color Mode", Float) = 0
            _OutlineColorMode("Outline Color Mode", Float) = 0
            _OutlineColorFactor("Outline Color Factor", Range(0, 1)) = 1
            _OutlineLightingMixFactor("Outline Lighting Mix Factor", Range(0, 1)) = 1
            
            // UV Animation
            _UvAnimMaskTexture("UV Animation Mask", 2D) = "white" {}
            _UvAnimScrollX("UV Animation Scroll X", Float) = 0
            _UvAnimScrollY("UV Animation Scroll Y", Float) = 0
            _UvAnimRotation("UV Animation Rotation", Float) = 0
            
            // Advanced
            _IndirectLightIntensity("Indirect Light Intensity", Range(0, 1)) = 0.1
            _GiEqualization("GI Equalization", Range(0, 1)) = 0.9
            _LightColorAttenuation("Light Color Attenuation", Range(0, 1)) = 0
            [HDR]_SkyColor("Sky Color", Color) = (0.5, 0.5, 0.5, 1)
            [HDR]_GroundColor("Ground Color", Color) = (0.2, 0.2, 0.2, 1)
            
            // Alpha
            _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
            [Toggle] _AlphaCutoutEnable("Alpha Cutout Enable", Float) = 0
            [Toggle] _TransparentEnable("Transparent Enable", Float) = 0
    
            [HideInInspector] _Surface("__surface", Float) = 0.0
            [HideInInspector] _BlendMode("__blend", Float) = 0.0
            [HideInInspector] _AlphaCutoffEnable("__AlphaCutoffEnable", Float) = 0.0
        }
    
        SubShader
        {
            Tags
            { 
                "RenderPipeline" = "HDRenderPipeline" 
                "RenderType" = "Transparent"
                "Queue" = "Transparent"
            }
    
            HLSLINCLUDE
            #pragma target 4.5
                    
            // キーワードの整理
            #pragma shader_feature_local_fragment _MATCAP_ON
            #pragma multi_compile _ _ALPHATEST_ON
            #pragma multi_compile _ _ALPHABLEND_ON
            #pragma multi_compile _ _OPAQUE_MODE
            #pragma multi_compile _ _ZWRITE_ON
    
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
            #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
            #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
            
            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);
            TEXTURE2D(_ShadeMap);
            SAMPLER(sampler_ShadeMap);
            TEXTURE2D(_BumpMap);
            SAMPLER(sampler_BumpMap);
            TEXTURE2D(_MatCapTex);
            SAMPLER(sampler_MatCapTex);
            TEXTURE2D(_EmissionMap);
            SAMPLER(sampler_EmissionMap);
            TEXTURE2D(_UvAnimMaskTexture);
            SAMPLER(sampler_UvAnimMaskTexture);
    
            CBUFFER_START(UnityPerMaterial)
                // 既存のバッファー定義に加えて新しいプロパティを追加
                float4 _BaseMap_ST;
                float4 _BaseColor;
                float4 _ShadeColor;
                float _ShadeToony;
                float _ShadingShiftFactor;
                float _ShadingToonyFactor;
                float _ShadingGradeRate;
                float _ShadeShift;
                float _BumpScale;
                float4 _MatCapColor;
                float4 _RimColor;
                float _RimLightingMix;
                float _RimFresnelPower;
                float _RimLift;
                float _RimDirectionLightContribution;
                float _RimLightMode;
                float _RimBlendStart;
                float _RimBlendEnd;
                float4 _EmissionColor;
                float _IndirectLightIntensity;
                float _GiEqualization;
                float _LightColorAttenuation;
                float _Cutoff;
                float _OutlineWidth;
                float4 _OutlineColor;
                float _OutlineWidthMode;
                float _OutlineScaledMaxDistance;
                float _OutlineLightingMix;
                float _OutlineWidthColorMode;
                float _OutlineColorMode;
                float _OutlineColorFactor;
                float _OutlineLightingMixFactor;
                float _UvAnimScrollX;
                float _UvAnimScrollY;
                float _UvAnimRotation;
                float4 _SkyColor;
                float4 _GroundColor;
                float _AlphaCutoutEnable;
                float _TransparentEnable;
                float _ZWrite;
                float _Surface;
                float _BlendMode;
                float _AlphaCutoffEnable;
            CBUFFER_END
    
            // 既存の構造体定義
            struct AppData
            {
                float4 positionOS : POSITION;
                float3 normalOS : NORMAL;
                float4 tangentOS : TANGENT;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };
    
            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 positionWS : TEXCOORD1;
                float3 normalWS : TEXCOORD2;
                float4 tangentWS : TEXCOORD3;
                float3 viewDirWS : TEXCOORD4;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };
    
            float2 RotateUV(float2 uv, float rotation)
            {
                float cos_rot = cos(rotation);
                float sin_rot = sin(rotation);
                float2 piv = float2(0.5, 0.5);
                float2 uv_rot = uv - piv;
                float2 rotated = float2(
                    cos_rot * uv_rot.x - sin_rot * uv_rot.y,
                    sin_rot * uv_rot.x + cos_rot * uv_rot.y
                );
                return rotated + piv;
            }
    
            float2 GetAnimatedUV(float2 uv)
            {
                float2 scrolledUV = uv + float2(_UvAnimScrollX, _UvAnimScrollY) * _Time.y;
                return RotateUV(scrolledUV, _UvAnimRotation * _Time.y);
            }
    
            float3 GetAmbientLight(float3 positionWS, float3 normalWS)
            {
                float3 ambient = float3(0.0, 0.0, 0.0);
                float weight = 0.0f;
                float3 upperHemisphereColor = _SkyColor.rgb;
                float3 lowerHemisphereColor = _GroundColor.rgb;
                float upDot = dot(normalWS, float3(0.0, 1.0, 0.0));
                ambient = lerp(lowerHemisphereColor, upperHemisphereColor, upDot * 0.5 + 0.5);
                return ambient * _GiEqualization;
            }
    
            float3 CalculateToonDiffuse(float3 normal, float3 lightDir, float shadingGradeRate)
            {
                float ndotl = dot(normal, normalize(lightDir));
                float shadeShift = _ShadeShift + _ShadingShiftFactor;
                float shadingGrade = 1.0 - _ShadeToony * shadingGradeRate;
                float lighting = saturate((ndotl + shadeShift) / (1.0 + shadeShift));
                return float3(smoothstep(shadingGrade, 1.0, lighting), 
                             smoothstep(shadingGrade, 1.0, lighting),
                             smoothstep(shadingGrade, 1.0, lighting));
            }
    
            // Modified rim lighting calculation
            float3 CalculateRimLighting(float3 normal, float3 viewDir, float3 lightDir)
            {
                float rim = 1.0 - saturate(dot(viewDir, normal));
                float rimBlend = smoothstep(_RimBlendStart, _RimBlendEnd, rim);
                rim = pow(rim, _RimFresnelPower);
                rim = smoothstep(_RimLift, 1.0, rim);
                
                float lightContribution = 1.0;
                if (_RimLightMode == 1)
                {
                    float ndotl = dot(normal, lightDir);
                    lightContribution = smoothstep(0.0, 0.5, ndotl);
                }
                
                return _RimColor.rgb * rim * _RimLightingMix * lightContribution;
            }
    
            float3 CalculateOutlineVertexPosition(float4 positionOS, float3 normalOS, float outlineWidth, float outlineWidthMode)
            {
                float3 positionWS = TransformObjectToWorld(positionOS.xyz);
                float3 normalWS = TransformObjectToWorldNormal(normalOS);
                
                float outlineScale = 1;
                if (outlineWidthMode == 1) // WorldCoordinates
                {
                    outlineScale = 1;
                }
                else if (outlineWidthMode == 2) // ScreenCoordinates
                {
                    float4 projectedNormal = normalize(mul(UNITY_MATRIX_P, float4(normalWS, 0)));
                    float4 projectedPosition = mul(UNITY_MATRIX_P, float4(positionWS, 1));
                    float distanceScale = min(_OutlineScaledMaxDistance, distance(_WorldSpaceCameraPos, positionWS));
                    outlineScale = distanceScale * length(projectedNormal.xy);
                }
                
                return positionOS.xyz + normalOS * outlineWidth * outlineScale;
            }
    
            ENDHLSL
    
            // Opaque Pass
            Pass
            {
                Name "ForwardOnly"
                Tags { "LightMode" = "ForwardOnly" }
    
                Blend [_SrcBlend] [_DstBlend]
                ZWrite [_ZWrite]
                Cull [_CullMode]
    
                HLSLPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                
                Varyings vert(AppData input)
                {
                    Varyings output = (Varyings)0;
                    UNITY_SETUP_INSTANCE_ID(input);
                    UNITY_TRANSFER_INSTANCE_ID(input, output);
    
                    float2 uv = GetAnimatedUV(input.texcoord);
                    output.uv = TRANSFORM_TEX(uv, _BaseMap);
    
                    output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
                    output.positionWS = TransformObjectToWorld(input.positionOS.xyz);
                    output.normalWS = TransformObjectToWorldNormal(input.normalOS);
                    output.tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
                    output.viewDirWS = normalize(GetWorldSpaceViewDir(output.positionWS));
    
                    return output;
                }
    
                float4 frag(Varyings input) : SV_Target
                {
                    UNITY_SETUP_INSTANCE_ID(input);
    
                    float4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv);
                    float4 baseColor = baseMap * _BaseColor;
                    
                    #ifdef _ALPHATEST_ON
                        clip(baseColor.a - _Cutoff);
                    #endif
    
                    float4 shadeMap = SAMPLE_TEXTURE2D(_ShadeMap, sampler_ShadeMap, input.uv);
                    
                    float3 normalTS = UnpackNormalScale(SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, input.uv), _BumpScale);
                    float3 bitangent = normalize(cross(input.normalWS, input.tangentWS.xyz)) * input.tangentWS.w;
                    float3x3 tangentToWorld = float3x3(normalize(input.tangentWS.xyz), bitangent, input.normalWS);
                    float3 normalWS = normalize(mul(normalTS, tangentToWorld));
    
                    float3 lightDir = float3(0.5, 0.5, -0.5);
                    float3 lightColor = float3(1.0, 1.0, 1.0);
                    float shadingGrade = SAMPLE_TEXTURE2D(_UvAnimMaskTexture, sampler_UvAnimMaskTexture, input.uv).r * _ShadingGradeRate;
                    
                    float3 toonDiffuse = CalculateToonDiffuse(normalWS, lightDir, shadingGrade);
                    float lighting = toonDiffuse.r; // All components are the same
                    
                    float3 finalColor = lerp(shadeMap.rgb * _ShadeColor.rgb, baseColor.rgb, lighting);
                    finalColor = lerp(finalColor, finalColor * lightColor, _LightColorAttenuation);
    
                    #ifdef _MATCAP_ON
                        // 視線方向での法線の計算を修正
                        float3 viewNormal = normalize(mul(UNITY_MATRIX_IT_MV, float4(normalWS, 0.0)).xyz);
                        float2 matcapUV = viewNormal.xy * 0.5 + 0.5;
                        float3 matCap = SAMPLE_TEXTURE2D(_MatCapTex, sampler_MatCapTex, matcapUV).rgb;
                        
                        // マットキャップの合成方法を加算合成に変更
                        float3 matCapColor = matCap.rgb * _MatCapColor.rgb;
                        finalColor += matCapColor * _MatCapColor.a;
                    #endif
    
                    float3 rimColor = CalculateRimLighting(normalWS, input.viewDirWS, lightDir);
                    finalColor += rimColor;
                    
                    float3 emission = SAMPLE_TEXTURE2D(_EmissionMap, sampler_EmissionMap, input.uv).rgb * _EmissionColor.rgb;
                    finalColor += emission;
    
                    float3 ambient = GetAmbientLight(input.positionWS, normalWS);
                    float3 indirectLight = ambient * _IndirectLightIntensity;
                    finalColor += indirectLight * baseColor.rgb;
    
                    return float4(finalColor, baseColor.a);
                }
                ENDHLSL
            }
    
            // Outline Pass
            Pass
            {
                Name "Outline"
                Tags { "LightMode" = "ForwardOnly" }
                
                Cull Front
                
                HLSLPROGRAM
                #pragma vertex outlineVert
                #pragma fragment outlineFrag
    
                Varyings outlineVert(AppData input)
                {
                    Varyings output = (Varyings)0;
                    UNITY_SETUP_INSTANCE_ID(input);
                    UNITY_TRANSFER_INSTANCE_ID(input, output);
    
                    float3 posOS = CalculateOutlineVertexPosition(input.positionOS, input.normalOS, _OutlineWidth, _OutlineWidthMode);
                    
                    output.positionCS = TransformObjectToHClip(posOS);
                    output.positionWS = TransformObjectToWorld(posOS);
                    output.normalWS = TransformObjectToWorldNormal(input.normalOS);
                    output.tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
                    output.viewDirWS = normalize(GetWorldSpaceViewDir(output.positionWS));
                    output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
    
                    return output;
                }
    
                float4 outlineFrag(Varyings input) : SV_Target
                {
                    UNITY_SETUP_INSTANCE_ID(input);
                    
                    float4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv);
                    float4 outlineColor = _OutlineColor;
                    
                    if (_OutlineColorMode == 1) // Multiply with texture
                    {
                        outlineColor *= baseMap;
                    }
                    
                    float3 lightDir = float3(0.5, 0.5, -0.5);
                    float lighting = dot(input.normalWS, normalize(lightDir)) * 0.5 + 0.5;
                    outlineColor.rgb = lerp(outlineColor.rgb, outlineColor.rgb * lighting, _OutlineLightingMixFactor);
                    
                    return outlineColor;
                }
                ENDHLSL
            }
    
            // GBuffer Pass
            Pass
            {
                Name "GBuffer"
                Tags { "LightMode" = "GBuffer" }
    
                HLSLPROGRAM
                #pragma vertex Vert
                #pragma fragment Frag
                
                #define SHADERPASS SHADERPASS_GBUFFER
                
                #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
                #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
                #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl"
                #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl"
    
                struct AttributesMesh
                {
                    float3 positionOS   : POSITION;
                    float3 normalOS     : NORMAL;
                    float4 tangentOS    : TANGENT;
                    float2 texCoord0    : TEXCOORD0;
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                };
    
                struct PackedVaryingsmeshToPS
                {
                    float4 positionCS   : SV_Position;
                    float3 positionWS   : TEXCOORD0;
                    float3 normalWS     : TEXCOORD1;
                    float4 tangentWS    : TEXCOORD2;
                    float2 texCoord0    : TEXCOORD3;
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                };
    
                PackedVaryingsmeshToPS Vert(AttributesMesh inputMesh)
                {
                    PackedVaryingsmeshToPS output;
                    UNITY_SETUP_INSTANCE_ID(inputMesh);
                    UNITY_TRANSFER_INSTANCE_ID(inputMesh, output);
    
                    float3 positionWS = TransformObjectToWorld(inputMesh.positionOS);
                    output.positionCS = TransformWorldToHClip(positionWS);
                    output.positionWS = positionWS;
                    output.normalWS = TransformObjectToWorldNormal(inputMesh.normalOS);
                    output.tangentWS = float4(TransformObjectToWorldDir(inputMesh.tangentOS.xyz), inputMesh.tangentOS.w);
                    output.texCoord0 = inputMesh.texCoord0;
    
                    return output;
                }
    
            // GBuffer Passの改善提案
            void Frag(PackedVaryingsmeshToPS packedInput,
                out float4 outGBuffer0 : SV_Target0,
                out float4 outGBuffer1 : SV_Target1,
                out float4 outGBuffer2 : SV_Target2,
                out float4 outGBuffer3 : SV_Target3)
            {
                UNITY_SETUP_INSTANCE_ID(packedInput);
    
                float2 uv = packedInput.texCoord0;
                float4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv);
                float4 baseColor = baseMap * _BaseColor;
                float4 shadeMap = SAMPLE_TEXTURE2D(_ShadeMap, sampler_ShadeMap, uv);
    
                #ifdef _ALPHATEST_ON
                    clip(baseColor.a - _Cutoff);
                #endif
    
                // 法線計算の改善
                float3 normalTS = UnpackNormalScale(SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, uv), _BumpScale);
                float3 bitangent = normalize(cross(packedInput.normalWS, packedInput.tangentWS.xyz)) * packedInput.tangentWS.w;
                float3x3 tangentToWorld = float3x3(normalize(packedInput.tangentWS.xyz), bitangent, packedInput.normalWS);
                float3 normalWS = normalize(mul(normalTS, tangentToWorld));
    
                // シェーディンググレードの計算
                float shadingGrade = SAMPLE_TEXTURE2D(_UvAnimMaskTexture, sampler_UvAnimMaskTexture, uv).r * _ShadingGradeRate;
                float shadeShift = _ShadeShift + _ShadingShiftFactor;
                float shadingToony = lerp(1.0, _ShadingToonyFactor, shadingGrade);
    
                // エミッション
                float3 emissiveColor = SAMPLE_TEXTURE2D(_EmissionMap, sampler_EmissionMap, uv).rgb * _EmissionColor.rgb;
    
                // MatCapの処理
                #ifdef _MATCAP_ON
                    float3 viewNormal = mul((float3x3)UNITY_MATRIX_V, normalWS);
                    float2 matcapUV = viewNormal.xy * 0.5 + 0.5;
                    float3 matCapColor = SAMPLE_TEXTURE2D(_MatCapTex, sampler_MatCapTex, matcapUV).rgb * _MatCapColor.rgb;
                #else
                    float3 matCapColor = 0;
                #endif
    
                // GBufferへの改善された出力
                outGBuffer0 = float4(baseColor.rgb, baseColor.a);                    // Albedo + Alpha
                outGBuffer1 = float4(shadeMap.rgb * _ShadeColor.rgb, shadingToony); // Shade Color + Toony
                outGBuffer2 = float4(normalWS * 0.5 + 0.5, _ShadingGradeRate);      // Normal + Shading Grade
                outGBuffer3 = float4(emissiveColor + matCapColor,                    // Emission + MatCap
                                    shadeShift);                                     // Shade Shift
            }
                ENDHLSL
            }
        }
        CustomEditor "MToon.HDRPMToonInspector"
    }