﻿Shader "SnapshotProHDRP/Painting"
{
    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);
	uint _KernelSize;

	struct region
	{
		float3 mean;
		float variance;
	};

	region calcRegion(int2 lower, int2 upper, int samples, float2 uv)
	{
		region r;
		float3 sum = 0.0f;
		float3 squareSum = 0.0f;

		for (int x = lower.x; x <= upper.x; ++x)
		{
			for (int y = lower.y; y <= upper.y; ++y)
			{
				float3 tex = LOAD_TEXTURE2D_X(_InputTexture, uv + float2(x, y));
				sum += tex;
				squareSum += tex * tex;
			}
		}

		r.mean = sum / samples;
		float3 variance = abs((squareSum / samples) - (r.mean * r.mean));
		r.variance = length(variance);

		return r;
	}

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

        uint2 positionSS = input.texcoord * _ScreenSize.xy;

		int upper = (_KernelSize - 1) / 2;
		int lower = -upper;

		int samples = (upper + 1) * (upper + 1);

		region regionA = calcRegion(int2(lower, lower), int2(0, 0), samples, positionSS);
		region regionB = calcRegion(int2(0, lower), int2(upper, 0), samples, positionSS);
		region regionC = calcRegion(int2(lower, 0), int2(0, upper), samples, positionSS);
		region regionD = calcRegion(int2(0, 0), int2(upper, upper), samples, positionSS);

		float3 col = regionA.mean;
		float minVar = regionA.variance;

		float testVal;

		testVal = step(regionB.variance, minVar);
		col = lerp(col, regionB.mean, testVal);
		minVar = lerp(minVar, regionB.variance, testVal);

		testVal = step(regionC.variance, minVar);
		col = lerp(col, regionC.mean, testVal);
		minVar = lerp(minVar, regionC.variance, testVal);

		testVal = step(regionD.variance, minVar);
		col = lerp(col, regionD.mean, testVal);

		return float4(col, 1.0f);
    }

    ENDHLSL

    SubShader
    {
        Pass
        {
            Name "Painting"

            ZWrite Off
            ZTest Always
            Blend Off
            Cull Off

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