◆ UI Codesempai

Bioelectric consciousness engine

A bioelectric consciousness engine built with Three.js, webgl and glsl. Click anywhere to trigger signals; the HUD tracks live neural state.

Category

3D & WebGL

Tech

Three.jsWebGLGlassmorphism

Tags

#particles#bloom#hud#interactive#sci-fi

Download

70.6 KB zip

Source code

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <title>Bioelectric consciousness engine</title>
    

  </head>
    
  <body>
  <style>
    :root {
        --cyan: #00f0ff;
        --gold: #ffaa00;
        --magenta: #ff00aa;
        --bg-dark: #010204;
        --glass-bg: linear-gradient(135deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.07) 45%, rgba(0, 240, 255, 0.08));
        --glass-border: rgba(255, 255, 255, 0.24);
        --glass-highlight: rgba(255, 255, 255, 0.42);
    }

    body, html {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 100%;
        background-color: var(--bg-dark);
        overflow: hidden;
        font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        color: white;
        user-select: none;
    }

    canvas {
        display: block;
        width: 100vw;
        height: 100vh;
        position: absolute;
        top: 0;
        left: 0;
        z-index: 1;
    }

    .overlay {
        position: absolute;
        top: 0; left: 0; width: 100%; height: 100%;
        pointer-events: none;
        z-index: 10;
        background: 
            radial-gradient(circle at center, transparent 40%, rgba(0, 0, 0, 0.85) 100%),
            repeating-linear-gradient(0deg, rgba(0,0,0,0.15) 0px, rgba(0,0,0,0.15) 1px, transparent 1px, transparent 2px);
        box-shadow: inset 0 0 100px rgba(0,0,0,0.9);
    }

    .hud-panel {
        position: absolute;
        z-index: 20;
        background: var(--glass-bg);
        border: 1px solid var(--glass-border);
        border-radius: 18px;
        backdrop-filter: blur(28px) saturate(170%);
        -webkit-backdrop-filter: blur(28px) saturate(170%);
        box-shadow:
            0 18px 45px rgba(0, 0, 0, 0.38),
            inset 0 1px 0 var(--glass-highlight),
            inset 0 -1px 0 rgba(255, 255, 255, 0.08);
        transition: all 0.3s ease;
        pointer-events: auto;
        overflow: hidden;
    }

    #hud-left {
        top: clamp(12px, 3vw, 28px);
        left: clamp(12px, 3vw, 28px);
        padding: 14px;
        width: min(230px, calc(100vw - 24px));
    }

    #hud-right {
        bottom: clamp(12px, 3vw, 28px);
        right: clamp(12px, 3vw, 28px);
        padding: 10px 14px;
        min-width: 130px;
        text-align: right;
    }

    .hud-header {
        border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        padding-bottom: 8px;
        margin-bottom: 10px;
    }

    h1 {
        font-size: 11px;
        letter-spacing: 2.6px;
        color: var(--cyan);
        margin: 0 0 4px 0;
        font-weight: 700;
        text-transform: uppercase;
        text-shadow: 0 0 10px rgba(0, 240, 255, 0.4);
    }

    .subtitle {
        font-size: 8px;
        color: rgba(255, 255, 255, 0.4);
        letter-spacing: 1.4px;
    }

    .hud-row {
        display: flex;
        justify-content: space-between;
        gap: 18px;
        margin-bottom: 8px;
        font-size: 9px;
        letter-spacing: 0.8px;
    }

    .hud-label {
        color: rgba(255, 255, 255, 0.5);
        text-transform: uppercase;
    }

    .hud-value {
        font-weight: 600;
        color: var(--cyan);
        text-shadow: 0 0 8px rgba(0, 240, 255, 0.5);
        transition: color 0.3s, text-shadow 0.3s;
        font-variant-numeric: tabular-nums;
    }

    .value-active { color: var(--gold); text-shadow: 0 0 10px rgba(255, 170, 0, 0.6); }
    .value-refract { color: var(--magenta); text-shadow: 0 0 10px rgba(255, 0, 170, 0.6); }

    .btn-trigger {
        margin-top: 12px;
        width: 100%;
        padding: 9px 10px;
        background: rgba(255, 255, 255, 0.1);
        border: 1px solid rgba(255, 255, 255, 0.24);
        color: var(--cyan);
        font-size: 9px;
        letter-spacing: 2px;
        border-radius: 999px;
        cursor: pointer;
        text-transform: uppercase;
        transition: all 0.2s;
        box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 15px rgba(0, 240, 255, 0.1);
    }

    .btn-trigger:hover {
        background: rgba(0, 240, 255, 0.15);
        box-shadow: 0 0 20px rgba(0, 240, 255, 0.4);
    }

    .btn-trigger.disabled {
        border-color: rgba(255,255,255,0.1);
        color: rgba(255,255,255,0.3);
        background: transparent;
        box-shadow: none;
        cursor: not-allowed;
    }

    #instructions {
        position: absolute;
        bottom: clamp(14px, 4vw, 40px); left: 50%;
        transform: translateX(-50%);
        z-index: 20;
        font-size: 9px;
        letter-spacing: 1.6px;
        color: rgba(255,255,255,0.4);
        pointer-events: none;
        text-transform: uppercase;
        animation: pulseText 2s infinite;
        white-space: nowrap;
    }

    @keyframes pulseText {
        0%, 100% { opacity: 0.3; }
        50% { opacity: 0.8; }
    }

    #cursor {
        position: fixed;
        top: 0; left: 0;
        width: 24px; height: 24px;
        border: 1px solid rgba(0, 240, 255, 0.8);
        border-radius: 50%;
        transform: translate(-50%, -50%);
        pointer-events: none;
        z-index: 9999;
        transition: width 0.2s, height 0.2s, background 0.2s;
        mix-blend-mode: screen;
        box-shadow: 0 0 10px rgba(0,240,255,0.4);
    }
    #cursor.click {
        width: 12px; height: 12px;
        background: var(--cyan);
        border-color: transparent;
    }

    #loader {
        position: absolute;
        top: 0; left: 0; width: 100%; height: 100%;
        background: var(--bg-dark);
        z-index: 9000;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        transition: opacity 1s ease;
    }
    .spinner {
        width: 50px; height: 50px;
        border: 2px solid rgba(0,240,255,0.1);
        border-top-color: var(--cyan);
        border-radius: 50%;
        animation: spin 1s cubic-bezier(0.4, 0, 0.2, 1) infinite;
        margin-bottom: 24px;
        box-shadow: 0 0 20px rgba(0,240,255,0.2);
    }
    @keyframes spin { 100% { transform: rotate(360deg); } }

    @media (max-width: 720px) {
        .overlay {
            background:
                radial-gradient(circle at center, transparent 52%, rgba(0, 0, 0, 0.78) 100%),
                repeating-linear-gradient(0deg, rgba(0,0,0,0.12) 0px, rgba(0,0,0,0.12) 1px, transparent 1px, transparent 2px);
            box-shadow: inset 0 0 60px rgba(0,0,0,0.82);
        }

        #hud-left {
            top: max(10px, env(safe-area-inset-top));
            left: 10px;
            right: auto;
            width: min(220px, calc(100vw - 20px));
            padding: 8px 9px;
            border-radius: 13px;
        }

        #hud-right {
            right: 10px;
            bottom: max(54px, env(safe-area-inset-bottom));
            padding: 8px 10px;
            min-width: 112px;
        }

        .hud-header {
            display: flex;
            align-items: baseline;
            justify-content: space-between;
            gap: 8px;
            padding-bottom: 5px;
            margin-bottom: 6px;
        }

        h1 {
            font-size: 9px;
            letter-spacing: 1.5px;
            margin-bottom: 0;
        }

        .subtitle {
            font-size: 6px;
            letter-spacing: 0.7px;
            text-align: right;
        }

        .hud-row {
            gap: 10px;
            margin-bottom: 4px;
            font-size: 7px;
            letter-spacing: 0.55px;
        }

        .btn-trigger {
            margin-top: 6px;
            padding: 6px 8px;
            font-size: 7px;
            letter-spacing: 1.2px;
        }

        #instructions {
            bottom: max(16px, env(safe-area-inset-bottom));
            font-size: 8px;
            letter-spacing: 1.1px;
        }

        #cursor {
            display: none;
        }
    }

    @media (max-width: 420px) {
        #hud-left {
            display: grid;
            grid-template-columns: 1fr 1fr;
            column-gap: 10px;
            row-gap: 0;
            width: min(236px, calc(100vw - 16px));
            left: 8px;
            top: max(8px, env(safe-area-inset-top));
            padding: 7px 8px;
        }

        .hud-header,
        .btn-trigger {
            grid-column: 1 / -1;
        }

        .hud-header {
            display: block;
        }

        .subtitle {
            display: none;
        }

        .hud-row {
            gap: 6px;
            margin-bottom: 4px;
        }

        .hud-label {
            max-width: 60px;
        }
    }
</style>

<script type="importmap">
    {
        "imports": {
            "three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js",
            "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/"
        }
    }
</script>

<div class="overlay"></div>
<div id="cursor"></div>

<div id="loader">
    <div class="spinner"></div>
    <h1 style="color: rgba(255,255,255,0.6); font-size: 11px;">INITIALIZING BIOELECTRIC ENGINE</h1>
</div>

<div id="hud-left" class="hud-panel">
    <div class="hud-header">
        <h1>Neural Cathedral</h1>
        <div class="subtitle">ID: NC-09 // BIOELECTRIC ENGINE</div>
    </div>
    <div class="hud-row">
        <span class="hud-label">Membrane V</span>
        <span class="hud-value" id="val-membrane">-70.0 mV</span>
    </div>
    <div class="hud-row">
        <span class="hud-label">Dendrite State</span>
        <span class="hud-value" id="val-dendrites">CALM</span>
    </div>
    <div class="hud-row">
        <span class="hud-label">Axon Load</span>
        <span class="hud-value" id="val-axon">02%</span>
    </div>
    <div class="hud-row">
        <span class="hud-label">Signal Phase</span>
        <span class="hud-value" id="val-state">RESTING</span>
    </div>
    <div class="hud-row">
        <span class="hud-label">Synaptic Coh</span>
        <span class="hud-value" id="val-sync">24%</span>
    </div>
    
    <button class="btn-trigger" id="btn-fire">Manual Override</button>
</div>

<div id="hud-right" class="hud-panel">
    <div class="hud-row">
        <span class="hud-label">Cam X</span>
        <span class="hud-value" id="val-cam-x">0.00</span>
    </div>
    <div class="hud-row">
        <span class="hud-label">Cam Y</span>
        <span class="hud-value" id="val-cam-y">0.00</span>
    </div>
    <div class="hud-row">
        <span class="hud-label">Cam Z</span>
        <span class="hud-value" id="val-cam-z">0.00</span>
    </div>
</div>

<div id="instructions">Click anywhere to trigger impulse</div>

<script type="module">
    import * as THREE from 'three';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
    import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
    import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
    import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';

    const cursor = document.getElementById('cursor');
    document.addEventListener('mousemove', (e) => {
        cursor.style.left = e.clientX + 'px';
        cursor.style.top = e.clientY + 'px';
    });
    document.addEventListener('mousedown', () => cursor.classList.add('click'));
    document.addEventListener('mouseup', () => cursor.classList.remove('click'));

    const shaderNoise = `
        vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
        vec4 mod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
        vec4 permute(vec4 x) { return mod289(((x*34.0)+1.0)*x); }
        vec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }
        float snoise(vec3 v) {
            const vec2  C = vec2(1.0/6.0, 1.0/3.0) ;
            const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);
            vec3 i  = floor(v + dot(v, C.yyy) );
            vec3 x0 = v - i + dot(i, C.xxx) ;
            vec3 g = step(x0.yzx, x0.xyz);
            vec3 l = 1.0 - g;
            vec3 i1 = min( g.xyz, l.zxy );
            vec3 i2 = max( g.xyz, l.zxy );
            vec3 x1 = x0 - i1 + C.xxx;
            vec3 x2 = x0 - i2 + C.yyy;
            vec3 x3 = x0 - D.yyy;
            i = mod289(i);
            vec4 p = permute( permute( permute(
                        i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
                    + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
                    + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
            float n_ = 0.142857142857;
            vec3  ns = n_ * D.wyz - D.xzx;
            vec4 j = p - 49.0 * floor(p * ns.z * ns.z);
            vec4 x_ = floor(j * ns.z);
            vec4 y_ = floor(j - 7.0 * x_ );
            vec4 x = x_ *ns.x + ns.yyyy;
            vec4 y = y_ *ns.x + ns.yyyy;
            vec4 h = 1.0 - abs(x) - abs(y);
            vec4 b0 = vec4( x.xy, y.xy );
            vec4 b1 = vec4( x.zw, y.zw );
            vec4 s0 = floor(b0)*2.0 + 1.0;
            vec4 s1 = floor(b1)*2.0 + 1.0;
            vec4 sh = -step(h, vec4(0.0));
            vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
            vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
            vec3 p0 = vec3(a0.xy,h.x);
            vec3 p1 = vec3(a0.zw,h.y);
            vec3 p2 = vec3(a1.xy,h.z);
            vec3 p3 = vec3(a1.zw,h.w);
            vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
            p0 *= norm.x;
            p1 *= norm.y;
            p2 *= norm.z;
            p3 *= norm.w;
            vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
            m = m * m;
            return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) );
        }
    `;

    const CONFIG = {
        somaRadius: 4.0,
        dendriteTrees: 14,
        axonTrees: 4,
        maxDistDendrite: 35.0,
        maxDistAxon: 50.0,
        colors: {
            cyan: new THREE.Color('#00e5ff'),
            blue: new THREE.Color('#0033aa'),
            gold: new THREE.Color('#ffaa00'),
            orange: new THREE.Color('#ff4400'),
            magenta: new THREE.Color('#ff0066'),
            violet: new THREE.Color('#6600ff')
        }
    };

    const STATE = {
        phase: 0,
        progress: 0,
        membraneV: -70.0,
        axonLoad: 2,
        sync: 24,
        isAnimating: false
    };

    const uniforms = {
        uTime: { value: 0 },
        uPhase: { value: 0 },
        uProgress: { value: 0 },
        uColCyan: { value: CONFIG.colors.cyan },
        uColBlue: { value: CONFIG.colors.blue },
        uColGold: { value: CONFIG.colors.gold },
        uColOrange: { value: CONFIG.colors.orange },
        uColMagenta: { value: CONFIG.colors.magenta },
        uColViolet: { value: CONFIG.colors.violet },
        uSomaRadius: { value: CONFIG.somaRadius },
        uMaxDistDendrite: { value: CONFIG.maxDistDendrite },
        uMaxDistAxon: { value: CONFIG.maxDistAxon }
    };

    const scene = new THREE.Scene();
    scene.fog = new THREE.FogExp2(0x010204, 0.015);

    const desktopCameraPosition = new THREE.Vector3(30, 20, 40);
    const mobileCameraPosition = new THREE.Vector3(34, 24, 62);

    const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 500);
    camera.position.copy(desktopCameraPosition);

    const renderer = new THREE.WebGLRenderer({ antialias: false, powerPreference: "high-performance" });
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1.2;
    document.body.appendChild(renderer.domElement);

    const composer = new EffectComposer(renderer);
    const renderPass = new RenderPass(scene, camera);
    composer.addPass(renderPass);
    
    const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.8, 0.6, 0.1);
    composer.addPass(bloomPass);

    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.04;
    controls.autoRotate = true;
    controls.autoRotateSpeed = 0.6;
    controls.enablePan = false;
    controls.minDistance = 15;
    controls.maxDistance = 120;

    function isCompactViewport() {
        return window.innerWidth <= 720 || window.matchMedia('(pointer: coarse)').matches;
    }

    function applyResponsiveScene(resetCamera = false) {
        const width = window.innerWidth;
        const height = window.innerHeight;
        const compact = isCompactViewport();
        const targetPosition = compact ? mobileCameraPosition : desktopCameraPosition;

        camera.aspect = width / height;
        camera.fov = compact ? 52 : 45;
        camera.updateProjectionMatrix();

        renderer.setPixelRatio(Math.min(window.devicePixelRatio, compact ? 1.5 : 2));
        renderer.setSize(width, height, false);
        composer.setSize(width, height);

        controls.minDistance = compact ? 24 : 15;
        controls.maxDistance = compact ? 140 : 120;

        if (resetCamera) {
            camera.position.copy(targetPosition);
        } else if (compact && camera.position.length() < targetPosition.length() * 0.8) {
            camera.position.setLength(targetPosition.length());
        }

        controls.update();
    }

    applyResponsiveScene(true);

    const somaMaterial = new THREE.ShaderMaterial({
        uniforms: uniforms,
        transparent: true,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        side: THREE.DoubleSide,
        vertexShader: `
            ${shaderNoise}
            uniform float uTime;
            uniform int uPhase;
            uniform float uProgress;
            
            varying vec3 vNormal;
            varying vec3 vViewPosition;
            varying float vNoise;

            void main() {
                vec3 pos = position;
                float noise = snoise(pos * 0.5 + uTime * 0.3) * 0.5;
                float burst = 0.0;
                if(uPhase == 2) {
                    burst = sin(uProgress * 3.14159) * 0.4;
                }
                pos += normal * (noise + burst);
                vNoise = noise;
                vNormal = normalize(normalMatrix * normal);
                vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
                vViewPosition = -mvPosition.xyz;
                gl_Position = projectionMatrix * mvPosition;
            }
        `,
        fragmentShader: `
            uniform int uPhase;
            uniform float uProgress;
            uniform float uTime;
            
            uniform vec3 uColCyan;
            uniform vec3 uColBlue;
            uniform vec3 uColGold;
            uniform vec3 uColMagenta;

            varying vec3 vNormal;
            varying vec3 vViewPosition;
            varying float vNoise;

            void main() {
                vec3 normal = normalize(vNormal);
                vec3 viewDir = normalize(vViewPosition);
                float fresnel = pow(1.0 - max(dot(normal, viewDir), 0.0), 2.5);
                vec3 color = mix(uColBlue * 0.2, uColCyan, fresnel);
                color += uColCyan * (vNoise * 0.5 + 0.5) * 0.3;
                if(uPhase == 2) {
                    float intensity = sin(uProgress * 3.14159);
                    color = mix(color, uColGold * 2.0 + uColCyan, intensity * fresnel * 2.0);
                    color += uColGold * intensity * (1.0 - fresnel);
                } else if(uPhase == 4) {
                    float intensity = 1.0 - uProgress;
                    color = mix(color, uColMagenta, intensity * fresnel * 1.5);
                }
                gl_FragColor = vec4(color, 0.8 * fresnel + 0.2);
            }
        `
    });

    const branchMaterial = new THREE.ShaderMaterial({
        uniforms: Object.assign({}, uniforms, { uIsAxon: { value: 0 } }),
        transparent: true,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        vertexShader: `
            ${shaderNoise}
            uniform float uTime;
            varying vec3 vWorldPos;
            varying vec3 vNormal;
            varying vec3 vViewPosition;
            varying vec2 vUv;

            void main() {
                vUv = uv;
                vec3 pos = position;
                float wiggle = snoise(pos * 0.2 + uTime * 0.5) * 0.1;
                pos += normal * wiggle;
                vec4 worldPosition = modelMatrix * vec4(pos, 1.0);
                vWorldPos = worldPosition.xyz;
                vNormal = normalize(normalMatrix * normal);
                vec4 mvPosition = viewMatrix * worldPosition;
                vViewPosition = -mvPosition.xyz;
                gl_Position = projectionMatrix * mvPosition;
            }
        `,
        fragmentShader: `
            ${shaderNoise}
            uniform float uTime;
            uniform int uPhase;
            uniform float uProgress;
            uniform int uIsAxon;
            
            uniform vec3 uColCyan;
            uniform vec3 uColBlue;
            uniform vec3 uColGold;
            uniform vec3 uColOrange;
            uniform vec3 uColMagenta;
            uniform vec3 uColViolet;
            
            uniform float uSomaRadius;
            uniform float uMaxDistDendrite;
            uniform float uMaxDistAxon;

            varying vec3 vWorldPos;
            varying vec3 vNormal;
            varying vec3 vViewPosition;
            varying vec2 vUv;

            void main() {
                vec3 normal = normalize(vNormal);
                vec3 viewDir = normalize(vViewPosition);
                float edge = pow(1.0 - abs(vUv.y - 0.5) * 2.0, 2.0); 
                float fresnel = pow(1.0 - max(dot(normal, viewDir), 0.0), 2.0);
                float dist = length(vWorldPos);
                vec3 baseColor = mix(uColBlue * 0.1, uColCyan * 0.5, fresnel * edge);
                vec3 pulseColor = vec3(0.0);
                float flowNoise = snoise(vec3(vUv.x * 20.0 - uTime * 2.0, vUv.y * 10.0, uTime)) * 0.5 + 0.5;
                float axialFlow = 0.65 + 0.35 * sin(vUv.x * 34.0 - uTime * 8.0);
                if (uIsAxon == 0) {
                    if (uPhase == 1) {
                        float currentWaveDist = mix(uMaxDistDendrite, uSomaRadius, uProgress);
                        float head = 1.0 - smoothstep(0.0, 2.3, abs(dist - currentWaveDist));
                        float outerTrail = step(currentWaveDist, dist) * exp(-(dist - currentWaveDist) * 0.18);
                        float mergeGlow = (1.0 - smoothstep(uSomaRadius, uSomaRadius + 8.0, dist)) * smoothstep(0.65, 1.0, uProgress);
                        float pulse = max(head * 1.6, outerTrail * 0.65) + mergeGlow * 0.8;
                        pulseColor = uColGold * pulse * flowNoise * axialFlow * 3.2;
                    }
                } else {
                    if (uPhase == 3) {
                        float currentWaveDist = mix(uSomaRadius, uMaxDistAxon + 18.0, uProgress);
                        float head = 1.0 - smoothstep(0.0, 3.4, abs(dist - currentWaveDist));
                        float innerTrail = step(dist, currentWaveDist) * exp(-(currentWaveDist - dist) * 0.1);
                        float somaLaunch = (1.0 - smoothstep(uSomaRadius, uSomaRadius + 7.0, dist)) * (1.0 - smoothstep(0.0, 0.28, uProgress));
                        float pulse = max(head * 2.0, innerTrail * 0.9) + somaLaunch * 1.2;
                        pulseColor = (uColOrange + uColGold * 0.45) * pulse * flowNoise * axialFlow * 4.6;
                    }
                }
                if (uPhase == 4) {
                    float intensity = 1.0 - uProgress;
                    pulseColor += uColViolet * intensity * edge * 1.5;
                }
                gl_FragColor = vec4(baseColor + pulseColor, 1.0);
            }
        `
    });

    const axonMaterial = branchMaterial.clone();
    Object.keys(uniforms).forEach((key) => {
        axonMaterial.uniforms[key] = uniforms[key];
    });
    axonMaterial.uniforms.uIsAxon = { value: 1 };

    const networkGroup = new THREE.Group();
    scene.add(networkGroup);

    const somaGeo = new THREE.IcosahedronGeometry(CONFIG.somaRadius, 32);
    const somaMesh = new THREE.Mesh(somaGeo, somaMaterial);
    networkGroup.add(somaMesh);
    
    const coreGeo = new THREE.IcosahedronGeometry(CONFIG.somaRadius * 0.8, 16);
    const coreMat = new THREE.MeshBasicMaterial({ color: CONFIG.colors.cyan, transparent: true, opacity: 0.1, blending: THREE.AdditiveBlending, wireframe: true });
    networkGroup.add(new THREE.Mesh(coreGeo, coreMat));

    function buildBranch(startPt, dir, length, radius, level, maxLevels, isAxon) {
        const segments = 12;
        const points = [startPt.clone()];
        let cur = startPt.clone();
        let cDir = dir.clone();

        for(let i=0; i<segments; i++) {
            let curl = new THREE.Vector3(
                Math.random() - 0.5,
                Math.random() - 0.5,
                Math.random() - 0.5
            ).multiplyScalar(isAxon ? 0.3 : 0.8);
            cDir.add(curl).normalize();
            cur.add(cDir.clone().multiplyScalar(length / segments));
            points.push(cur.clone());
        }

        const curve = new THREE.CatmullRomCurve3(points);
        const tubeGeo = new THREE.TubeGeometry(curve, segments * 2, radius, 6, false);
        const mesh = new THREE.Mesh(tubeGeo, isAxon ? axonMaterial : branchMaterial);
        networkGroup.add(mesh);

        if (level < maxLevels) {
            const childCount = isAxon ? (Math.random() > 0.3 ? 1 : 2) : (Math.random() > 0.2 ? 2 : 3);
            for(let j=0; j<childCount; j++) {
                let splitDir = cDir.clone().add(new THREE.Vector3(
                    Math.random()-0.5, Math.random()-0.5, Math.random()-0.5
                ).multiplyScalar(0.8)).normalize();
                
                buildBranch(
                    cur, 
                    splitDir, 
                    length * (0.6 + Math.random()*0.3), 
                    radius * 0.65, 
                    level + 1, 
                    maxLevels, 
                    isAxon
                );
            }
        } else {
            addSynapse(cur);
        }
    }

    const synapsePositions = [];
    function addSynapse(pos) {
        synapsePositions.push(pos.x, pos.y, pos.z);
    }

    for(let i=0; i<CONFIG.dendriteTrees; i++) {
        let dir = new THREE.Vector3(Math.random()-0.5, Math.random()-0.5, Math.random()-0.5).normalize();
        if (dir.z > 0.3) dir.z -= 0.8;
        dir.normalize();
        let start = dir.clone().multiplyScalar(CONFIG.somaRadius - 0.5);
        buildBranch(start, dir, 12 + Math.random()*5, 0.4, 0, 2, false);
    }

    for(let i=0; i<CONFIG.axonTrees; i++) {
        let dir = new THREE.Vector3((Math.random()-0.5)*0.5, (Math.random()-0.5)*0.5, 1.0).normalize();
        let start = dir.clone().multiplyScalar(CONFIG.somaRadius - 0.5);
        buildBranch(start, dir, 25 + Math.random()*10, 0.6, 0, 2, true);
    }

    const synGeo = new THREE.BufferGeometry();
    synGeo.setAttribute('position', new THREE.Float32BufferAttribute(synapsePositions, 3));
    
    const synSizes = new Float32Array(synapsePositions.length / 3);
    for(let i=0; i<synSizes.length; i++) synSizes[i] = Math.random();
    synGeo.setAttribute('aSize', new THREE.BufferAttribute(synSizes, 1));

    const synMat = new THREE.ShaderMaterial({
        uniforms: uniforms,
        transparent: true,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        vertexShader: `
            attribute float aSize;
            uniform float uTime;
            varying float vSize;
            void main() {
                vSize = aSize;
                vec3 pos = position;
                pos.y += sin(uTime * 2.0 + pos.x) * 0.5;
                vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
                gl_PointSize = (20.0 + aSize * 15.0) * (100.0 / -mvPosition.z);
                gl_Position = projectionMatrix * mvPosition;
            }
        `,
        fragmentShader: `
            uniform int uPhase;
            uniform float uProgress;
            uniform vec3 uColCyan;
            uniform vec3 uColGold;
            uniform vec3 uColMagenta;
            varying float vSize;
            
            void main() {
                vec2 coord = gl_PointCoord - vec2(0.5);
                float dist = length(coord);
                if (dist > 0.5) discard;
                float alpha = (0.5 - dist) * 2.0;
                vec3 color = uColCyan * 0.5;
                if (uPhase == 1 || uPhase == 3) {
                    float spark = step(0.8, fract(vSize * 10.0 + uProgress * 5.0));
                    color = mix(color, uColGold, spark * 2.0);
                } else if (uPhase == 4) {
                    color = mix(color, uColMagenta, (1.0 - uProgress));
                }
                gl_FragColor = vec4(color, alpha);
            }
        `
    });
    const synapses = new THREE.Points(synGeo, synMat);
    networkGroup.add(synapses);

    const dustGeo = new THREE.BufferGeometry();
    const dustCount = 800;
    const dustPos = new Float32Array(dustCount * 3);
    for(let i=0; i<dustCount * 3; i++) {
        dustPos[i] = (Math.random() - 0.5) * 150;
    }
    dustGeo.setAttribute('position', new THREE.BufferAttribute(dustPos, 3));
    const dustMat = new THREE.PointsMaterial({
        color: CONFIG.colors.cyan,
        size: 0.2,
        transparent: true,
        opacity: 0.3,
        blending: THREE.AdditiveBlending,
        depthWrite: false
    });
    const dust = new THREE.Points(dustGeo, dustMat);
    scene.add(dust);

    const btnFire = document.getElementById('btn-fire');

    function triggerImpulse(e) {
        if (e && e.target && e.target.closest && e.target.closest('.hud-panel')) {
            if (e.target !== btnFire) return;
        }

        if (STATE.isAnimating) return;
        STATE.isAnimating = true;
        STATE.phase = 1;
        STATE.progress = 0;
        btnFire.classList.add('disabled');
        btnFire.innerText = 'FIRING SEQUENCE...';
    }

    window.addEventListener('pointerdown', triggerImpulse);

    const clock = new THREE.Clock();

    const elMembrane = document.getElementById('val-membrane');
    const elDendrites = document.getElementById('val-dendrites');
    const elAxon = document.getElementById('val-axon');
    const elState = document.getElementById('val-state');
    const elSync = document.getElementById('val-sync');
    
    const elCamX = document.getElementById('val-cam-x');
    const elCamY = document.getElementById('val-cam-y');
    const elCamZ = document.getElementById('val-cam-z');

    function updateUI() {
        elCamX.innerText = camera.position.x.toFixed(2);
        elCamY.innerText = camera.position.y.toFixed(2);
        elCamZ.innerText = camera.position.z.toFixed(2);

        let targetMembrane = -70.0;
        let targetAxon = 2;
        let targetSync = 24 + Math.sin(uniforms.uTime.value * 2) * 5;
        
        let stateText = "RESTING";
        let denText = "CALM";

        elMembrane.className = "hud-value";
        elAxon.className = "hud-value";
        elState.className = "hud-value";

        switch(STATE.phase) {
            case 1:
                stateText = "INCOMING STIMULUS";
                denText = "ACTIVE LOAD";
                targetMembrane = -55.0; 
                targetSync = 45;
                elState.classList.add('value-active');
                break;
            case 2:
                stateText = "SOMA MERGE";
                denText = "CONVERGED";
                targetMembrane = +40.0;
                targetSync = 85;
                elMembrane.classList.add('value-active');
                elState.classList.add('value-active');
                break;
            case 3:
                stateText = "AXON OUTFLOW";
                targetMembrane = +20.0;
                targetAxon = 98;
                targetSync = 99;
                elAxon.classList.add('value-active');
                elState.classList.add('value-active');
                break;
            case 4:
                stateText = "REFRACTORY PERIOD";
                targetMembrane = -80.0;
                targetAxon = 15;
                targetSync = 15;
                elMembrane.classList.add('value-refract');
                elState.classList.add('value-refract');
                break;
        }

        STATE.membraneV += (targetMembrane - STATE.membraneV) * 0.15;
        STATE.axonLoad += (targetAxon - STATE.axonLoad) * 0.15;
        STATE.sync += (targetSync - STATE.sync) * 0.15;

        elMembrane.innerText = `${STATE.membraneV > 0 ? '+' : ''}${STATE.membraneV.toFixed(1)} mV`;
        elAxon.innerText = `${Math.round(STATE.axonLoad).toString().padStart(2, '0')}%`;
        elSync.innerText = `${Math.round(STATE.sync).toString().padStart(2, '0')}%`;
        elState.innerText = stateText;
        elDendrites.innerText = denText;
    }

    function animate() {
        requestAnimationFrame(animate);

        const dt = clock.getDelta();
        const time = clock.getElapsedTime();
        uniforms.uTime.value = time;

        controls.update();

        dust.rotation.y = time * 0.02;
        dust.rotation.x = Math.sin(time * 0.01) * 0.05;

        if (STATE.isAnimating) {
            let speed = 1.0;
            if (STATE.phase === 1) speed = 0.8;
            if (STATE.phase === 2) speed = 2.5;
            if (STATE.phase === 3) speed = 0.95;
            if (STATE.phase === 4) speed = 0.5;

            STATE.progress += dt * speed;

            if (STATE.progress >= 1.0) {
                STATE.progress = 0.0;
                STATE.phase++;
                
                if (STATE.phase === 2) {
                    const target = camera.position.clone().multiplyScalar(0.85);
                    camera.position.lerp(target, 0.5);
                    bloomPass.strength = 2.5;
                }
                if (STATE.phase === 3) {
                    const target = camera.position.clone().multiplyScalar(1.2);
                    camera.position.lerp(target, 0.5);
                }

                if (STATE.phase > 4) {
                    STATE.phase = 0;
                    STATE.isAnimating = false;
                    btnFire.classList.remove('disabled');
                    btnFire.innerText = 'MANUAL OVERRIDE';
                }
            }
        } else {
            bloomPass.strength += (1.8 - bloomPass.strength) * 0.05;
        }

        uniforms.uPhase.value = STATE.phase;
        uniforms.uProgress.value = STATE.progress;

        updateUI();

        composer.render();
    }

    setTimeout(() => {
        document.getElementById('loader').style.opacity = '0';
        setTimeout(() => document.getElementById('loader').style.display = 'none', 1000);
    }, 1200);

    window.addEventListener('resize', () => {
        applyResponsiveScene();
    });

    animate();
</script>
    
  </body>
  
</html>

More in 3D & WebGL