#include "core.fsh"
#include "idioms.sh"

#ifdef _SHADERC_PRESET
#define ASSAO_HORIZONTAL_BLUR
#endif

uniform lowp sampler2D AOInputTexture;
uniform half4 AOInputSize;


const half4 HALF_ZERO = float4(0.f);
const half HALF_ONE = 1.f;
const half HALF_TWO = 2.f;
const half HALF_POINT_FIVE = 0.5f;
const half HALF_POINT_OO_ONE = 0.001f;

// ------------------------------------------------------------------
// Guassian Blur
// ------------------------------------------------------------------
const float kGuassianLinearOffsets[2] = float[2](0.53805, 2.06278);
const float kGuassianLinearWeights[2] = float[2](0.44908, 0.05092);

// @ref: https://www.intel.com/content/www/us/en/developer/articles/technical/an-investigation-of-fast-real-time-gpu-based-image-blur-algorithms.html
half4 GuassianBlur(float2 uv, float2 pixelOffset) {
    half4 colOut = HALF_ZERO;
    ////////////////////////////////////////////////;
    // Kernel width 7 x 7
    //
    const int stepCount = 2;
    //
    ////////////////////////////////////////////////;
    #pragma unroll
    for(int i = 0; i < stepCount; ++i) {
        float2 texCoordOffset = kGuassianLinearOffsets[i] * pixelOffset;
        half4 p1 = texture(AOInputTexture, uv - texCoordOffset);
        half4 p2 = texture(AOInputTexture, uv + texCoordOffset);
        half4 col = p1 + p2;
        colOut += kGuassianLinearWeights[i] * col;
    }

    return colOut;
}

half4 HorizontalGaussianBlur(float2 uv) {
    float2 delta = float2(AOInputSize.z, 0.f);
    return GuassianBlur(uv, delta);
}

half4 VerticalGuassianBlur(float2 uv) {
    float2 delta = float2(0.f, AOInputSize.w);
    return GuassianBlur(uv, delta);
}

in float2 UV_f;
layout(location = 0) out half4 fs_AOOutput;

void main() {
#ifdef ASSAO_HORIZONTAL_BLUR
    fs_AOOutput = HorizontalGaussianBlur(UV_f);
#else
    fs_AOOutput = VerticalGuassianBlur(UV_f);
#endif
}