/**
 * Copyright (c) 2019-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
 *
 * @author Alexander Rose <alexander.rose@weirdbyte.de>
 */
export declare const spheres_vert = "\nprecision highp float;\nprecision highp int;\n\n#include common\n#include read_from_texture\n#include common_vert_params\n#include color_vert_params\n#include size_vert_params\n#include common_clip\n\nuniform mat4 uModelView;\nuniform mat4 uInvProjection;\nuniform float uIsOrtho;\nuniform bool uIsAsymmetricProjection;\n\nuniform vec2 uTexDim;\nuniform sampler2D tPositionGroup;\n\nattribute mat4 aTransform;\nattribute float aInstance;\n\nvarying float vRadius;\nvarying vec3 vPoint;\nvarying vec3 vPointViewPosition;\n\n/**\n * Bounding rectangle of a clipped, perspective-projected 3D Sphere.\n * Michael Mara, Morgan McGuire. 2013\n *\n * Specialization by Arseny Kapoulkine, MIT License Copyright (c) 2018\n * https://github.com/zeux/niagara\n *\n * Only works for for symmetric projections.\n */\nvoid sphereProjection(const in vec3 p, const in float r, const in vec2 mapping) {\n    vec3 pr = p * r;\n    float pzr2 = p.z * p.z - r * r;\n\n    float vx = sqrt(p.x * p.x + pzr2);\n    float minx = ((vx * p.x - pr.z) / (vx * p.z + pr.x)) * uProjection[0][0];\n    float maxx = ((vx * p.x + pr.z) / (vx * p.z - pr.x)) * uProjection[0][0];\n\n    float vy = sqrt(p.y * p.y + pzr2);\n    float miny = ((vy * p.y - pr.z) / (vy * p.z + pr.y)) * uProjection[1][1];\n    float maxy = ((vy * p.y + pr.z) / (vy * p.z - pr.y)) * uProjection[1][1];\n\n    gl_Position.xy = vec2(maxx + minx, maxy + miny) * -0.5;\n    gl_Position.xy -= mapping * vec2(maxx - minx, maxy - miny) * 0.5;\n    gl_Position.xy *= gl_Position.w;\n}\n\nconst mat4 D = mat4(\n    1.0, 0.0, 0.0, 0.0,\n    0.0, 1.0, 0.0, 0.0,\n    0.0, 0.0, 1.0, 0.0,\n    0.0, 0.0, 0.0, -1.0\n);\n\n/**\n * Compute point size and center using the technique described in:\n * \"GPU-Based Ray-Casting of Quadratic Surfaces\" http://dl.acm.org/citation.cfm?id=2386396\n * by Christian Sigg, Tim Weyrich, Mario Botsch, Markus Gross.\n */\nvoid quadraticProjection(const in vec3 position, const in float radius, const in vec2 mapping) {\n    vec2 xbc, ybc;\n\n    mat4 T = mat4(\n        radius, 0.0, 0.0, 0.0,\n        0.0, radius, 0.0, 0.0,\n        0.0, 0.0, radius, 0.0,\n        position.x, position.y, position.z, 1.0\n    );\n\n    mat4 R = transpose4(uProjection * uModelView * aTransform * T);\n    float A = dot(R[3], D * R[3]);\n    float B = -2.0 * dot(R[0], D * R[3]);\n    float C = dot(R[0], D * R[0]);\n    xbc[0] = (-B - sqrt(B * B - 4.0 * A * C)) / (2.0 * A);\n    xbc[1] = (-B + sqrt(B * B - 4.0 * A * C)) / (2.0 * A);\n    float sx = abs(xbc[0] - xbc[1]) * 0.5;\n\n    A = dot(R[3], D * R[3]);\n    B = -2.0 * dot(R[1], D * R[3]);\n    C = dot(R[1], D * R[1]);\n    ybc[0] = (-B - sqrt(B * B - 4.0 * A * C)) / (2.0 * A);\n    ybc[1] = (-B + sqrt(B * B - 4.0 * A * C)) / (2.0 * A);\n    float sy = abs(ybc[0] - ybc[1]) * 0.5;\n\n    gl_Position.xy = vec2(0.5 * (xbc.x + xbc.y), 0.5 * (ybc.x + ybc.y));\n    gl_Position.xy -= mapping * vec2(sx, sy);\n    gl_Position.xy *= gl_Position.w;\n}\n\nvoid main(void){\n    vec2 mapping = vec2(1.0, 1.0); // vertices 2 and 5\n    #if __VERSION__ == 100\n        int m = imod(VertexID, 6);\n    #else\n        int m = VertexID % 6;\n    #endif\n    if (m == 0) {\n        mapping = vec2(-1.0, 1.0);\n    } else if (m == 1 || m == 3) {\n        mapping = vec2(-1.0, -1.0);\n    } else if (m == 4) {\n        mapping = vec2(1.0, -1.0);\n    }\n\n    int vertexId = VertexID / 6;\n\n    vec4 positionGroup = readFromTexture(tPositionGroup, vertexId, uTexDim);\n    vec3 position = positionGroup.rgb;\n    float group = positionGroup.a;\n\n    #include assign_color_varying\n    #include assign_marker_varying\n    #include assign_clipping_varying\n    #include assign_size\n\n    vRadius = size * uModelScale;\n\n    vec4 position4 = vec4(position, 1.0);\n    vModelPosition = (uModel * aTransform * position4).xyz; // for clipping in frag shader\n\n    float d;\n    if (uLod.w != 0.0 && (uLod.x != 0.0 || uLod.y != 0.0)) {\n        if (uModelScale != 1.0) {\n            vRadius *= uLod.w;\n        } else {\n            d = (dot(uCameraPlane.xyz, vModelPosition) + uCameraPlane.w) / uModelScale;\n            float f = min(\n                smoothstep(uLod.x, uLod.x + uLod.z, d),\n                1.0 - smoothstep(uLod.y - uLod.z, uLod.y, d)\n            ) * uLod.w;\n            vRadius *= f;\n        }\n    }\n\n    vec4 mvPosition = uModelView * aTransform * position4;\n\n    #ifdef dApproximate\n        vec4 mvCorner = vec4(mvPosition.xyz, 1.0);\n        mvCorner.xy += mapping * vRadius;\n        gl_Position = uProjection * mvCorner;\n    #else\n        if (uIsOrtho == 1.0) {\n            vec4 mvCorner = vec4(mvPosition.xyz, 1.0);\n            mvCorner.xy += mapping * vRadius;\n            gl_Position = uProjection * mvCorner;\n        } else if (uIsAsymmetricProjection) {\n            gl_Position = uProjection * vec4(mvPosition.xyz, 1.0);\n            quadraticProjection(position, vRadius / uModelScale, mapping);\n        } else {\n            gl_Position = uProjection * vec4(mvPosition.xyz, 1.0);\n            sphereProjection(mvPosition.xyz, vRadius, mapping);\n        }\n    #endif\n\n    vec4 vPoint4 = uInvProjection * gl_Position;\n    vPoint = vPoint4.xyz / vPoint4.w;\n    vPointViewPosition = -mvPosition.xyz / mvPosition.w;\n\n    if (gl_Position.z < -gl_Position.w) {\n        mvPosition.z -= 2.0 * vRadius; // avoid clipping\n        gl_Position.z = (uProjection * vec4(mvPosition.xyz, 1.0)).z;\n    }\n\n    if (uModelScale == 1.0) {\n        if (uLod.w != 0.0 && (uLod.x != 0.0 || uLod.y != 0.0)) {\n            if (d < uLod.x || d > uLod.y) {\n                // move out of [ -w, +w ] to 'discard' in vert shader\n                gl_Position.z = 2.0 * gl_Position.w;\n            }\n        }\n    }\n\n    #if defined(dClipPrimitive) && !defined(dClipVariant_instance) && dClipObjectCount != 0\n        if (clipTest(vModelPosition / uModelScale)) {\n            // move out of [ -w, +w ] to 'discard' in vert shader\n            gl_Position.z = 2.0 * gl_Position.w;\n        }\n    #else\n        #include clip_instance\n    #endif\n}\n";
