﻿Shader "SnapshotProHDRP/SobelNeon"
{
    HLSLINCLUDE

    #pragma target 4.5
    #pragma only_renderers d3d11 ps4 xboxone vulkan metal switch

    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/FXAA.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/RTUpscale.hlsl"

    struct Attributes
    {
        uint vertexID : SV_VertexID;
        UNITY_VERTEX_INPUT_INSTANCE_ID
    };

    struct Varyings
    {
        float4 positionCS : SV_POSITION;
        float2 texcoord   : TEXCOORD0;
        UNITY_VERTEX_OUTPUT_STEREO
    };

    Varyings Vert(Attributes input)
    {
        Varyings output;
        UNITY_SETUP_INSTANCE_ID(input);
        UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
        output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
        output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID);
        return output;
    }

    // List of properties to control your post process effect
	TEXTURE2D_X(_InputTexture);
	float _SaturationFloor;
	float _LightnessFloor;

	float3 sobel(float2 uv)
	{
		float3 x = 0.0f;
		float3 y = 0.0f;

		x += LOAD_TEXTURE2D_X(_InputTexture, uv + float2(-1, -1)).xyz * -1.0f;
		x += LOAD_TEXTURE2D_X(_InputTexture, uv + float2(-1,  0)).xyz * -2.0f;
		x += LOAD_TEXTURE2D_X(_InputTexture, uv + float2(-1,  1)).xyz * -1.0f;

		x += LOAD_TEXTURE2D_X(_InputTexture, uv + float2( 1, -1)).xyz *  1.0f;
		x += LOAD_TEXTURE2D_X(_InputTexture, uv + float2( 1,  0)).xyz *  2.0f;
		x += LOAD_TEXTURE2D_X(_InputTexture, uv + float2( 1,  1)).xyz *  1.0f;

		y += LOAD_TEXTURE2D_X(_InputTexture, uv + float2(-1, -1)).xyz * -1.0f;
		y += LOAD_TEXTURE2D_X(_InputTexture, uv + float2( 0, -1)).xyz * -2.0f;
		y += LOAD_TEXTURE2D_X(_InputTexture, uv + float2( 1, -1)).xyz * -1.0f;

		y += LOAD_TEXTURE2D_X(_InputTexture, uv + float2(-1,  1)).xyz *  1.0f;
		y += LOAD_TEXTURE2D_X(_InputTexture, uv + float2( 0,  1)).xyz *  2.0f;
		y += LOAD_TEXTURE2D_X(_InputTexture, uv + float2( 1,  1)).xyz *  1.0f;

		float xLum = Luminance(x);
		float yLum = Luminance(y);

		return sqrt(xLum * xLum + yLum * yLum);
	}

	// Credit: http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
	float3 rgb2hsv(float3 c)
	{
		float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
		float4 p = c.g < c.b ? float4(c.bg, K.wz) : float4(c.gb, K.xy);
		float4 q = c.r < p.x ? float4(p.xyw, c.r) : float4(c.r, p.yzx);

		float d = q.x - min(q.w, q.y);
		float e = 1.0e-10;
		return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
	}

	// Credit: http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
	float3 hsv2rgb(float3 c)
	{
		float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
		float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
		return c.z * lerp(K.xxx, saturate(p - K.xxx), c.y);
	}

    float4 CustomPostProcess(Varyings input) : SV_Target
    {
        UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

        uint2 positionSS = input.texcoord * _ScreenSize.xy;
		float3 tex = LOAD_TEXTURE2D_X(_InputTexture, positionSS);

		float3 hsvTex = rgb2hsv(tex);
		hsvTex.y = max(hsvTex.y, _SaturationFloor);
		hsvTex.z = max(hsvTex.z, _LightnessFloor);
		float3 col = hsv2rgb(hsvTex);

		return float4(col * sobel(positionSS), 1.0f);
    }

    ENDHLSL

    SubShader
    {
        Pass
        {
            Name "SobelNeon"

            ZWrite Off
            ZTest Always
            Blend Off
            Cull Off

            HLSLPROGRAM
                #pragma fragment CustomPostProcess
                #pragma vertex Vert
            ENDHLSL
        }
    }
    Fallback Off
}
