/**
 * Copyright (c) 2019-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
 *
 * @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
 * @author Alexander Rose <alexander.rose@weirdbyte.de>
 * @author Ludovic Autin <ludovic.autin@gmail.com>
 * @author Gianluca Tomasello <giagitom@gmail.com>
 */
export declare const ssaoBlur_frag = "\nprecision highp float;\nprecision highp int;\nprecision highp sampler2D;\n\nuniform sampler2D tSsaoDepth;\nuniform vec2 uTexSize;\nuniform vec4 uBounds;\n\nuniform float uKernel[dOcclusionKernelSize];\nuniform float uBlurDepthBias;\n\nuniform float uBlurDirectionX;\nuniform float uBlurDirectionY;\n\nuniform mat4 uInvProjection;\nuniform float uNear;\nuniform float uFar;\n\n#include common\n\nfloat getViewZ(const in float depth) {\n    #if dOrthographic == 1\n        return orthographicDepthToViewZ(depth, uNear, uFar);\n    #else\n        return perspectiveDepthToViewZ(depth, uNear, uFar);\n    #endif\n}\n\nbool isBackground(const in float depth) {\n    return depth == 1.0;\n}\n\nbool isNearClip(const in float depth) {\n    return depth == 0.0;\n}\n\nbool outsideBounds(const in vec2 p) {\n    return p.x < uBounds.x || p.y < uBounds.y || p.x > uBounds.z || p.y > uBounds.w;\n}\n\nfloat getPixelSize(const in vec2 coords, const in float depth) {\n    vec3 viewPos0 = screenSpaceToViewSpace(vec3(coords, depth), uInvProjection);\n    vec3 viewPos1 = screenSpaceToViewSpace(vec3(coords + vec2(1.0, 0.0) / uTexSize, depth), uInvProjection);\n    return distance(viewPos0, viewPos1);\n}\n\nvoid main(void) {\n    vec2 coords = gl_FragCoord.xy / uTexSize;\n\n    vec2 packedDepth = texture2D(tSsaoDepth, coords).zw;\n\n    if (outsideBounds(coords)) {\n        gl_FragColor = vec4(packUnitIntervalToRG(1.0), packedDepth);\n        return;\n    }\n\n    float selfDepth = unpackRGToUnitInterval(packedDepth);\n    // (if background and if second pass) or if near clip\n    if ((isBackground(selfDepth) && uBlurDirectionY != 0.0) || isNearClip(selfDepth)) {\n        gl_FragColor = vec4(packUnitIntervalToRG(1.0), packedDepth);\n        return;\n    }\n\n    float selfViewZ = getViewZ(selfDepth);\n    float pixelSize = getPixelSize(coords, selfDepth);\n\n    vec2 offset = vec2(uBlurDirectionX, uBlurDirectionY) / uTexSize;\n\n    float sum = 0.0;\n    float kernelSum = 0.0;\n    int halfKernelSize = dOcclusionKernelSize / 2;\n    // only if kernelSize is odd\n    for (int i = -halfKernelSize; i <= halfKernelSize; i++) {\n        if (abs(float(i)) > 1.0 && abs(float(i)) * pixelSize > 0.8) continue;\n\n        vec2 sampleCoords = coords + float(i) * offset;\n        if (outsideBounds(sampleCoords)) {\n            continue;\n        }\n\n        vec4 sampleSsaoDepth = texture2D(tSsaoDepth, sampleCoords);\n\n        float sampleDepth = unpackRGToUnitInterval(sampleSsaoDepth.zw);\n        if (isBackground(sampleDepth) || isNearClip(sampleDepth)) {\n            continue;\n        }\n\n        float sampleViewZ = getViewZ(sampleDepth);\n        if (abs(selfViewZ - sampleViewZ) >= uBlurDepthBias) {\n            continue;\n        }\n\n        float kernel = uKernel[int(abs(float(i)))]; // abs is not defined for int in webgl1\n        float sampleValue = unpackRGToUnitInterval(sampleSsaoDepth.xy);\n\n        sum += kernel * sampleValue;\n        kernelSum += kernel;\n    }\n    gl_FragColor = vec4(packUnitIntervalToRG(sum / kernelSum), packedDepth);\n}\n";
