export declare const speckleEdgesGeneratorFrag = "\n#include \nvarying vec2 vUv;\nuniform sampler2D tDepth;\nuniform sampler2D tNormal;\nuniform sampler2D tId;\nuniform float uDepthMultiplier;\nuniform float uDepthBias;\nuniform float uNormalMultiplier;\nuniform float uNormalBias;\nuniform float uOutlineThickness;\nuniform float uOutlineDensity;\nuniform vec3 uOutlineColor;\nuniform vec3 uBackgroundColor;\nuniform vec2 size;\n\nuniform float cameraNear;\nuniform float cameraFar;\nuniform mat4 cameraProjectionMatrix;\nuniform mat4 cameraInverseProjectionMatrix;\n\n#define ID_GRADIENT_THRESHOLD 1e-4\n#include \n\n\nfloat getDepth( const in ivec2 screenPosition ) {\n #if __VERSION__ == 300\n\t return unpackRGBAToDepth( texelFetch( tDepth, clamp(screenPosition, ivec2(0,0), ivec2(size)), 0 ) );\n #else\n vec2 cUv = vec2(0.5/size.x, 0.5/size.y);\n return unpackRGBAToDepth( texture2D( tDepth, vec2(min(screenPosition, ivec2(size)))/size + cUv ) );\n #endif\n}\n\n\n\nvec3 SobelSample(sampler2D t, vec2 uv, vec3 offset){\n\tvec3 pixelCenter = texture2D(t, uv).rgb;\n\tvec3 pixelLeft = texture2D(t, uv - offset.xz).rgb;\n\tvec3 pixelRight = texture2D(t, uv + offset.xz).rgb;\n\tvec3 pixelUp = texture2D(t, uv + offset.zy).rgb;\n\tvec3 pixelDown = texture2D(t, uv - offset.zy).rgb;\n\n\treturn abs(pixelLeft - pixelCenter) +\n\t\t\tabs(pixelRight - pixelCenter) +\n\t\t\tabs(pixelUp - pixelCenter) +\n\t\t\tabs(pixelDown - pixelCenter);\n}\n\n\nfloat GetTolerance(float d, float k)\n{\n // -------------------------------------------\n // Find a tolerance for depth that is constant\n // in view space (k in view space).\n //\n // tol = k*ddx(ZtoDepth(z))\n // -------------------------------------------\n \n float A=- (cameraFar+cameraNear)/(cameraFar - cameraNear);\n float B=-2.0*cameraFar*cameraNear /(cameraFar -cameraNear);\n \n d = d*2.0-1.0;\n \n return -k*(d+A)*(d+A)/B; \n}\n\nfloat DetectSilho(ivec2 fragCoord, ivec2 dir, float tolerance)\n{\n // -------------------------------------------\n // x0 ___ x1----o \n // : : \n // r0 : : r1\n // : : \n // o---x2 ___ x3\n //\n // r0 and r1 are the differences between actual\n // and expected (as if x0..3 where on the same\n // plane) depth values.\n // -------------------------------------------\n float x0 = abs(getDepth(fragCoord + dir*-2));\n float x1 = abs(getDepth(fragCoord + dir*-1));\n float x2 = abs(getDepth(fragCoord + dir* 0));\n float x3 = abs(getDepth(fragCoord + dir* 1));\n \n float d0 = (x1-x0);\n float d1 = (x2-x3);\n \n float r0 = x1 + d0 - x2;\n float r1 = x2 + d1 - x1;\n \n float tol = GetTolerance(x2, tolerance);\n \n return smoothstep(0.0, tol*tol, max( - r0*r1, 0.0));\n\n}\n\n// Source: https://www.shadertoy.com/view/DslXz2\nfloat DepthEdge(ivec2 fragCoord, float tolerance)\n{\n return max(\n DetectSilho(fragCoord, ivec2(1,0), tolerance), // Horizontal\n DetectSilho(fragCoord, ivec2(0,1), tolerance) // Vertical\n );\n}\n\nfloat NormalEdge(float scale)\n{\n\tfloat halfScaleFloor = floor(scale * 0.5);\n\tfloat halfScaleCeil = ceil(scale * 0.5);\n\n\tvec2 pixelSize = vec2(1.0 / size.x, 1.0 / size.y);\n\n\tvec2 bottomLeftUV = vUv - pixelSize * halfScaleFloor;\n\tvec2 topRightUV = vUv + pixelSize * halfScaleCeil; \n\tvec2 bottomRightUV = vUv + vec2(pixelSize.x * halfScaleCeil, -pixelSize.y * halfScaleFloor);\n\tvec2 topLeftUV = vUv + vec2(-pixelSize.x * halfScaleFloor, pixelSize.y * halfScaleCeil);\n\n\tvec3 centerNormal = unpackRGBToNormal(texture2D(tNormal, vUv).rgb);\n\tvec3 normal0 = unpackRGBToNormal(texture2D(tNormal, bottomLeftUV).rgb);\n\tvec3 normal1 = unpackRGBToNormal(texture2D(tNormal, topRightUV).rgb);\n\tvec3 normal2 = unpackRGBToNormal(texture2D(tNormal, bottomRightUV).rgb);\n\tvec3 normal3 = unpackRGBToNormal(texture2D(tNormal, topLeftUV).rgb);\n\n\tvec3 normalFiniteDifference0 = normal1 - normal0;\n\tvec3 normalFiniteDifference1 = normal3 - normal2;\n\n\treturn sqrt(dot(normalFiniteDifference0, normalFiniteDifference0) + dot(normalFiniteDifference1, normalFiniteDifference1));\n}\n\n/** Alternative to NormalEdge. */\nvec3 SobelSampleNormal(vec2 uv){\n\tfloat w = 1.0 / size.x;\n\tfloat h = 1.0 / size.y;\n\tvec3 n[9];\n\tn[0] = unpackRGBToNormal(texture2D(tNormal, uv + vec2( -w, -h)).rgb);\n\tn[1] = unpackRGBToNormal(texture2D(tNormal, uv + vec2(0.0, -h)).rgb);\n\tn[2] = unpackRGBToNormal(texture2D(tNormal, uv + vec2( w, -h)).rgb);\n\tn[3] = unpackRGBToNormal(texture2D(tNormal, uv + vec2( -w, 0.0)).rgb);\n\tn[4] = unpackRGBToNormal(texture2D(tNormal, uv).rgb);\n\tn[5] = unpackRGBToNormal(texture2D(tNormal, uv + vec2( w, 0.0)).rgb);\n\tn[6] = unpackRGBToNormal(texture2D(tNormal, uv + vec2( -w, h)).rgb);\n\tn[7] = unpackRGBToNormal(texture2D(tNormal, uv + vec2(0.0, h)).rgb);\n\tn[8] = unpackRGBToNormal(texture2D(tNormal, uv + vec2( w, h)).rgb);\n\n\tvec3 sobel_edge_h = n[2] + (2.0*n[5]) + n[8] - (n[0] + (2.0*n[3]) + n[6]);\n \tvec3 sobel_edge_v = n[0] + (2.0*n[1]) + n[2] - (n[6] + (2.0*n[7]) + n[8]);\n\tvec3 sobel = sqrt((sobel_edge_h * sobel_edge_h) + (sobel_edge_v * sobel_edge_v));\n\treturn sobel;\n}\n\n\nvoid main() {\n\t// Depth edge\n float depthEdge = DepthEdge(ivec2(gl_FragCoord), uDepthBias) * uDepthMultiplier; \n // Normal edge\n\tfloat normalEdge = pow(NormalEdge(uOutlineThickness) * uNormalMultiplier, uNormalBias);\n // Id edge\n\tvec3 offset = vec3((1.0 / size.x), (1.0 / size.y), 0.0) * uOutlineThickness;\n\tvec3 sobelIdVec = abs(SobelSample(tId, vUv, offset));\n // This is the branchless equivalent of sobelIdVec.x + sobelIdVec.y + sobelIdVec.z > ID_GRADIENT_THRESHOLD ? 1. : 0.\n\tfloat sobelIdEdge = step(ID_GRADIENT_THRESHOLD, sobelIdVec.x + sobelIdVec.y + sobelIdVec.z);\n\n // Combine the three edges by taking the minimum\n float maxOutline = saturate(max(sobelIdEdge, max(depthEdge, normalEdge)));\n\tfloat sobelOutline = maxOutline * uOutlineDensity;\n\n \n vec3 color = mix(uBackgroundColor, uOutlineColor, sobelOutline);\n float alpha = mix(0., uOutlineDensity, sobelOutline);\n // vec3 color = vec3(depthEdge, normalEdge, sobelIdEdge); // Debug\n\tgl_FragColor = vec4(color, alpha);\n\n}";