export declare const fxaa_frag = "\nprecision highp float;\nprecision highp int;\nprecision highp sampler2D;\n\nuniform sampler2D tColor;\nuniform vec2 uTexSizeInv;\n\n// adapted from https://github.com/kosua20/Rendu\n// MIT License Copyright (c) 2017 Simon Rodriguez\n\n#define QUALITY(q) ((q) < 5 ? 1.0 : ((q) > 5 ? ((q) < 10 ? 2.0 : ((q) < 11 ? 4.0 : 8.0)) : 1.5))\n\nfloat rgb2luma(vec3 rgb){\n    return sqrt(dot(rgb, vec3(0.299, 0.587, 0.114)));\n}\n\nfloat sampleLuma(vec2 uv) {\n    return rgb2luma(texture2D(tColor, uv).rgb);\n}\n\nfloat sampleLuma(vec2 uv, float uOffset, float vOffset) {\n    uv += uTexSizeInv * vec2(uOffset, vOffset);\n    return sampleLuma(uv);\n}\n\nvoid main(void) {\n    vec2 coords = gl_FragCoord.xy * uTexSizeInv;\n    vec2 inverseScreenSize = uTexSizeInv;\n\n    vec4 colorCenter = texture2D(tColor, coords);\n\n    // Luma at the current fragment\n    float lumaCenter = rgb2luma(colorCenter.rgb);\n\n    // Luma at the four direct neighbours of the current fragment.\n    float lumaDown = sampleLuma(coords, 0.0, -1.0);\n    float lumaUp = sampleLuma(coords, 0.0, 1.0);\n    float lumaLeft = sampleLuma(coords, -1.0, 0.0);\n    float lumaRight = sampleLuma(coords, 1.0, 0.0);\n\n    // Find the maximum and minimum luma around the current fragment.\n    float lumaMin = min(lumaCenter, min(min(lumaDown, lumaUp), min(lumaLeft, lumaRight)));\n    float lumaMax = max(lumaCenter, max(max(lumaDown, lumaUp), max(lumaLeft, lumaRight)));\n\n    // Compute the delta.\n    float lumaRange = lumaMax - lumaMin;\n\n    // If the luma variation is lower that a threshold (or if we are in a really dark area),\n    // we are not on an edge, don't perform any AA.\n    if (lumaRange < max(dEdgeThresholdMin, lumaMax * dEdgeThresholdMax)) {\n        gl_FragColor = colorCenter;\n        return;\n    }\n\n    // Query the 4 remaining corners lumas.\n    float lumaDownLeft = sampleLuma(coords, -1.0, -1.0);\n    float lumaUpRight = sampleLuma(coords, 1.0, 1.0);\n    float lumaUpLeft = sampleLuma(coords, -1.0, 1.0);\n    float lumaDownRight = sampleLuma(coords, 1.0, -1.0);\n\n    // Combine the four edges lumas (using intermediary variables for future computations\n    // with the same values).\n    float lumaDownUp = lumaDown + lumaUp;\n    float lumaLeftRight = lumaLeft + lumaRight;\n\n    // Same for corners\n    float lumaLeftCorners = lumaDownLeft + lumaUpLeft;\n    float lumaDownCorners = lumaDownLeft + lumaDownRight;\n    float lumaRightCorners = lumaDownRight + lumaUpRight;\n    float lumaUpCorners = lumaUpRight + lumaUpLeft;\n\n    // Compute an estimation of the gradient along the horizontal and vertical axis.\n    float edgeHorizontal = abs(-2.0 * lumaLeft + lumaLeftCorners) + abs(-2.0 * lumaCenter + lumaDownUp) * 2.0 + abs(-2.0 * lumaRight + lumaRightCorners);\n    float edgeVertical = abs(-2.0 * lumaUp + lumaUpCorners) + abs(-2.0 * lumaCenter + lumaLeftRight) * 2.0 + abs(-2.0 * lumaDown + lumaDownCorners);\n\n    // Is the local edge horizontal or vertical ?\n    bool isHorizontal = (edgeHorizontal >= edgeVertical);\n\n    // Choose the step size (one pixel) accordingly.\n    float stepLength = isHorizontal ? inverseScreenSize.y : inverseScreenSize.x;\n\n    // Select the two neighboring texels lumas in the opposite direction to the local edge.\n    float luma1 = isHorizontal ? lumaDown : lumaLeft;\n    float luma2 = isHorizontal ? lumaUp : lumaRight;\n    // Compute gradients in this direction.\n    float gradient1 = luma1 - lumaCenter;\n    float gradient2 = luma2 - lumaCenter;\n\n    // Which direction is the steepest ?\n    bool is1Steepest = abs(gradient1) >= abs(gradient2);\n\n    // Gradient in the corresponding direction, normalized.\n    float gradientScaled = 0.25 * max(abs(gradient1), abs(gradient2));\n\n    // Average luma in the correct direction.\n    float lumaLocalAverage = 0.0;\n    if(is1Steepest){\n        // Switch the direction\n        stepLength = -stepLength;\n        lumaLocalAverage = 0.5 * (luma1 + lumaCenter);\n    } else {\n        lumaLocalAverage = 0.5 * (luma2 + lumaCenter);\n    }\n\n    // Shift UV in the correct direction by half a pixel.\n    vec2 currentUv = coords;\n    if(isHorizontal){\n        currentUv.y += stepLength * 0.5;\n    } else {\n        currentUv.x += stepLength * 0.5;\n    }\n\n    // Compute offset (for each iteration step) in the right direction.\n    vec2 offset = isHorizontal ? vec2(inverseScreenSize.x, 0.0) : vec2(0.0, inverseScreenSize.y);\n    // Compute UVs to explore on each side of the edge, orthogonally.\n    // The QUALITY allows us to step faster.\n    vec2 uv1 = currentUv - offset * QUALITY(0);\n    vec2 uv2 = currentUv + offset * QUALITY(0);\n\n    // Read the lumas at both current extremities of the exploration segment,\n    // and compute the delta wrt to the local average luma.\n    float lumaEnd1 = sampleLuma(uv1);\n    float lumaEnd2 = sampleLuma(uv2);\n    lumaEnd1 -= lumaLocalAverage;\n    lumaEnd2 -= lumaLocalAverage;\n\n    // If the luma deltas at the current extremities is larger than the local gradient,\n    // we have reached the side of the edge.\n    bool reached1 = abs(lumaEnd1) >= gradientScaled;\n    bool reached2 = abs(lumaEnd2) >= gradientScaled;\n    bool reachedBoth = reached1 && reached2;\n\n    // If the side is not reached, we continue to explore in this direction.\n    if(!reached1){\n        uv1 -= offset * QUALITY(1);\n    }\n    if(!reached2){\n        uv2 += offset * QUALITY(1);\n    }\n\n    // If both sides have not been reached, continue to explore.\n    if(!reachedBoth){\n        for(int i = 2; i < dIterations; i++){\n            // If needed, read luma in 1st direction, compute delta.\n            if(!reached1){\n                lumaEnd1 = sampleLuma(uv1);\n                lumaEnd1 = lumaEnd1 - lumaLocalAverage;\n            }\n            // If needed, read luma in opposite direction, compute delta.\n            if(!reached2){\n                lumaEnd2 = sampleLuma(uv2);\n                lumaEnd2 = lumaEnd2 - lumaLocalAverage;\n            }\n            // If the luma deltas at the current extremities is larger than the local gradient,\n            // we have reached the side of the edge.\n            reached1 = abs(lumaEnd1) >= gradientScaled;\n            reached2 = abs(lumaEnd2) >= gradientScaled;\n            reachedBoth = reached1 && reached2;\n\n            // If the side is not reached, we continue to explore in this direction,\n            // with a variable quality.\n            if(!reached1){\n                uv1 -= offset * QUALITY(i);\n            }\n            if(!reached2){\n                uv2 += offset * QUALITY(i);\n            }\n\n            // If both sides have been reached, stop the exploration.\n            if(reachedBoth){\n                break;\n            }\n        }\n    }\n\n    // Compute the distances to each side edge of the edge (!).\n    float distance1 = isHorizontal ? (coords.x - uv1.x) : (coords.y - uv1.y);\n    float distance2 = isHorizontal ? (uv2.x - coords.x) : (uv2.y - coords.y);\n\n    // In which direction is the side of the edge closer ?\n    bool isDirection1 = distance1 < distance2;\n    float distanceFinal = min(distance1, distance2);\n\n    // Thickness of the edge.\n    float edgeThickness = (distance1 + distance2);\n\n    // Is the luma at center smaller than the local average ?\n    bool isLumaCenterSmaller = lumaCenter < lumaLocalAverage;\n\n    // If the luma at center is smaller than at its neighbour,\n    // the delta luma at each end should be positive (same variation).\n    bool correctVariation1 = (lumaEnd1 < 0.0) != isLumaCenterSmaller;\n    bool correctVariation2 = (lumaEnd2 < 0.0) != isLumaCenterSmaller;\n\n    // Only keep the result in the direction of the closer side of the edge.\n    bool correctVariation = isDirection1 ? correctVariation1 : correctVariation2;\n\n    // UV offset: read in the direction of the closest side of the edge.\n    float pixelOffset = - distanceFinal / edgeThickness + 0.5;\n\n    // If the luma variation is incorrect, do not offset.\n    float finalOffset = correctVariation ? pixelOffset : 0.0;\n\n    // Sub-pixel shifting\n    // Full weighted average of the luma over the 3x3 neighborhood.\n    float lumaAverage = (1.0 / 12.0) * (2.0 * (lumaDownUp + lumaLeftRight) + lumaLeftCorners + lumaRightCorners);\n    // Ratio of the delta between the global average and the center luma,\n    // over the luma range in the 3x3 neighborhood.\n    float subPixelOffset1 = clamp(abs(lumaAverage - lumaCenter) / lumaRange, 0.0, 1.0);\n    float subPixelOffset2 = (-2.0 * subPixelOffset1 + 3.0) * subPixelOffset1 * subPixelOffset1;\n    // Compute a sub-pixel offset based on this delta.\n    float subPixelOffsetFinal = subPixelOffset2 * subPixelOffset2 * float(dSubpixelQuality);\n\n    // Pick the biggest of the two offsets.\n    finalOffset = max(finalOffset, subPixelOffsetFinal);\n\n    // Compute the final UV coordinates.\n    vec2 finalUv = coords;\n    if(isHorizontal){\n        finalUv.y += finalOffset * stepLength;\n    } else {\n        finalUv.x += finalOffset * stepLength;\n    }\n\n    // Read the color at the new UV coordinates, and use it.\n    gl_FragColor = texture2D(tColor, finalUv);\n}\n";
