{"slug": "bioelectric-consciousness-engine", "title": "Bioelectric consciousness engine", "summary": "Techartist, a developer on CodePen, has created a bioelectric consciousness engine using Three.js, WebGL, and GLSL. The interactive visualization allows users to click anywhere to trigger signals, while a HUD tracks live neural state in real time.", "body_md": "A bioelectric consciousness engine built with Three.js, webgl and glsl. Click anywhere to trigger signals; the HUD tracks live neural state.\n\nA [Pen](https://codepen.io/VoXelo/pen/xbgpJre) by [Techartist](https://codepen.io/VoXelo) on [CodePen](https://codepen.io).\n\nA bioelectric consciousness engine built with Three.js, webgl and glsl. Click anywhere to trigger signals; the HUD tracks live neural state.\n\nA [Pen](https://codepen.io/VoXelo/pen/xbgpJre) by [Techartist](https://codepen.io/VoXelo) on [CodePen](https://codepen.io).\n\n| <style> | |\n| :root { | |\n| --cyan: #00f0ff; | |\n| --gold: #ffaa00; | |\n| --magenta: #ff00aa; | |\n| --bg-dark: #010204; | |\n| --glass-bg: linear-gradient(135deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.07) 45%, rgba(0, 240, 255, 0.08)); | |\n| --glass-border: rgba(255, 255, 255, 0.24); | |\n| --glass-highlight: rgba(255, 255, 255, 0.42); | |\n| } | |\n| body, html { | |\n| margin: 0; | |\n| padding: 0; | |\n| width: 100%; | |\n| height: 100%; | |\n| background-color: var(--bg-dark); | |\n| overflow: hidden; | |\n| font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | |\n| color: white; | |\n| user-select: none; | |\n| } | |\n| canvas { | |\n| display: block; | |\n| width: 100vw; | |\n| height: 100vh; | |\n| position: absolute; | |\n| top: 0; | |\n| left: 0; | |\n| z-index: 1; | |\n| } | |\n| .overlay { | |\n| position: absolute; | |\n| top: 0; left: 0; width: 100%; height: 100%; | |\n| pointer-events: none; | |\n| z-index: 10; | |\n| background: | |\n| radial-gradient(circle at center, transparent 40%, rgba(0, 0, 0, 0.85) 100%), | |\n| repeating-linear-gradient(0deg, rgba(0,0,0,0.15) 0px, rgba(0,0,0,0.15) 1px, transparent 1px, transparent 2px); | |\n| box-shadow: inset 0 0 100px rgba(0,0,0,0.9); | |\n| } | |\n| .hud-panel { | |\n| position: absolute; | |\n| z-index: 20; | |\n| background: var(--glass-bg); | |\n| border: 1px solid var(--glass-border); | |\n| border-radius: 18px; | |\n| backdrop-filter: blur(28px) saturate(170%); | |\n| -webkit-backdrop-filter: blur(28px) saturate(170%); | |\n| box-shadow: | |\n| 0 18px 45px rgba(0, 0, 0, 0.38), | |\n| inset 0 1px 0 var(--glass-highlight), | |\n| inset 0 -1px 0 rgba(255, 255, 255, 0.08); | |\n| transition: all 0.3s ease; | |\n| pointer-events: auto; | |\n| overflow: hidden; | |\n| } | |\n| #hud-left { | |\n| top: clamp(12px, 3vw, 28px); | |\n| left: clamp(12px, 3vw, 28px); | |\n| padding: 14px; | |\n| width: min(230px, calc(100vw - 24px)); | |\n| } | |\n| #hud-right { | |\n| bottom: clamp(12px, 3vw, 28px); | |\n| right: clamp(12px, 3vw, 28px); | |\n| padding: 10px 14px; | |\n| min-width: 130px; | |\n| text-align: right; | |\n| } | |\n| .hud-header { | |\n| border-bottom: 1px solid rgba(255, 255, 255, 0.1); | |\n| padding-bottom: 8px; | |\n| margin-bottom: 10px; | |\n| } | |\n| h1 { | |\n| font-size: 11px; | |\n| letter-spacing: 2.6px; | |\n| color: var(--cyan); | |\n| margin: 0 0 4px 0; | |\n| font-weight: 700; | |\n| text-transform: uppercase; | |\n| text-shadow: 0 0 10px rgba(0, 240, 255, 0.4); | |\n| } | |\n| .subtitle { | |\n| font-size: 8px; | |\n| color: rgba(255, 255, 255, 0.4); | |\n| letter-spacing: 1.4px; | |\n| } | |\n| .hud-row { | |\n| display: flex; | |\n| justify-content: space-between; | |\n| gap: 18px; | |\n| margin-bottom: 8px; | |\n| font-size: 9px; | |\n| letter-spacing: 0.8px; | |\n| } | |\n| .hud-label { | |\n| color: rgba(255, 255, 255, 0.5); | |\n| text-transform: uppercase; | |\n| } | |\n| .hud-value { | |\n| font-weight: 600; | |\n| color: var(--cyan); | |\n| text-shadow: 0 0 8px rgba(0, 240, 255, 0.5); | |\n| transition: color 0.3s, text-shadow 0.3s; | |\n| font-variant-numeric: tabular-nums; | |\n| } | |\n| .value-active { color: var(--gold); text-shadow: 0 0 10px rgba(255, 170, 0, 0.6); } | |\n| .value-refract { color: var(--magenta); text-shadow: 0 0 10px rgba(255, 0, 170, 0.6); } | |\n| .btn-trigger { | |\n| margin-top: 12px; | |\n| width: 100%; | |\n| padding: 9px 10px; | |\n| background: rgba(255, 255, 255, 0.1); | |\n| border: 1px solid rgba(255, 255, 255, 0.24); | |\n| color: var(--cyan); | |\n| font-size: 9px; | |\n| letter-spacing: 2px; | |\n| border-radius: 999px; | |\n| cursor: pointer; | |\n| text-transform: uppercase; | |\n| transition: all 0.2s; | |\n| box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 15px rgba(0, 240, 255, 0.1); | |\n| } | |\n| .btn-trigger:hover { | |\n| background: rgba(0, 240, 255, 0.15); | |\n| box-shadow: 0 0 20px rgba(0, 240, 255, 0.4); | |\n| } | |\n| .btn-trigger.disabled { | |\n| border-color: rgba(255,255,255,0.1); | |\n| color: rgba(255,255,255,0.3); | |\n| background: transparent; | |\n| box-shadow: none; | |\n| cursor: not-allowed; | |\n| } | |\n| #instructions { | |\n| position: absolute; | |\n| bottom: clamp(14px, 4vw, 40px); left: 50%; | |\n| transform: translateX(-50%); | |\n| z-index: 20; | |\n| font-size: 9px; | |\n| letter-spacing: 1.6px; | |\n| color: rgba(255,255,255,0.4); | |\n| pointer-events: none; | |\n| text-transform: uppercase; | |\n| animation: pulseText 2s infinite; | |\n| white-space: nowrap; | |\n| } | |\n| @keyframes pulseText { | |\n| 0%, 100% { opacity: 0.3; } | |\n| 50% { opacity: 0.8; } | |\n| } | |\n| #cursor { | |\n| position: fixed; | |\n| top: 0; left: 0; | |\n| width: 24px; height: 24px; | |\n| border: 1px solid rgba(0, 240, 255, 0.8); | |\n| border-radius: 50%; | |\n| transform: translate(-50%, -50%); | |\n| pointer-events: none; | |\n| z-index: 9999; | |\n| transition: width 0.2s, height 0.2s, background 0.2s; | |\n| mix-blend-mode: screen; | |\n| box-shadow: 0 0 10px rgba(0,240,255,0.4); | |\n| } | |\n| #cursor.click { | |\n| width: 12px; height: 12px; | |\n| background: var(--cyan); | |\n| border-color: transparent; | |\n| } | |\n| #loader { | |\n| position: absolute; | |\n| top: 0; left: 0; width: 100%; height: 100%; | |\n| background: var(--bg-dark); | |\n| z-index: 9000; | |\n| display: flex; | |\n| justify-content: center; | |\n| align-items: center; | |\n| flex-direction: column; | |\n| transition: opacity 1s ease; | |\n| } | |\n| .spinner { | |\n| width: 50px; height: 50px; | |\n| border: 2px solid rgba(0,240,255,0.1); | |\n| border-top-color: var(--cyan); | |\n| border-radius: 50%; | |\n| animation: spin 1s cubic-bezier(0.4, 0, 0.2, 1) infinite; | |\n| margin-bottom: 24px; | |\n| box-shadow: 0 0 20px rgba(0,240,255,0.2); | |\n| } | |\n| @keyframes spin { 100% { transform: rotate(360deg); } } | |\n| @media (max-width: 720px) { | |\n| .overlay { | |\n| background: | |\n| radial-gradient(circle at center, transparent 52%, rgba(0, 0, 0, 0.78) 100%), | |\n| repeating-linear-gradient(0deg, rgba(0,0,0,0.12) 0px, rgba(0,0,0,0.12) 1px, transparent 1px, transparent 2px); | |\n| box-shadow: inset 0 0 60px rgba(0,0,0,0.82); | |\n| } | |\n| #hud-left { | |\n| top: max(10px, env(safe-area-inset-top)); | |\n| left: 10px; | |\n| right: auto; | |\n| width: min(220px, calc(100vw - 20px)); | |\n| padding: 8px 9px; | |\n| border-radius: 13px; | |\n| } | |\n| #hud-right { | |\n| right: 10px; | |\n| bottom: max(54px, env(safe-area-inset-bottom)); | |\n| padding: 8px 10px; | |\n| min-width: 112px; | |\n| } | |\n| .hud-header { | |\n| display: flex; | |\n| align-items: baseline; | |\n| justify-content: space-between; | |\n| gap: 8px; | |\n| padding-bottom: 5px; | |\n| margin-bottom: 6px; | |\n| } | |\n| h1 { | |\n| font-size: 9px; | |\n| letter-spacing: 1.5px; | |\n| margin-bottom: 0; | |\n| } | |\n| .subtitle { | |\n| font-size: 6px; | |\n| letter-spacing: 0.7px; | |\n| text-align: right; | |\n| } | |\n| .hud-row { | |\n| gap: 10px; | |\n| margin-bottom: 4px; | |\n| font-size: 7px; | |\n| letter-spacing: 0.55px; | |\n| } | |\n| .btn-trigger { | |\n| margin-top: 6px; | |\n| padding: 6px 8px; | |\n| font-size: 7px; | |\n| letter-spacing: 1.2px; | |\n| } | |\n| #instructions { | |\n| bottom: max(16px, env(safe-area-inset-bottom)); | |\n| font-size: 8px; | |\n| letter-spacing: 1.1px; | |\n| } | |\n| #cursor { | |\n| display: none; | |\n| } | |\n| } | |\n| @media (max-width: 420px) { | |\n| #hud-left { | |\n| display: grid; | |\n| grid-template-columns: 1fr 1fr; | |\n| column-gap: 10px; | |\n| row-gap: 0; | |\n| width: min(236px, calc(100vw - 16px)); | |\n| left: 8px; | |\n| top: max(8px, env(safe-area-inset-top)); | |\n| padding: 7px 8px; | |\n| } | |\n| .hud-header, | |\n| .btn-trigger { | |\n| grid-column: 1 / -1; | |\n| } | |\n| .hud-header { | |\n| display: block; | |\n| } | |\n| .subtitle { | |\n| display: none; | |\n| } | |\n| .hud-row { | |\n| gap: 6px; | |\n| margin-bottom: 4px; | |\n| } | |\n| .hud-label { | |\n| max-width: 60px; | |\n| } | |\n| } | |\n| </style> | |\n| <script type=\"importmap\"> | |\n| { | |\n| \"imports\": { | |\n| \"three\": \"https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js\", | |\n| \"three/addons/\": \"https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/\" | |\n| } | |\n| } | |\n| </script> | |\n| <div class=\"overlay\"></div> | |\n| <div id=\"cursor\"></div> | |\n| <div id=\"loader\"> | |\n| <div class=\"spinner\"></div> | |\n| <h1 style=\"color: rgba(255,255,255,0.6); font-size: 11px;\">INITIALIZING BIOELECTRIC ENGINE</h1> | |\n| </div> | |\n| <div id=\"hud-left\" class=\"hud-panel\"> | |\n| <div class=\"hud-header\"> | |\n| <h1>Neural Cathedral</h1> | |\n| <div class=\"subtitle\">ID: NC-09 // BIOELECTRIC ENGINE</div> | |\n| </div> | |\n| <div class=\"hud-row\"> | |\n| <span class=\"hud-label\">Membrane V</span> | |\n| <span class=\"hud-value\" id=\"val-membrane\">-70.0 mV</span> | |\n| </div> | |\n| <div class=\"hud-row\"> | |\n| <span class=\"hud-label\">Dendrite State</span> | |\n| <span class=\"hud-value\" id=\"val-dendrites\">CALM</span> | |\n| </div> | |\n| <div class=\"hud-row\"> | |\n| <span class=\"hud-label\">Axon Load</span> | |\n| <span class=\"hud-value\" id=\"val-axon\">02%</span> | |\n| </div> | |\n| <div class=\"hud-row\"> | |\n| <span class=\"hud-label\">Signal Phase</span> | |\n| <span class=\"hud-value\" id=\"val-state\">RESTING</span> | |\n| </div> | |\n| <div class=\"hud-row\"> | |\n| <span class=\"hud-label\">Synaptic Coh</span> | |\n| <span class=\"hud-value\" id=\"val-sync\">24%</span> | |\n| </div> | |\n| <button class=\"btn-trigger\" id=\"btn-fire\">Manual Override</button> | |\n| </div> | |\n| <div id=\"hud-right\" class=\"hud-panel\"> | |\n| <div class=\"hud-row\"> | |\n| <span class=\"hud-label\">Cam X</span> | |\n| <span class=\"hud-value\" id=\"val-cam-x\">0.00</span> | |\n| </div> | |\n| <div class=\"hud-row\"> | |\n| <span class=\"hud-label\">Cam Y</span> | |\n| <span class=\"hud-value\" id=\"val-cam-y\">0.00</span> | |\n| </div> | |\n| <div class=\"hud-row\"> | |\n| <span class=\"hud-label\">Cam Z</span> | |\n| <span class=\"hud-value\" id=\"val-cam-z\">0.00</span> | |\n| </div> | |\n| </div> | |\n| <div id=\"instructions\">Click anywhere to trigger impulse</div> | |\n| <script type=\"module\"> | |\n| import * as THREE from 'three'; | |\n| import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; | |\n| import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; | |\n| import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; | |\n| import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js'; | |\n| const cursor = document.getElementById('cursor'); | |\n| document.addEventListener('mousemove', (e) => { | |\n| cursor.style.left = e.clientX + 'px'; | |\n| cursor.style.top = e.clientY + 'px'; | |\n| }); | |\n| document.addEventListener('mousedown', () => cursor.classList.add('click')); | |\n| document.addEventListener('mouseup', () => cursor.classList.remove('click')); | |\n| const shaderNoise = ` | |\n| vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } | |\n| vec4 mod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } | |\n| vec4 permute(vec4 x) { return mod289(((x*34.0)+1.0)*x); } | |\n| vec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; } | |\n| float snoise(vec3 v) { | |\n| const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; | |\n| const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); | |\n| vec3 i = floor(v + dot(v, C.yyy) ); | |\n| vec3 x0 = v - i + dot(i, C.xxx) ; | |\n| vec3 g = step(x0.yzx, x0.xyz); | |\n| vec3 l = 1.0 - g; | |\n| vec3 i1 = min( g.xyz, l.zxy ); | |\n| vec3 i2 = max( g.xyz, l.zxy ); | |\n| vec3 x1 = x0 - i1 + C.xxx; | |\n| vec3 x2 = x0 - i2 + C.yyy; | |\n| vec3 x3 = x0 - D.yyy; | |\n| i = mod289(i); | |\n| vec4 p = permute( permute( permute( | |\n| i.z + vec4(0.0, i1.z, i2.z, 1.0 )) | |\n| + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) | |\n| + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); | |\n| float n_ = 0.142857142857; | |\n| vec3 ns = n_ * D.wyz - D.xzx; | |\n| vec4 j = p - 49.0 * floor(p * ns.z * ns.z); | |\n| vec4 x_ = floor(j * ns.z); | |\n| vec4 y_ = floor(j - 7.0 * x_ ); | |\n| vec4 x = x_ *ns.x + ns.yyyy; | |\n| vec4 y = y_ *ns.x + ns.yyyy; | |\n| vec4 h = 1.0 - abs(x) - abs(y); | |\n| vec4 b0 = vec4( x.xy, y.xy ); | |\n| vec4 b1 = vec4( x.zw, y.zw ); | |\n| vec4 s0 = floor(b0)*2.0 + 1.0; | |\n| vec4 s1 = floor(b1)*2.0 + 1.0; | |\n| vec4 sh = -step(h, vec4(0.0)); | |\n| vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; | |\n| vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; | |\n| vec3 p0 = vec3(a0.xy,h.x); | |\n| vec3 p1 = vec3(a0.zw,h.y); | |\n| vec3 p2 = vec3(a1.xy,h.z); | |\n| vec3 p3 = vec3(a1.zw,h.w); | |\n| vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); | |\n| p0 *= norm.x; | |\n| p1 *= norm.y; | |\n| p2 *= norm.z; | |\n| p3 *= norm.w; | |\n| vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); | |\n| m = m * m; | |\n| return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) ); | |\n| } | |\n| `; | |\n| const CONFIG = { | |\n| somaRadius: 4.0, | |\n| dendriteTrees: 14, | |\n| axonTrees: 4, | |\n| maxDistDendrite: 35.0, | |\n| maxDistAxon: 50.0, | |\n| colors: { | |\n| cyan: new THREE.Color('#00e5ff'), | |\n| blue: new THREE.Color('#0033aa'), | |\n| gold: new THREE.Color('#ffaa00'), | |\n| orange: new THREE.Color('#ff4400'), | |\n| magenta: new THREE.Color('#ff0066'), | |\n| violet: new THREE.Color('#6600ff') | |\n| } | |\n| }; | |\n| const STATE = { | |\n| phase: 0, | |\n| progress: 0, | |\n| membraneV: -70.0, | |\n| axonLoad: 2, | |\n| sync: 24, | |\n| isAnimating: false | |\n| }; | |\n| const uniforms = { | |\n| uTime: { value: 0 }, | |\n| uPhase: { value: 0 }, | |\n| uProgress: { value: 0 }, | |\n| uColCyan: { value: CONFIG.colors.cyan }, | |\n| uColBlue: { value: CONFIG.colors.blue }, | |\n| uColGold: { value: CONFIG.colors.gold }, | |\n| uColOrange: { value: CONFIG.colors.orange }, | |\n| uColMagenta: { value: CONFIG.colors.magenta }, | |\n| uColViolet: { value: CONFIG.colors.violet }, | |\n| uSomaRadius: { value: CONFIG.somaRadius }, | |\n| uMaxDistDendrite: { value: CONFIG.maxDistDendrite }, | |\n| uMaxDistAxon: { value: CONFIG.maxDistAxon } | |\n| }; | |\n| const scene = new THREE.Scene(); | |\n| scene.fog = new THREE.FogExp2(0x010204, 0.015); | |\n| const desktopCameraPosition = new THREE.Vector3(30, 20, 40); | |\n| const mobileCameraPosition = new THREE.Vector3(34, 24, 62); | |\n| const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 500); | |\n| camera.position.copy(desktopCameraPosition); | |\n| const renderer = new THREE.WebGLRenderer({ antialias: false, powerPreference: \"high-performance\" }); | |\n| renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); | |\n| renderer.setSize(window.innerWidth, window.innerHeight); | |\n| renderer.toneMapping = THREE.ACESFilmicToneMapping; | |\n| renderer.toneMappingExposure = 1.2; | |\n| document.body.appendChild(renderer.domElement); | |\n| const composer = new EffectComposer(renderer); | |\n| const renderPass = new RenderPass(scene, camera); | |\n| composer.addPass(renderPass); | |\n| const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.8, 0.6, 0.1); | |\n| composer.addPass(bloomPass); | |\n| const controls = new OrbitControls(camera, renderer.domElement); | |\n| controls.enableDamping = true; | |\n| controls.dampingFactor = 0.04; | |\n| controls.autoRotate = true; | |\n| controls.autoRotateSpeed = 0.6; | |\n| controls.enablePan = false; | |\n| controls.minDistance = 15; | |\n| controls.maxDistance = 120; | |\n| function isCompactViewport() { | |\n| return window.innerWidth <= 720 || window.matchMedia('(pointer: coarse)').matches; | |\n| } | |\n| function applyResponsiveScene(resetCamera = false) { | |\n| const width = window.innerWidth; | |\n| const height = window.innerHeight; | |\n| const compact = isCompactViewport(); | |\n| const targetPosition = compact ? mobileCameraPosition : desktopCameraPosition; | |\n| camera.aspect = width / height; | |\n| camera.fov = compact ? 52 : 45; | |\n| camera.updateProjectionMatrix(); | |\n| renderer.setPixelRatio(Math.min(window.devicePixelRatio, compact ? 1.5 : 2)); | |\n| renderer.setSize(width, height, false); | |\n| composer.setSize(width, height); | |\n| controls.minDistance = compact ? 24 : 15; | |\n| controls.maxDistance = compact ? 140 : 120; | |\n| if (resetCamera) { | |\n| camera.position.copy(targetPosition); | |\n| } else if (compact && camera.position.length() < targetPosition.length() * 0.8) { | |\n| camera.position.setLength(targetPosition.length()); | |\n| } | |\n| controls.update(); | |\n| } | |\n| applyResponsiveScene(true); | |\n| const somaMaterial = new THREE.ShaderMaterial({ | |\n| uniforms: uniforms, | |\n| transparent: true, | |\n| blending: THREE.AdditiveBlending, | |\n| depthWrite: false, | |\n| side: THREE.DoubleSide, | |\n| vertexShader: ` | |\n| ${shaderNoise} | |\n| uniform float uTime; | |\n| uniform int uPhase; | |\n| uniform float uProgress; | |\n| varying vec3 vNormal; | |\n| varying vec3 vViewPosition; | |\n| varying float vNoise; | |\n| void main() { | |\n| vec3 pos = position; | |\n| float noise = snoise(pos * 0.5 + uTime * 0.3) * 0.5; | |\n| float burst = 0.0; | |\n| if(uPhase == 2) { | |\n| burst = sin(uProgress * 3.14159) * 0.4; | |\n| } | |\n| pos += normal * (noise + burst); | |\n| vNoise = noise; | |\n| vNormal = normalize(normalMatrix * normal); | |\n| vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0); | |\n| vViewPosition = -mvPosition.xyz; | |\n| gl_Position = projectionMatrix * mvPosition; | |\n| } | |\n| `, | |\n| fragmentShader: ` | |\n| uniform int uPhase; | |\n| uniform float uProgress; | |\n| uniform float uTime; | |\n| uniform vec3 uColCyan; | |\n| uniform vec3 uColBlue; | |\n| uniform vec3 uColGold; | |\n| uniform vec3 uColMagenta; | |\n| varying vec3 vNormal; | |\n| varying vec3 vViewPosition; | |\n| varying float vNoise; | |\n| void main() { | |\n| vec3 normal = normalize(vNormal); | |\n| vec3 viewDir = normalize(vViewPosition); | |\n| float fresnel = pow(1.0 - max(dot(normal, viewDir), 0.0), 2.5); | |\n| vec3 color = mix(uColBlue * 0.2, uColCyan, fresnel); | |\n| color += uColCyan * (vNoise * 0.5 + 0.5) * 0.3; | |\n| if(uPhase == 2) { | |\n| float intensity = sin(uProgress * 3.14159); | |\n| color = mix(color, uColGold * 2.0 + uColCyan, intensity * fresnel * 2.0); | |\n| color += uColGold * intensity * (1.0 - fresnel); | |\n| } else if(uPhase == 4) { | |\n| float intensity = 1.0 - uProgress; | |\n| color = mix(color, uColMagenta, intensity * fresnel * 1.5); | |\n| } | |\n| gl_FragColor = vec4(color, 0.8 * fresnel + 0.2); | |\n| } | |\n| ` | |\n| }); | |\n| const branchMaterial = new THREE.ShaderMaterial({ | |\n| uniforms: Object.assign({}, uniforms, { uIsAxon: { value: 0 } }), | |\n| transparent: true, | |\n| blending: THREE.AdditiveBlending, | |\n| depthWrite: false, | |\n| vertexShader: ` | |\n| ${shaderNoise} | |\n| uniform float uTime; | |\n| varying vec3 vWorldPos; | |\n| varying vec3 vNormal; | |\n| varying vec3 vViewPosition; | |\n| varying vec2 vUv; | |\n| void main() { | |\n| vUv = uv; | |\n| vec3 pos = position; | |\n| float wiggle = snoise(pos * 0.2 + uTime * 0.5) * 0.1; | |\n| pos += normal * wiggle; | |\n| vec4 worldPosition = modelMatrix * vec4(pos, 1.0); | |\n| vWorldPos = worldPosition.xyz; | |\n| vNormal = normalize(normalMatrix * normal); | |\n| vec4 mvPosition = viewMatrix * worldPosition; | |\n| vViewPosition = -mvPosition.xyz; | |\n| gl_Position = projectionMatrix * mvPosition; | |\n| } | |\n| `, | |\n| fragmentShader: ` | |\n| ${shaderNoise} | |\n| uniform float uTime; | |\n| uniform int uPhase; | |\n| uniform float uProgress; | |\n| uniform int uIsAxon; | |\n| uniform vec3 uColCyan; | |\n| uniform vec3 uColBlue; | |\n| uniform vec3 uColGold; | |\n| uniform vec3 uColOrange; | |\n| uniform vec3 uColMagenta; | |\n| uniform vec3 uColViolet; | |\n| uniform float uSomaRadius; | |\n| uniform float uMaxDistDendrite; | |\n| uniform float uMaxDistAxon; | |\n| varying vec3 vWorldPos; | |\n| varying vec3 vNormal; | |\n| varying vec3 vViewPosition; | |\n| varying vec2 vUv; | |\n| void main() { | |\n| vec3 normal = normalize(vNormal); | |\n| vec3 viewDir = normalize(vViewPosition); | |\n| float edge = pow(1.0 - abs(vUv.y - 0.5) * 2.0, 2.0); | |\n| float fresnel = pow(1.0 - max(dot(normal, viewDir), 0.0), 2.0); | |\n| float dist = length(vWorldPos); | |\n| vec3 baseColor = mix(uColBlue * 0.1, uColCyan * 0.5, fresnel * edge); | |\n| vec3 pulseColor = vec3(0.0); | |\n| float flowNoise = snoise(vec3(vUv.x * 20.0 - uTime * 2.0, vUv.y * 10.0, uTime)) * 0.5 + 0.5; | |\n| float axialFlow = 0.65 + 0.35 * sin(vUv.x * 34.0 - uTime * 8.0); | |\n| if (uIsAxon == 0) { | |\n| if (uPhase == 1) { | |\n| float currentWaveDist = mix(uMaxDistDendrite, uSomaRadius, uProgress); | |\n| float head = 1.0 - smoothstep(0.0, 2.3, abs(dist - currentWaveDist)); | |\n| float outerTrail = step(currentWaveDist, dist) * exp(-(dist - currentWaveDist) * 0.18); | |\n| float mergeGlow = (1.0 - smoothstep(uSomaRadius, uSomaRadius + 8.0, dist)) * smoothstep(0.65, 1.0, uProgress); | |\n| float pulse = max(head * 1.6, outerTrail * 0.65) + mergeGlow * 0.8; | |\n| pulseColor = uColGold * pulse * flowNoise * axialFlow * 3.2; | |\n| } | |\n| } else { | |\n| if (uPhase == 3) { | |\n| float currentWaveDist = mix(uSomaRadius, uMaxDistAxon + 18.0, uProgress); | |\n| float head = 1.0 - smoothstep(0.0, 3.4, abs(dist - currentWaveDist)); | |\n| float innerTrail = step(dist, currentWaveDist) * exp(-(currentWaveDist - dist) * 0.1); | |\n| float somaLaunch = (1.0 - smoothstep(uSomaRadius, uSomaRadius + 7.0, dist)) * (1.0 - smoothstep(0.0, 0.28, uProgress)); | |\n| float pulse = max(head * 2.0, innerTrail * 0.9) + somaLaunch * 1.2; | |\n| pulseColor = (uColOrange + uColGold * 0.45) * pulse * flowNoise * axialFlow * 4.6; | |\n| } | |\n| } | |\n| if (uPhase == 4) { | |\n| float intensity = 1.0 - uProgress; | |\n| pulseColor += uColViolet * intensity * edge * 1.5; | |\n| } | |\n| gl_FragColor = vec4(baseColor + pulseColor, 1.0); | |\n| } | |\n| ` | |\n| }); | |\n| const axonMaterial = branchMaterial.clone(); | |\n| Object.keys(uniforms).forEach((key) => { | |\n| axonMaterial.uniforms[key] = uniforms[key]; | |\n| }); | |\n| axonMaterial.uniforms.uIsAxon = { value: 1 }; | |\n| const networkGroup = new THREE.Group(); | |\n| scene.add(networkGroup); | |\n| const somaGeo = new THREE.IcosahedronGeometry(CONFIG.somaRadius, 32); | |\n| const somaMesh = new THREE.Mesh(somaGeo, somaMaterial); | |\n| networkGroup.add(somaMesh); | |\n| const coreGeo = new THREE.IcosahedronGeometry(CONFIG.somaRadius * 0.8, 16); | |\n| const coreMat = new THREE.MeshBasicMaterial({ color: CONFIG.colors.cyan, transparent: true, opacity: 0.1, blending: THREE.AdditiveBlending, wireframe: true }); | |\n| networkGroup.add(new THREE.Mesh(coreGeo, coreMat)); | |\n| function buildBranch(startPt, dir, length, radius, level, maxLevels, isAxon) { | |\n| const segments = 12; | |\n| const points = [startPt.clone()]; | |\n| let cur = startPt.clone(); | |\n| let cDir = dir.clone(); | |\n| for(let i=0; i<segments; i++) { | |\n| let curl = new THREE.Vector3( | |\n| Math.random() - 0.5, | |\n| Math.random() - 0.5, | |\n| Math.random() - 0.5 | |\n| ).multiplyScalar(isAxon ? 0.3 : 0.8); | |\n| cDir.add(curl).normalize(); | |\n| cur.add(cDir.clone().multiplyScalar(length / segments)); | |\n| points.push(cur.clone()); | |\n| } | |\n| const curve = new THREE.CatmullRomCurve3(points); | |\n| const tubeGeo = new THREE.TubeGeometry(curve, segments * 2, radius, 6, false); | |\n| const mesh = new THREE.Mesh(tubeGeo, isAxon ? axonMaterial : branchMaterial); | |\n| networkGroup.add(mesh); | |\n| if (level < maxLevels) { | |\n| const childCount = isAxon ? (Math.random() > 0.3 ? 1 : 2) : (Math.random() > 0.2 ? 2 : 3); | |\n| for(let j=0; j<childCount; j++) { | |\n| let splitDir = cDir.clone().add(new THREE.Vector3( | |\n| Math.random()-0.5, Math.random()-0.5, Math.random()-0.5 | |\n| ).multiplyScalar(0.8)).normalize(); | |\n| buildBranch( | |\n| cur, | |\n| splitDir, | |\n| length * (0.6 + Math.random()*0.3), | |\n| radius * 0.65, | |\n| level + 1, | |\n| maxLevels, | |\n| isAxon | |\n| ); | |\n| } | |\n| } else { | |\n| addSynapse(cur); | |\n| } | |\n| } | |\n| const synapsePositions = []; | |\n| function addSynapse(pos) { | |\n| synapsePositions.push(pos.x, pos.y, pos.z); | |\n| } | |\n| for(let i=0; i<CONFIG.dendriteTrees; i++) { | |\n| let dir = new THREE.Vector3(Math.random()-0.5, Math.random()-0.5, Math.random()-0.5).normalize(); | |\n| if (dir.z > 0.3) dir.z -= 0.8; | |\n| dir.normalize(); | |\n| let start = dir.clone().multiplyScalar(CONFIG.somaRadius - 0.5); | |\n| buildBranch(start, dir, 12 + Math.random()*5, 0.4, 0, 2, false); | |\n| } | |\n| for(let i=0; i<CONFIG.axonTrees; i++) { | |\n| let dir = new THREE.Vector3((Math.random()-0.5)*0.5, (Math.random()-0.5)*0.5, 1.0).normalize(); | |\n| let start = dir.clone().multiplyScalar(CONFIG.somaRadius - 0.5); | |\n| buildBranch(start, dir, 25 + Math.random()*10, 0.6, 0, 2, true); | |\n| } | |\n| const synGeo = new THREE.BufferGeometry(); | |\n| synGeo.setAttribute('position', new THREE.Float32BufferAttribute(synapsePositions, 3)); | |\n| const synSizes = new Float32Array(synapsePositions.length / 3); | |\n| for(let i=0; i<synSizes.length; i++) synSizes[i] = Math.random(); | |\n| synGeo.setAttribute('aSize', new THREE.BufferAttribute(synSizes, 1)); | |\n| const synMat = new THREE.ShaderMaterial({ | |\n| uniforms: uniforms, | |\n| transparent: true, | |\n| blending: THREE.AdditiveBlending, | |\n| depthWrite: false, | |\n| vertexShader: ` | |\n| attribute float aSize; | |\n| uniform float uTime; | |\n| varying float vSize; | |\n| void main() { | |\n| vSize = aSize; | |\n| vec3 pos = position; | |\n| pos.y += sin(uTime * 2.0 + pos.x) * 0.5; | |\n| vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0); | |\n| gl_PointSize = (20.0 + aSize * 15.0) * (100.0 / -mvPosition.z); | |\n| gl_Position = projectionMatrix * mvPosition; | |\n| } | |\n| `, | |\n| fragmentShader: ` | |\n| uniform int uPhase; | |\n| uniform float uProgress; | |\n| uniform vec3 uColCyan; | |\n| uniform vec3 uColGold; | |\n| uniform vec3 uColMagenta; | |\n| varying float vSize; | |\n| void main() { | |\n| vec2 coord = gl_PointCoord - vec2(0.5); | |\n| float dist = length(coord); | |\n| if (dist > 0.5) discard; | |\n| float alpha = (0.5 - dist) * 2.0; | |\n| vec3 color = uColCyan * 0.5; | |\n| if (uPhase == 1 || uPhase == 3) { | |\n| float spark = step(0.8, fract(vSize * 10.0 + uProgress * 5.0)); | |\n| color = mix(color, uColGold, spark * 2.0); | |\n| } else if (uPhase == 4) { | |\n| color = mix(color, uColMagenta, (1.0 - uProgress)); | |\n| } | |\n| gl_FragColor = vec4(color, alpha); | |\n| } | |\n| ` | |\n| }); | |\n| const synapses = new THREE.Points(synGeo, synMat); | |\n| networkGroup.add(synapses); | |\n| const dustGeo = new THREE.BufferGeometry(); | |\n| const dustCount = 800; | |\n| const dustPos = new Float32Array(dustCount * 3); | |\n| for(let i=0; i<dustCount * 3; i++) { | |\n| dustPos[i] = (Math.random() - 0.5) * 150; | |\n| } | |\n| dustGeo.setAttribute('position', new THREE.BufferAttribute(dustPos, 3)); | |\n| const dustMat = new THREE.PointsMaterial({ | |\n| color: CONFIG.colors.cyan, | |\n| size: 0.2, | |\n| transparent: true, | |\n| opacity: 0.3, | |\n| blending: THREE.AdditiveBlending, | |\n| depthWrite: false | |\n| }); | |\n| const dust = new THREE.Points(dustGeo, dustMat); | |\n| scene.add(dust); | |\n| const btnFire = document.getElementById('btn-fire'); | |\n| function triggerImpulse(e) { | |\n| if (e && e.target && e.target.closest && e.target.closest('.hud-panel')) { | |\n| if (e.target !== btnFire) return; | |\n| } | |\n| if (STATE.isAnimating) return; | |\n| STATE.isAnimating = true; | |\n| STATE.phase = 1; | |\n| STATE.progress = 0; | |\n| btnFire.classList.add('disabled'); | |\n| btnFire.innerText = 'FIRING SEQUENCE...'; | |\n| } | |\n| window.addEventListener('pointerdown', triggerImpulse); | |\n| const clock = new THREE.Clock(); | |\n| const elMembrane = document.getElementById('val-membrane'); | |\n| const elDendrites = document.getElementById('val-dendrites'); | |\n| const elAxon = document.getElementById('val-axon'); | |\n| const elState = document.getElementById('val-state'); | |\n| const elSync = document.getElementById('val-sync'); | |\n| const elCamX = document.getElementById('val-cam-x'); | |\n| const elCamY = document.getElementById('val-cam-y'); | |\n| const elCamZ = document.getElementById('val-cam-z'); | |\n| function updateUI() { | |\n| elCamX.innerText = camera.position.x.toFixed(2); | |\n| elCamY.innerText = camera.position.y.toFixed(2); | |\n| elCamZ.innerText = camera.position.z.toFixed(2); | |\n| let targetMembrane = -70.0; | |\n| let targetAxon = 2; | |\n| let targetSync = 24 + Math.sin(uniforms.uTime.value * 2) * 5; | |\n| let stateText = \"RESTING\"; | |\n| let denText = \"CALM\"; | |\n| elMembrane.className = \"hud-value\"; | |\n| elAxon.className = \"hud-value\"; | |\n| elState.className = \"hud-value\"; | |\n| switch(STATE.phase) { | |\n| case 1: | |\n| stateText = \"INCOMING STIMULUS\"; | |\n| denText = \"ACTIVE LOAD\"; | |\n| targetMembrane = -55.0; | |\n| targetSync = 45; | |\n| elState.classList.add('value-active'); | |\n| break; | |\n| case 2: | |\n| stateText = \"SOMA MERGE\"; | |\n| denText = \"CONVERGED\"; | |\n| targetMembrane = +40.0; | |\n| targetSync = 85; | |\n| elMembrane.classList.add('value-active'); | |\n| elState.classList.add('value-active'); | |\n| break; | |\n| case 3: | |\n| stateText = \"AXON OUTFLOW\"; | |\n| targetMembrane = +20.0; | |\n| targetAxon = 98; | |\n| targetSync = 99; | |\n| elAxon.classList.add('value-active'); | |\n| elState.classList.add('value-active'); | |\n| break; | |\n| case 4: | |\n| stateText = \"REFRACTORY PERIOD\"; | |\n| targetMembrane = -80.0; | |\n| targetAxon = 15; | |\n| targetSync = 15; | |\n| elMembrane.classList.add('value-refract'); | |\n| elState.classList.add('value-refract'); | |\n| break; | |\n| } | |\n| STATE.membraneV += (targetMembrane - STATE.membraneV) * 0.15; | |\n| STATE.axonLoad += (targetAxon - STATE.axonLoad) * 0.15; | |\n| STATE.sync += (targetSync - STATE.sync) * 0.15; | |\n| elMembrane.innerText = `${STATE.membraneV > 0 ? '+' : ''}${STATE.membraneV.toFixed(1)} mV`; | |\n| elAxon.innerText = `${Math.round(STATE.axonLoad).toString().padStart(2, '0')}%`; | |\n| elSync.innerText = `${Math.round(STATE.sync).toString().padStart(2, '0')}%`; | |\n| elState.innerText = stateText; | |\n| elDendrites.innerText = denText; | |\n| } | |\n| function animate() { | |\n| requestAnimationFrame(animate); | |\n| const dt = clock.getDelta(); | |\n| const time = clock.getElapsedTime(); | |\n| uniforms.uTime.value = time; | |\n| controls.update(); | |\n| dust.rotation.y = time * 0.02; | |\n| dust.rotation.x = Math.sin(time * 0.01) * 0.05; | |\n| if (STATE.isAnimating) { | |\n| let speed = 1.0; | |\n| if (STATE.phase === 1) speed = 0.8; | |\n| if (STATE.phase === 2) speed = 2.5; | |\n| if (STATE.phase === 3) speed = 0.95; | |\n| if (STATE.phase === 4) speed = 0.5; | |\n| STATE.progress += dt * speed; | |\n| if (STATE.progress >= 1.0) { | |\n| STATE.progress = 0.0; | |\n| STATE.phase++; | |\n| if (STATE.phase === 2) { | |\n| const target = camera.position.clone().multiplyScalar(0.85); | |\n| camera.position.lerp(target, 0.5); | |\n| bloomPass.strength = 2.5; | |\n| } | |\n| if (STATE.phase === 3) { | |\n| const target = camera.position.clone().multiplyScalar(1.2); | |\n| camera.position.lerp(target, 0.5); | |\n| } | |\n| if (STATE.phase > 4) { | |\n| STATE.phase = 0; | |\n| STATE.isAnimating = false; | |\n| btnFire.classList.remove('disabled'); | |\n| btnFire.innerText = 'MANUAL OVERRIDE'; | |\n| } | |\n| } | |\n| } else { | |\n| bloomPass.strength += (1.8 - bloomPass.strength) * 0.05; | |\n| } | |\n| uniforms.uPhase.value = STATE.phase; | |\n| uniforms.uProgress.value = STATE.progress; | |\n| updateUI(); | |\n| composer.render(); | |\n| } | |\n| setTimeout(() => { | |\n| document.getElementById('loader').style.opacity = '0'; | |\n| setTimeout(() => document.getElementById('loader').style.display = 'none', 1000); | |\n| }, 1200); | |\n| window.addEventListener('resize', () => { | |\n| applyResponsiveScene(); | |\n| }); | |\n| animate(); | |\n| </script> |", "url": "https://wpnews.pro/news/bioelectric-consciousness-engine", "canonical_source": "https://gist.github.com/kazzohikaru/3cd0ae9f8f5eef8c74e863f36515680a", "published_at": "2026-08-14 12:43:37+00:00", "updated_at": "2026-08-14 12:49:47.511322+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Techartist", "CodePen", "Three.js", "WebGL", "GLSL"], "alternates": {"html": "https://wpnews.pro/news/bioelectric-consciousness-engine", "markdown": "https://wpnews.pro/news/bioelectric-consciousness-engine.md", "text": "https://wpnews.pro/news/bioelectric-consciousness-engine.txt", "jsonld": "https://wpnews.pro/news/bioelectric-consciousness-engine.jsonld"}}