/**
 * Custom GLSL shaders for the AIOrb effect.
 *
 * Uses Three.js ShaderMaterial conventions (GLSL 100-style syntax;
 * Three.js auto-converts to GLSL 300 es for WebGL2).
 *
 * Built-in uniforms/attributes provided by Three.js:
 *   modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix,
 *   normalMatrix, cameraPosition, position, normal, uv
 */
export declare const dotSphereVertex = "\nuniform float u_time;\n\nvarying vec3 vNormal;\nvarying vec3 vWorldPosition;\nvarying vec3 vViewDirection;\nvarying float vDisplacement;\n\n\nfloat hash(vec3 p) {\n    p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n    p += dot(p, p.yxz + 33.33);\n    return fract((p.x + p.y) * p.z);\n}\n\nfloat noise(vec3 x) {\n    vec3 i = floor(x);\n    vec3 f = fract(x);\n    f = f * f * (3.0 - 2.0 * f);\n\n    return mix(\n        mix(mix(hash(i + vec3(0,0,0)), hash(i + vec3(1,0,0)), f.x),\n            mix(hash(i + vec3(0,1,0)), hash(i + vec3(1,1,0)), f.x), f.y),\n        mix(mix(hash(i + vec3(0,0,1)), hash(i + vec3(1,0,1)), f.x),\n            mix(hash(i + vec3(0,1,1)), hash(i + vec3(1,1,1)), f.x), f.y),\n        f.z);\n}\n\n\nvoid main() {\n    // Multi-octave noise for organic surface displacement\n    float n1 = noise(normal * 1.8 + u_time * 0.8);\n    float n2 = noise(normal * 3.6 - u_time * 0.5) * 0.5;\n    float disp = (n1 + n2 - 0.75) * 0.15;\n\n    // Visible traveling wave across the surface\n    disp += sin(normal.x * 4.0 + u_time * 2.5) *\n            sin(normal.z * 4.0 + u_time * 1.8) * 0.06;\n\n    // Global breathing\n    disp += sin(u_time * 1.5) * 0.025;\n\n    vec3 newPos = position + normal * disp;\n    vDisplacement = disp;\n\n    vNormal = normalize(normalMatrix * normal);\n    vec4 worldPos = modelMatrix * vec4(newPos, 1.0);\n    vWorldPosition = worldPos.xyz;\n    vViewDirection = normalize(cameraPosition - worldPos.xyz);\n    gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos, 1.0);\n}\n";
export declare const dotSphereFragment = "\nprecision highp float;\n\nuniform float u_time;\nuniform vec3  u_color1;\nuniform vec3  u_color2;\nuniform vec3  u_color3;\nuniform float u_dotSize;\nuniform float u_gridDensity;\nuniform float u_rimIntensity;\n\nvarying vec3 vNormal;\nvarying vec3 vWorldPosition;\nvarying vec3 vViewDirection;\nvarying float vDisplacement;\n\nvoid main() {\n    vec3 N = normalize(vNormal);\n    vec3 V = normalize(vViewDirection);\n\n    // \u2500\u2500 Fresnel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    float NdotV   = max(dot(N, V), 0.0);\n    float fresnel = pow(1.0 - NdotV, 2.5);\n\n    // \u2500\u2500 Dot pattern on the sphere surface \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    vec3 pos = normalize(vWorldPosition);\n\n    // Multi-axis rotation so dots tumble in 3D, not just left-to-right\n    // Y-axis\n    float rY = u_time * 0.2;\n    float cY = cos(rY), sY = sin(rY);\n    vec3 rotPos = vec3(\n        pos.x * cY - pos.z * sY,\n        pos.y,\n        pos.x * sY + pos.z * cY\n    );\n    // X-axis (tilt)\n    float rX = u_time * 0.13;\n    float cX = cos(rX), sX = sin(rX);\n    rotPos = vec3(\n        rotPos.x,\n        rotPos.y * cX - rotPos.z * sX,\n        rotPos.y * sX + rotPos.z * cX\n    );\n    // Z-axis (slow roll)\n    float rZ = u_time * 0.08;\n    float cZ = cos(rZ), sZ = sin(rZ);\n    rotPos = vec3(\n        rotPos.x * cZ - rotPos.y * sZ,\n        rotPos.x * sZ + rotPos.y * cZ,\n        rotPos.z\n    );\n\n    float theta    = acos(clamp(rotPos.y, -1.0, 1.0));\n    float phi      = atan(rotPos.z, rotPos.x);\n    float sinTheta = sin(theta);\n\n    float latGrid = theta * u_gridDensity / 3.14159265;\n    float lonGrid = phi  * u_gridDensity * max(sinTheta, 0.15) / 3.14159265;\n\n    vec2  cell    = fract(vec2(latGrid, lonGrid));\n    float dotDist = length(cell - 0.5);\n\n    // Dots react to surface displacement \u2013 swell on peaks, shrink in valleys\n    float dispInfluence = smoothstep(-0.05, 0.15, vDisplacement);\n    float pulse = 0.75 + dispInfluence * 0.5\n                + sin(u_time * 1.5 + theta * 3.0 + phi * 2.0) * 0.15;\n    float adjustedDotSize = u_dotSize * pulse;\n    // Sharper edge for more visible dots\n    float dotMask = 1.0 - smoothstep(adjustedDotSize - 0.008, adjustedDotSize + 0.008, dotDist);\n\n    // \u2500\u2500 Multi-colour rim based on normal direction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    float cAngle = u_time * 0.35;\n    float cc = cos(cAngle), sc = sin(cAngle);\n    vec3 colorDir = vec3(\n        N.x * cc - N.z * sc,\n        N.y,\n        N.x * sc + N.z * cc\n    );\n\n    float vert = colorDir.y * 0.5 + 0.5;\n    vec3  rimColor = mix(u_color3, u_color1, vert);\n    float midW     = 1.0 - abs(vert - 0.5) * 2.0;\n    rimColor = mix(rimColor, u_color2, midW * 0.6);\n\n    // \u2500\u2500 Compose \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    // Dots: bright coloured points with hot white core\n    vec3  dotColor  = rimColor * 2.0 + vec3(0.2);\n    float dotBright = dotMask * 0.85;\n\n    // Rim glow (independent of dots \u2013 visible at edges)\n    float rimGlow   = pow(fresnel, 1.5) * u_rimIntensity;\n    vec3  glowColor = rimColor * rimGlow;\n\n    vec3  col   = dotColor * dotBright + glowColor;\n    // Between dots: transparent \u2192 waves show through; on dots: near-opaque\n    float alpha = max(dotBright, pow(fresnel, 1.0) * 0.7);\n\n    gl_FragColor = vec4(col, alpha);\n}\n";
export declare const waveVertex = "\nuniform float u_time;\nuniform float u_flowSpeed;\n\nvarying vec3 vNormal;\nvarying vec3 vWorldPosition;\nvarying vec3 vViewDirection;\n\n\nfloat hash(vec3 p) {\n    p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n    p += dot(p, p.yxz + 33.33);\n    return fract((p.x + p.y) * p.z);\n}\n\nfloat noise(vec3 x) {\n    vec3 i = floor(x);\n    vec3 f = fract(x);\n    f = f * f * (3.0 - 2.0 * f);\n\n    return mix(\n        mix(mix(hash(i + vec3(0,0,0)), hash(i + vec3(1,0,0)), f.x),\n            mix(hash(i + vec3(0,1,0)), hash(i + vec3(1,1,0)), f.x), f.y),\n        mix(mix(hash(i + vec3(0,0,1)), hash(i + vec3(1,0,1)), f.x),\n            mix(hash(i + vec3(0,1,1)), hash(i + vec3(1,1,1)), f.x), f.y),\n        f.z);\n}\n\n\nvoid main() {\n    // Organic displacement matching the outer dot sphere deformation\n    float t = u_time * 0.8;\n    float n1 = noise(normal * 1.8 + t);\n    float n2 = noise(normal * 3.6 - t * 0.625) * 0.5;\n    float disp = (n1 + n2 - 0.75) * 0.15;\n    disp += sin(normal.x * 4.0 + t * 3.125) *\n            sin(normal.z * 4.0 + t * 2.25) * 0.06;\n    disp += sin(t * 1.875) * 0.025;\n\n    vec3 newPos = position + normal * disp;\n\n    vNormal = normalize(normalMatrix * normal);\n    vec4 worldPos = modelMatrix * vec4(newPos, 1.0);\n    vWorldPosition = worldPos.xyz;\n    vViewDirection = normalize(cameraPosition - worldPos.xyz);\n    gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos, 1.0);\n}\n";
export declare const waveFragment = "\nprecision highp float;\n\nuniform float u_time;\nuniform vec3  u_color1;\nuniform vec3  u_color2;\nuniform vec3  u_color3;\nuniform float u_intensity;\nuniform float u_noiseScale;\nuniform float u_flowSpeed;\n\nvarying vec3 vNormal;\nvarying vec3 vWorldPosition;\nvarying vec3 vViewDirection;\n\n\nfloat hash(vec3 p) {\n    p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n    p += dot(p, p.yxz + 33.33);\n    return fract((p.x + p.y) * p.z);\n}\n\nfloat noise(vec3 x) {\n    vec3 i = floor(x);\n    vec3 f = fract(x);\n    f = f * f * (3.0 - 2.0 * f);\n\n    return mix(\n        mix(mix(hash(i + vec3(0,0,0)), hash(i + vec3(1,0,0)), f.x),\n            mix(hash(i + vec3(0,1,0)), hash(i + vec3(1,1,0)), f.x), f.y),\n        mix(mix(hash(i + vec3(0,0,1)), hash(i + vec3(1,0,1)), f.x),\n            mix(hash(i + vec3(0,1,1)), hash(i + vec3(1,1,1)), f.x), f.y),\n        f.z);\n}\n\n\nvoid main() {\n    vec3 N = normalize(vNormal);\n    vec3 V = normalize(vViewDirection);\n    vec3 pos = normalize(vWorldPosition);\n\n    float t = u_time * u_flowSpeed;\n\n    // \u2500\u2500 Three overlapping soft wave layers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    // Layer 1 \u2013 large blobs, clearly moving\n    vec3 flow1 = vec3(sin(t * 0.8), cos(t * 0.6), sin(t * 0.5)) * 0.8;\n    float w1 = noise(pos * u_noiseScale + flow1);\n    w1 = smoothstep(0.2, 0.8, w1);\n\n    // Layer 2 \u2013 medium detail, different axis\n    vec3 flow2 = vec3(cos(t * 0.7), sin(t * 0.9), cos(t * 0.6)) * 0.7;\n    float w2 = noise(pos * u_noiseScale * 1.6 + flow2 + 100.0);\n    w2 = smoothstep(0.25, 0.75, w2);\n\n    // Layer 3 \u2013 faster, finer detail\n    vec3 flow3 = vec3(sin(t * 1.1), cos(t * 0.8), sin(t * 1.2)) * 0.6;\n    float w3 = noise(pos * u_noiseScale * 2.8 + flow3 + 200.0);\n    w3 = smoothstep(0.3, 0.7, w3);\n\n    // \u2500\u2500 Colour each layer \u2013 bright and glowing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    vec3 col = u_color1 * w1 * 0.8\n             + u_color2 * w2 * 0.6\n             + u_color3 * w3 * 0.5;\n\n    // Vertical base wash\n    float yGrad = pos.y * 0.5 + 0.5;\n    col += mix(u_color3, u_color1, yGrad) * 0.15;\n\n    // \u2500\u2500 Edge fade \u2013 glowing centre, soft feathered rim \u2500\u2500\u2500\u2500\n    float NdotV = max(dot(N, V), 0.0);\n    float centerFade = smoothstep(0.0, 0.55, NdotV);\n\n    col *= u_intensity;\n    float alpha = centerFade * 0.85;\n\n    gl_FragColor = vec4(col, alpha);\n}\n";
export declare const glowVertex = "\nvarying vec3 vNormal;\nvarying vec3 vViewDirection;\n\nvoid main() {\n    vNormal = normalize(normalMatrix * normal);\n    vec4 worldPos = modelMatrix * vec4(position, 1.0);\n    vViewDirection = normalize(cameraPosition - worldPos.xyz);\n    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n";
export declare const glowFragment = "\nprecision highp float;\n\nuniform float u_time;\nuniform vec3  u_color1;\nuniform vec3  u_color2;\nuniform vec3  u_color3;\nuniform float u_intensity;\nuniform float u_falloff;\n\nvarying vec3 vNormal;\nvarying vec3 vViewDirection;\n\nvoid main() {\n    vec3 N = normalize(vNormal);\n    vec3 V = normalize(vViewDirection);\n\n    float NdotV   = max(dot(N, V), 0.0);\n    float fresnel = pow(1.0 - NdotV, u_falloff);\n\n    // Rotate colour mapping\n    float a  = u_time * 0.35;\n    float ca = cos(a), sa = sin(a);\n    vec3 dir = vec3(\n        N.x * ca - N.z * sa,\n        N.y,\n        N.x * sa + N.z * ca\n    );\n\n    float vert = dir.y * 0.5 + 0.5;\n    vec3  col  = mix(u_color3, u_color1, vert);\n    float midW = 1.0 - abs(vert - 0.5) * 2.0;\n    col = mix(col, u_color2, midW * 0.6);\n\n    // Subtle glow pulsing\n    float pulse = 0.88 + sin(u_time * 1.0) * 0.12;\n    float alpha = fresnel * u_intensity * pulse;\n\n    gl_FragColor = vec4(col * alpha, alpha);\n}\n";
