Shader "CRTShader"
{
    Properties
    {
        _MainTex("Texture", 2D) = "Transparent" {}
        u_time("Time",float) = 0.5
        u_bend("Bend",range(0.5, 10.0)) = 0.5
        u_space_bend("Space Bend",range(1.5, 2.5)) = 2.5
        u_scanlin_transparence1("Scanline 1 Transparence",range(0, 0.5)) = 0.5
        u_scanline_size_1("Scanline Size 1",range(0, 750)) = 0.5
        u_scanline_speed_1("Scanline Speed 1",float) = 0.5
        u_scanlin_transparence2("Scanline 2 Transparence",range(0, 0.5)) = 0.5
        u_scanline_size_2("Scanline Size 2",range(0, 750)) = 0.5
        u_scanline_speed_2("Scanline Speed 2",float) = 0.5
        u_scanline_amount("Scanline Amount",range(0, 1)) = 0.5
        u_vignette_size("Vignette Size",range(0, 10)) = 0.5
        u_vignette_smoothness("Vignette Smoothness",range(0, 2)) = 0.5
        u_vignette_edge_round("Vignette Edge Round",range(0, 100)) = 0.5
        u_noise_size("Noise Size",range(0, 500 )) = 0.5
        u_noise_amount("Noise Amount",range(0, 0.15)) = 0.5
        u_red_offset_y("Red Offset",range(-0.01,0.01)) = 0
        u_green_offset_y("Green Offset",range(-0.01,0.01)) = 0
        u_blue_offset_y("Blue Offset",range(-0.01,0.01)) = 0
    }

    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Tags
        {
            "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"
        }

        Pass
        {
            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"

            #pragma vertex vert
            #pragma fragment frag

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);

            float _Intensity;

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

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                UNITY_VERTEX_OUTPUT_STEREO
            };


            Varyings vert(Attributes input)
            {
                Varyings output = (Varyings)0;
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);

                VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
                output.vertex = vertexInput.positionCS;
                output.uv = input.uv;

                return output;
            }

            uniform float u_time;
            uniform float u_bend;
            uniform float u_space_bend;
            uniform float u_scanlin_transparence1;
            uniform float u_scanline_size_1;
            uniform float u_scanline_speed_1;
            uniform float u_scanlin_transparence2;
            uniform float u_scanline_size_2;
            uniform float u_scanline_speed_2;
            uniform float u_scanline_amount;
            uniform float u_vignette_size;
            uniform float u_vignette_smoothness;
            uniform float u_vignette_edge_round;
            uniform float u_noise_size;
            uniform float u_noise_amount;
            uniform float u_red_offset_y;
            uniform float u_green_offset_y;
            uniform float u_blue_offset_y;

            half2 u_color_offset(float offset)
            {
                return half2(0, offset);
            }

            half2 crt_coords(half2 uv, float bend)
            {
                uv -= 0.5;
                uv *= 2.;
                
                uv.x *= 1. + pow(abs(uv.y) / bend, 2.);
                uv.y *= 1. + pow(abs(uv.x) / bend, 2.);

                uv /= u_space_bend;
                return (uv + .5);
            }

            float vignette(half2 uv, float size, float smoothness, float edgeRounding)
            {
                uv -= .5;
                uv *= size;
                float amount = sqrt(pow(abs(uv.x), edgeRounding) + pow(abs(uv.y), edgeRounding));
                amount = 1. - amount;
                return smoothstep(0, smoothness, amount);
            }

            float scanline(half2 uv, float lines, float speed, float transparence)
            {
                return sin(uv.y * lines + u_time * speed) * transparence;
            }

            float random(half2 uv)
            {
                return frac(sin(dot(uv, half2(15.1511, 42.5225))) * 12341.51611 * sin(u_time * 0.03));
            }

            float noise(half2 uv)
            {
                half2 i = floor(uv);
                half2 f = frac(uv);

                float a = random(i);
                float b = random(i + half2(1., 0.));
                float c = random(i + half2(0, 1.));
                float d = random(i + half2(1., 1.));

                half2 u = smoothstep(0., 1., f);

                return (lerp(a, b, u.x) + (c - a) * u.y * (1. - u.x) + (d - b) * u.x * u.y);
            }

            float4 frag(Varyings i) : SV_Target
            {
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
                u_time = _Time;
                half2 crt_uv = crt_coords(i.uv, u_bend);
                float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
                
                color.r = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, crt_uv + u_color_offset(u_red_offset_y)).r;
                color.g = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, crt_uv + u_color_offset(u_green_offset_y)).g;
                color.b = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, crt_uv + u_color_offset(u_blue_offset_y)).b;
                color.a = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, crt_uv).a;
                
                float s1 = scanline(i.uv, u_scanline_size_1, u_scanline_speed_1, u_scanlin_transparence1);
                float s2 = scanline(i.uv, u_scanline_size_2, u_scanline_speed_2, u_scanlin_transparence2);
                
                color = lerp(color, (s1 + s2), u_scanline_amount);
                color = lerp(color, noise(i.uv * u_noise_size), u_noise_amount);
                color *= vignette(i.uv, u_vignette_size, u_vignette_smoothness, u_vignette_edge_round);

                return color;
            }
            ENDHLSL
        }
    }
    FallBack "Diffuse"
}