// This shader draws a texture on the mesh.
Shader "KernelPanic/glitch"
{
    // The _BaseMap variable is visible in the Material's Inspector, as a field
    // called Base Map.
    Properties
    {
        [HDR] _BaseColor("Base Color", Color) = (1,1,1,1)
        [HDR] _NoiseColor("Noise Color", Color) = (1,1,1,1)
        [HDR] _GlitchColor("Glitch Color", Color) = (1,1,1,1)

        _BaseMap("Base Map", 2D) = "white"
        _NoiseMap1("Noise 1", 2D) = "black"
        _GlitchTex("Glitch Tex", 2D) = "black"

        [Range(0,1)] _Distortion("Distortion", Float) = 0
        _Intensity("Intensity", Float) = 1
        _TrailScatter("Trail Scatter", Float) = 0.02
        _VertShake("Vertex Shake", Float) = 0.05
        _VertFloat("Vertex Float", Float) = 0.1
    }

    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "Queue" = "Geometry"
            "RenderPipeline" = "UniversalRenderPipeline"
        }

        Pass
        {
            Stencil
            {
                Ref 1
                Comp always
                Pass replace
            }
            
            Cull Off
            Zwrite On
            ZTest LEqual
            
            Blend SrcAlpha OneMinusSrcAlpha

            HLSLPROGRAM
            // #pragma target 5.0
            // #pragma only_renderers d3d11

            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Assets/Shaders/random.cginc"

            struct Attributes
            {
                float4 positionOS : POSITION;
                // The uv variable contains the UV coordinate on the texture for the
                // given vertex.
                float2 uv : TEXCOORD0;
                half3 normal : NORMAL;
            };

            struct Varyings
            {
                float4 positionHCS : SV_POSITION;
                // The uv variable contains the UV coordinate on the texture for the
                // given vertex.
                float2 uv : TEXCOORD0;
                half3 normal : NORMAL;
                float4 screenPos : TEXCOORD1;
            };

            // This macro declares _BaseMap as a Texture2D object.
            TEXTURE2D(_BaseMap);
            TEXTURE2D(_NoiseMap1);
            TEXTURE2D(_GlitchTex);
            TEXTURE2D(_CameraDepthTexture);

            // This macro declares the sampler for the _BaseMap texture.
            SAMPLER(sampler_BaseMap);
            SAMPLER(sampler_NoiseMap1);
            SAMPLER(sampler_GlitchTex);
            SAMPLER(sampler_CameraDepthTexture);

            CBUFFER_START(UnityPerMaterial)
            // The following line declares the _BaseMap_ST variable, so that you
            // can use the _BaseMap variable in the fragment shader. The _ST 
            // suffix is necessary for the tiling and offset function to work.
            float4 _BaseMap_ST;
            float4 _NoiseMap_ST;
            
            float _VertFloat;
            float _VertShake;
            float _Distortion;
            float _Intensity;
            float _TrailScatter;
            
            float4 _NoiseColor;
            float4 _BaseColor;
            float4 _GlitchColor;
            CBUFFER_END

            UNITY_INSTANCING_BUFFER_START(Props)
            UNITY_DEFINE_INSTANCED_PROP(float4, _Positions)
            UNITY_INSTANCING_BUFFER_END(Props)

            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                OUT.normal = TransformObjectToWorldDir(IN.normal);
                // OUT.normal = IN.normal;

                float4 poscs = TransformObjectToHClip(IN.positionOS);
                
                float4 n = SAMPLE_TEXTURE2D_LOD(_NoiseMap1, sampler_NoiseMap1, hash42(poscs+_Time), 0);
                
                float3 pos = IN.positionOS + (n-0.5) * _VertShake;
                float4 p = UNITY_ACCESS_INSTANCED_PROP(Props, _Positions);
                float t = sin(p.y*_Time.w + p.x*6.28);

                float3 wpos = TransformObjectToWorld(pos);
                wpos += float3(0,t*p.z*_VertFloat,0);
                pos = TransformWorldToObject(wpos);

                OUT.positionHCS = TransformObjectToHClip(pos);
                // The TRANSFORM_TEX macro performs the tiling and offset
                // transformation.
                OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
                OUT.screenPos = ComputeScreenPos(OUT.positionHCS);
                
                return OUT;
            }

            half4 frag(Varyings IN) : SV_Target
            {
                float2 suv = IN.screenPos.xy / IN.screenPos.w;

                float d = SAMPLE_TEXTURE2D(_CameraDepthTexture, sampler_CameraDepthTexture, suv);

                
                // float4 p = float4(.42069, .6969, .1337, .8008135);
                float4 p = UNITY_ACCESS_INSTANCED_PROP(Props, _Positions);
                
                
                float t = (p.x*sin(_Time.y)+p.w*cos(_Time.x)) * 0.5 + 0.5;
                
                // sample regular color
                float4 c = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, (IN.uv +lerp(p.xy,p.zw,0.2+0.6*t))*0.5);
                // c = lerp(c, _BaseColor, 0.5);

                float4 n = SAMPLE_TEXTURE2D(_NoiseMap1, sampler_NoiseMap1, (IN.uv +lerp(p.xy,p.zw,0.9-30*t))*190);
                n *= _NoiseColor;

                // sample blended glitch
                float4 g = SAMPLE_TEXTURE2D(_GlitchTex, sampler_GlitchTex,
                    suv + _TrailScatter*n*hash42(IN.uv));
                // g *= _GlitchColor;
                // g = 1 - g;


                // sample color distorted by noise
                float distortion = _Distortion + (t-0.5) * _Intensity;
                float4 cd = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv + n * distortion * t);

                // float4 cn = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv + nuv * _GlitchColor);
                // c *= _BaseColor;

                // cn = lerp(cn,(1-cn),_Distortion);
                // cn += n;

                // float4 color = lerp(c, cn, n);

                // cheeky bit of top shading
                float un = dot(float3(0,1,0), IN.normal); // dot of up and normal
                c = lerp(c,_BaseColor,un*(1-d));
                // color += (1-abs(un)) *_BaseColor;
                
                c = lerp(n, c, g);
                // c = min(c, float4(1, 1, 1, 1));

                c += n*_NoiseColor;
                
                // c = lerp(n,c,0.5);
                // c = lerp(c, _BaseColor, _BaseColor.a);
                
                return c * _BaseColor;
            }
            ENDHLSL
        }

        UsePass "Universal Render Pipeline/Lit/DepthOnly"
    }
}