Shader "Unlit/Silhouette"
{
    Properties
    {
        // Outline.
        _OutlineColor("Outline Color", Color) = (0, 0, 0, 0)
        _OutlineThickness("Outline Thickness", Float) = 0.1

        // Dither.
        _Color("Dither Color", Color) = (0, 0 ,0, 0)
        _DitherAmount("Dither Amount", Float) = 1
        _AlphaClipThreshold("Dither Alpha Clip Threshold", Float) = 1
    }

    SubShader
    {
        Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "RenderPipeline" = "UniversalPipeline" }

        ZWrite OFF // Alot of tranparency stuff.

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

        CBUFFER_START(UnityPerMaterial)

            //Outline.
            float4 _OutlineColor;
            float _OutlineThickness;

            // Dither.
            float4 _Color;
            float _DitherAmount;
            float _AlphaClipThreshold;

        CBUFFER_END

        // Unlit so no need for lighting etc, but you need the screen position and normal.
        struct VertexInput
        {
            float4 position : POSITION;
            float4 screenPosition : TEXCOORD1;
        };

        struct VertexOutput
        {
            float4 position : SV_POSITION;
            float4 screenPosition : TEXCOORD1;
        };

        struct VertexInputOutline
        {
            float4 position : POSITION;
            float3 normal : NORMAL;
        };

        struct VertexOutputOutline
        {
            float4 position : SV_POSITION;
        };

        ENDHLSL

        // This is the pass for the dither.
        Pass
        {   
            Blend srcAlpha OneMinusSrcAlpha 
  
            HLSLPROGRAM
            
            #pragma vertex vertex
            #pragma fragment fragment

            VertexOutput vertex(VertexInput input) 
            {
                VertexOutput output;
                
                output.position = TransformObjectToHClip(input.position.xyz);
                output.screenPosition = ComputeScreenPos(output.position);
                
                return output;
            }
            
            float Dither(float amount, float2 screenPosition) // Controls dither.
            {
                float2 uv = screenPosition.xy * _ScreenParams.xy; // UV.
                
                // This is a matrix to control the dither shape.
                float DITHER_THRESHOLDS[16] =
                {
                    1.0 / 17.0,  9.0 / 17.0,  3.0 / 17.0, 11.0 / 17.0,
                    13.0 / 17.0,  5.0 / 17.0, 15.0 / 17.0,  7.0 / 17.0,
                    4.0 / 17.0, 12.0 / 17.0,  2.0 / 17.0, 10.0 / 17.0,
                    16.0 / 17.0,  8.0 / 17.0, 14.0 / 17.0,  6.0 / 17.0
                };

                // I have no idea what this does lmao.
                uint index = (uint(uv.x) % 4) * 4 + uint(uv.y) % 4;
                return amount - DITHER_THRESHOLDS[index];
            }

            float4 fragment(VertexOutput input) : SV_Target
            {
                float ditherAmount = Dither(_DitherAmount, input.screenPosition.xy / input.screenPosition.w);
                clip(ditherAmount - _AlphaClipThreshold); // Sets clip to remove pixels that should be transparent.

                return _Color;
            }
                
            ENDHLSL
        }

        // Pass for the outline.
        Pass
        {
            Tags { "LightMode" = "Outline" }

            HLSLPROGRAM

            #pragma vertex vertex
            #pragma fragment fragment

            VertexOutputOutline vertex(VertexInputOutline input)
            {
                VertexOutputOutline output;

                float3 normal = normalize(input.normal) * _OutlineThickness;
                float3 position = input.position.xyz + normal;
                output.position = TransformObjectToHClip(position);

                return output;
            }

            float4 fragment(VertexOutputOutline input) : SV_Target
            {
                return _OutlineColor;
            }

            ENDHLSL
        }
    }
}