Files
the-matrix/js/world.js
Perplexity Computer fdfae19956 feat: The Matrix — Sovereign Agent World
3D visualization for AI agent swarms built with Three.js.
Matrix green/noir cyberpunk aesthetic.

- 4 agents: Timmy (orchestrator), Forge (builder), Seer (planner), Echo (comms)
- Central core pillar, animated green grid, digital rain
- Agent info panels, chat, task list, memory views
- WebSocket protocol for real-time state updates
- iPad-ready: touch controls, add-to-homescreen
- Post-processing: bloom, scanlines, vignette
- No build step — pure ES modules via esm.sh CDN

Created with Perplexity Computer
2026-03-18 18:32:47 -04:00

207 lines
5.8 KiB
JavaScript

// ===== World: Ground plane, grid, core pillar, environment =====
import * as THREE from 'three';
// Grid shader - animated green grid on the ground
const gridVertexShader = `
varying vec2 vUv;
varying vec3 vWorldPos;
void main() {
vUv = uv;
vec4 worldPos = modelMatrix * vec4(position, 1.0);
vWorldPos = worldPos.xyz;
gl_Position = projectionMatrix * viewMatrix * worldPos;
}
`;
const gridFragmentShader = `
uniform float uTime;
uniform float uRadius;
varying vec2 vUv;
varying vec3 vWorldPos;
void main() {
vec2 p = vWorldPos.xz;
float dist = length(p);
// Circular falloff
float edge = smoothstep(uRadius, uRadius - 8.0, dist);
// Grid lines
float gridSize = 2.0;
vec2 grid = abs(fract(p / gridSize - 0.5) - 0.5) / fwidth(p / gridSize);
float line = min(grid.x, grid.y);
float gridAlpha = 1.0 - min(line, 1.0);
// Pulse wave from center
float pulse = sin(dist * 0.3 - uTime * 1.5) * 0.5 + 0.5;
pulse = smoothstep(0.3, 0.7, pulse);
// Sub-grid (finer lines)
float subGridSize = 0.5;
vec2 subGrid = abs(fract(p / subGridSize - 0.5) - 0.5) / fwidth(p / subGridSize);
float subLine = min(subGrid.x, subGrid.y);
float subGridAlpha = 1.0 - min(subLine, 1.0);
// Combine
float alpha = (gridAlpha * 0.5 + subGridAlpha * 0.08) * edge;
alpha += gridAlpha * edge * pulse * 0.2;
// Radial glow near center
float centerGlow = smoothstep(15.0, 0.0, dist) * 0.04;
alpha += centerGlow * edge;
// Green color with slight variation
vec3 color = mix(vec3(0.0, 0.4, 0.02), vec3(0.0, 1.0, 0.25), pulse * 0.5 + gridAlpha * 0.5);
gl_FragColor = vec4(color, alpha);
}
`;
export function createWorld(scene) {
const worldGroup = new THREE.Group();
// ---- Ground Plane with Grid Shader ----
const groundGeom = new THREE.PlaneGeometry(120, 120, 1, 1);
groundGeom.rotateX(-Math.PI / 2);
const gridMaterial = new THREE.ShaderMaterial({
vertexShader: gridVertexShader,
fragmentShader: gridFragmentShader,
uniforms: {
uTime: { value: 0 },
uRadius: { value: 50 },
},
transparent: true,
depthWrite: false,
side: THREE.DoubleSide,
});
const groundMesh = new THREE.Mesh(groundGeom, gridMaterial);
groundMesh.position.y = -0.01;
groundMesh.renderOrder = -1;
worldGroup.add(groundMesh);
// ---- Dark solid floor underneath ----
const floorGeom = new THREE.CircleGeometry(52, 64);
floorGeom.rotateX(-Math.PI / 2);
const floorMat = new THREE.MeshBasicMaterial({ color: 0x030503, transparent: true, opacity: 0.9 });
const floorMesh = new THREE.Mesh(floorGeom, floorMat);
floorMesh.position.y = -0.05;
worldGroup.add(floorMesh);
// ---- THE CORE — Central Pillar ----
const coreGroup = new THREE.Group();
coreGroup.name = 'core';
// Main pillar - octagonal prism
const pillarGeom = new THREE.CylinderGeometry(1.2, 1.5, 14, 8, 1);
const pillarMat = new THREE.MeshBasicMaterial({
color: 0x00ff41,
wireframe: true,
transparent: true,
opacity: 0.3,
});
const pillar = new THREE.Mesh(pillarGeom, pillarMat);
pillar.position.y = 7;
coreGroup.add(pillar);
// Inner glowing core
const innerGeom = new THREE.CylinderGeometry(0.6, 0.8, 12, 8, 1);
const innerMat = new THREE.MeshBasicMaterial({
color: 0x00ff41,
transparent: true,
opacity: 0.6,
});
const inner = new THREE.Mesh(innerGeom, innerMat);
inner.position.y = 7;
coreGroup.add(inner);
// Floating rings around core
for (let i = 0; i < 3; i++) {
const ringGeom = new THREE.TorusGeometry(2.2 + i * 0.6, 0.04, 8, 32);
const ringMat = new THREE.MeshBasicMaterial({
color: 0x00ff41,
transparent: true,
opacity: 0.4 - i * 0.1,
});
const ring = new THREE.Mesh(ringGeom, ringMat);
ring.position.y = 4 + i * 4;
ring.rotation.x = Math.PI / 2 + (i * 0.2);
ring.userData.ringIndex = i;
coreGroup.add(ring);
}
// Core base glow
const baseGlowGeom = new THREE.CylinderGeometry(2.5, 3, 0.3, 8, 1);
const baseGlowMat = new THREE.MeshBasicMaterial({
color: 0x00ff41,
transparent: true,
opacity: 0.15,
});
const baseGlow = new THREE.Mesh(baseGlowGeom, baseGlowMat);
baseGlow.position.y = 0.15;
coreGroup.add(baseGlow);
// Point light at core
const coreLight = new THREE.PointLight(0x00ff41, 2, 30);
coreLight.position.y = 7;
coreGroup.add(coreLight);
worldGroup.add(coreGroup);
// ---- Ambient lighting ----
const ambient = new THREE.AmbientLight(0x112211, 0.3);
worldGroup.add(ambient);
// Dim directional for slight form
const dirLight = new THREE.DirectionalLight(0x00ff41, 0.15);
dirLight.position.set(10, 20, 10);
worldGroup.add(dirLight);
// ---- Green fog ----
scene.fog = new THREE.FogExp2(0x020502, 0.012);
scene.add(worldGroup);
return {
worldGroup,
gridMaterial,
coreGroup,
coreLight,
update(time, delta) {
// Update grid pulse
gridMaterial.uniforms.uTime.value = time;
// Rotate core slowly
coreGroup.rotation.y = time * 0.15;
// Pulse core light
coreLight.intensity = 1.5 + Math.sin(time * 2) * 0.5;
// Animate rings
coreGroup.children.forEach(child => {
if (child.userData.ringIndex !== undefined) {
const i = child.userData.ringIndex;
child.rotation.z = time * (0.2 + i * 0.1);
child.position.y = 4 + i * 4 + Math.sin(time * 0.8 + i) * 0.3;
}
});
// Pulse inner core opacity
inner.material.opacity = 0.4 + Math.sin(time * 3) * 0.2;
},
dispose() {
worldGroup.traverse(obj => {
if (obj.geometry) obj.geometry.dispose();
if (obj.material) {
if (Array.isArray(obj.material)) obj.material.forEach(m => m.dispose());
else obj.material.dispose();
}
});
scene.remove(worldGroup);
}
};
}