declare const _default: "\n    #include \"screenDepthPS\"\n    \n    varying vec2 uv0;\n\n    uniform vec2 uInvResolution;\n    uniform float uAspect;\n\n    #define saturate(x) clamp(x,0.0,1.0)\n\n    // Largely based on 'Dominant Light Shadowing'\n    // 'Lighting Technology of The Last of Us Part II' by Hawar Doghramachi, Naughty Dog, LLC\n\n    highp float getWFromProjectionMatrix(const mat4 p, const vec3 v) {\n        // this essentially returns (p * vec4(v, 1.0)).w, but we make some assumptions\n        // this assumes a perspective projection\n        return -v.z;\n        // this assumes a perspective or ortho projection\n        // return p[2][3] * v.z + p[3][3];\n    }\n\n    highp float getViewSpaceZFromW(const mat4 p, const float w) {\n        // this assumes a perspective projection\n        return -w;\n        // this assumes a perspective or ortho projection\n        // return (w - p[3][3]) / p[2][3];\n    }\n\n    const float kLog2LodRate = 3.0;\n\n    // random number between 0 and 1, using interleaved gradient noise\n    float random(const highp vec2 w) {\n        const vec3 m = vec3(0.06711056, 0.00583715, 52.9829189);\n        return fract(m.z * fract(dot(w, m.xy)));\n    }\n\n    // returns the frag coord in the GL convention with (0, 0) at the bottom-left\n    highp vec2 getFragCoord() {\n        return gl_FragCoord.xy;\n    }\n\n    highp vec3 computeViewSpacePositionFromDepth(highp vec2 uv, highp float linearDepth) {\n        return vec3((0.5 - uv) * vec2(uAspect, 1.0) * linearDepth, linearDepth);\n    }\n\n    highp vec3 faceNormal(highp vec3 dpdx, highp vec3 dpdy) {\n        return normalize(cross(dpdx, dpdy));\n    }\n\n    // Compute normals using derivatives, which essentially results in half-resolution normals\n    // this creates artifacts around geometry edges.\n    // Note: when using the spirv optimizer, this results in much slower execution time because\n    //       this whole expression is inlined in the AO loop below.\n    highp vec3 computeViewSpaceNormal(const highp vec3 position) {\n        return faceNormal(dFdx(position), dFdy(position));\n    }\n\n    // Compute normals directly from the depth texture, resulting in full resolution normals\n    // Note: This is actually as cheap as using derivatives because the texture fetches\n    //       are essentially equivalent to textureGather (which we don't have on ES3.0),\n    //       and this is executed just once.\n    highp vec3 computeViewSpaceNormal(const highp vec3 position, const highp vec2 uv) {\n        highp vec2 uvdx = uv + vec2(uInvResolution.x, 0.0);\n        highp vec2 uvdy = uv + vec2(0.0, uInvResolution.y);\n        highp vec3 px = computeViewSpacePositionFromDepth(uvdx, -getLinearScreenDepth(uvdx));\n        highp vec3 py = computeViewSpacePositionFromDepth(uvdy, -getLinearScreenDepth(uvdy));\n        highp vec3 dpdx = px - position;\n        highp vec3 dpdy = py - position;\n        return faceNormal(dpdx, dpdy);\n    }\n\n    // Ambient Occlusion, largely inspired from:\n    // 'The Alchemy Screen-Space Ambient Obscurance Algorithm' by Morgan McGuire\n    // 'Scalable Ambient Obscurance' by Morgan McGuire, Michael Mara and David Luebke\n\n    uniform vec2 uSampleCount;\n    uniform float uSpiralTurns;\n\n    #define PI (3.14159)\n\n    mediump vec3 tapLocation(mediump float i, const mediump float noise) {\n        mediump float offset = ((2.0 * PI) * 2.4) * noise;\n        mediump float angle = ((i * uSampleCount.y) * uSpiralTurns) * (2.0 * PI) + offset;\n        mediump float radius = (i + noise + 0.5) * uSampleCount.y;\n        return vec3(cos(angle), sin(angle), radius * radius);\n    }\n\n    highp vec2 startPosition(const float noise) {\n        float angle = ((2.0 * PI) * 2.4) * noise;\n        return vec2(cos(angle), sin(angle));\n    }\n\n    uniform vec2 uAngleIncCosSin;\n\n    highp mat2 tapAngleStep() {\n        highp vec2 t = uAngleIncCosSin;\n        return mat2(t.x, t.y, -t.y, t.x);\n    }\n\n    mediump vec3 tapLocationFast(mediump float i, mediump vec2 p, const mediump float noise) {\n        mediump float radius = (i + noise + 0.5) * uSampleCount.y;\n        return vec3(p, radius * radius);\n    }\n\n    uniform float uMaxLevel;\n    uniform float uInvRadiusSquared;\n    uniform float uMinHorizonAngleSineSquared;\n    uniform float uBias;\n    uniform float uPeak2;\n\n    void computeAmbientOcclusionSAO(inout mediump float occlusion, mediump float i, mediump float ssDiskRadius,\n            const highp vec2 uv, const highp vec3 origin, const mediump vec3 normal,\n            const mediump vec2 tapPosition, const float noise) {\n\n        mediump vec3 tap = tapLocationFast(i, tapPosition, noise);\n\n        mediump float ssRadius = max(1.0, tap.z * ssDiskRadius); // at least 1 pixel screen-space radius\n\n        mediump vec2 uvSamplePos = uv + vec2(ssRadius * tap.xy) * uInvResolution;\n\n        // TODO: level is not used, but could be used with mip-mapped depth texture\n        mediump float level = clamp(floor(log2(ssRadius)) - kLog2LodRate, 0.0, float(uMaxLevel));\n        highp float occlusionDepth = -getLinearScreenDepth(uvSamplePos);\n        highp vec3 p = computeViewSpacePositionFromDepth(uvSamplePos, occlusionDepth);\n\n        // now we have the sample, compute AO\n        vec3 v = p - origin;        // sample vector\n        float vv = dot(v, v);       // squared distance\n        float vn = dot(v, normal);  // distance * cos(v, normal)\n\n        // discard samples that are outside of the radius, preventing distant geometry to cast\n        // shadows -- there are many functions that work and choosing one is an artistic decision.\n        mediump float w = max(0.0, 1.0 - vv * uInvRadiusSquared);\n        w = w * w;\n\n        // discard samples that are too close to the horizon to reduce shadows cast by geometry\n        // not sufficiently tessellated. The goal is to discard samples that form an angle 'beta'\n        // smaller than 'epsilon' with the horizon. We already have dot(v,n) which is equal to the\n        // sin(beta) * |v|. So the test simplifies to vn^2 < vv * sin(epsilon)^2.\n        w *= step(vv * uMinHorizonAngleSineSquared, vn * vn);\n\n        occlusion += w * max(0.0, vn + origin.z * uBias) / (vv + uPeak2);\n    }\n\n    uniform float uProjectionScaleRadius;\n    uniform float uIntensity;\n    uniform float uRandomize;\n\n    float scalableAmbientObscurance(highp vec2 uv, highp vec3 origin, vec3 normal) {\n        float noise = random(getFragCoord()) + uRandomize;\n        highp vec2 tapPosition = startPosition(noise);\n        highp mat2 angleStep = tapAngleStep();\n\n        // Choose the screen-space sample radius\n        // proportional to the projected area of the sphere\n        float ssDiskRadius = -(uProjectionScaleRadius / origin.z);\n\n        float occlusion = 0.0;\n        for (float i = 0.0; i < uSampleCount.x; i += 1.0) {\n            computeAmbientOcclusionSAO(occlusion, i, ssDiskRadius, uv, origin, normal, tapPosition, noise);\n            tapPosition = angleStep * tapPosition;\n        }\n        return occlusion;\n    }\n\n    uniform float uPower;\n\n    void main() {\n        highp vec2 uv = uv0; // interpolated to pixel center\n\n        highp float depth = -getLinearScreenDepth(uv0);\n        highp vec3 origin = computeViewSpacePositionFromDepth(uv, depth);\n        vec3 normal = computeViewSpaceNormal(origin, uv);\n\n        float occlusion = 0.0;\n        if (uIntensity > 0.0) {\n            occlusion = scalableAmbientObscurance(uv, origin, normal);\n        }\n\n        // occlusion to visibility\n        float ao = max(0.0, 1.0 - occlusion * uIntensity);\n        ao = pow(ao, uPower);\n\n        gl_FragColor = vec4(ao, ao, ao, 1.0);\n    }\n";
export default _default;
