;
top of page

​BACK TO THE CHAPTER LIST >>

I Hand‑Crafted an Optical Universe That Responds to a Writer’s State

  • 3 days ago
  • 6 min read

Updated: 23 hours ago

I hand‑crafted an optical universe that responds to a writer’s working state,

and I dedicate this universe to everyone who writes quietly in the dark.


It is a digital cosmos that can be triggered and altered by the keyboard.

Every keystroke ignites a spark of starlight at the edge of space,

and that light travels across the vast structure before fading into the depths of the void.

When you slack off, the universe grows dim and silent;

when you surge with energy, the universe blazes with you.


You can even use a small external screen as a “universe monitor.”

While you write, it stays by your side—

a world that seems to breathe with you.


Sometimes, all a lonely writer needs

is a small joy like this, isn’t it.


And if you come up with better ideas or improvements, I’d love to see them.



Demo Preview


// ===== Keyboard Event =====
document.addEventListener("keydown", fireUserSignal);

// ===== Basic Setup =====
document.body.style.margin = "0";
document.body.style.overflow = "hidden";
const scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x05030a, 40, 260);

const camera = new THREE.PerspectiveCamera(
  60,
  window.innerWidth / window.innerHeight,
  0.1,
  500
);
camera.position.set(0, 0, 40);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(0x050308, 1);
document.body.appendChild(renderer.domElement);

// ===== Color Settings =====
const lineColor = new THREE.Color("#262b3a");
const autoSignalColor = new THREE.Color("#5a6b7a");
const userSignalMain = new THREE.Color("#e8ffff");
const userSignalExtra1 = new THREE.Color("#ff4fa8");
const userSignalExtra2 = new THREE.Color("#ffd45a");

// ===== Lighting =====
scene.add(new THREE.AmbientLight(0x404060, 1.4));
const pointLight = new THREE.PointLight(0x88ccff, 2.5, 320);

scene.add(pointLight);

// ===== Line Structure: Fractal Harmonic Field (Cosmic Flow) + Distribution Refinement =====
const LINE_COUNT = 130;
const AUTO_SIGNAL_COUNT = 80;
const lines = [];
const autoSignals = [];
const userSignals = [];

const lineMat = new THREE.LineBasicMaterial({
  color: lineColor,
  transparent: true,
  opacity: 0.85
});

// Fractal Harmonic parameters (avoid stacking, maintain flow)
const FH_FREQ1 = 4.2;
const FH_FREQ2 = 7.9;
const FH_FREQ3 = 13.3;
const FH_AMP1 = 3.2;
const FH_AMP2 = 2.1;
const FH_AMP3 = 1.4;

for (let i = 0; i < LINE_COUNT; i++) {
  const points = [];

  // Base angle: evenly distributed + slight nonlinear offset to avoid empty regions
  const angleBase =
    (i / LINE_COUNT) * Math.PI * 2 + Math.sin(i * 0.7) * 0.2;

  const baseRadius = 50;
  const depth = 260;

  for (let j = 0; j <= 320; j++) {
    const t = j / 320;

    // Radius: stable ring at the front, nonlinear contraction toward the back
    let radius;
    if (t < 0.03) {
      radius = baseRadius;
    } else {
      const radialMain = baseRadius * Math.pow(1.0 - t, 1.18);
      const radialShell = 8 * (1.0 - t);
      radius = radialMain + radialShell;
    }

    // Angle: directional twist of the Cosmic Flow
    let angle = angleBase;
    if (t > 0.03) {
      angle += t * 1.1;
      angle += Math.sin(t * 3.5 + i * 0.27) * 0.18;
      angle += Math.cos(t * 4.7 - i * 0.19) * 0.13;
    }

    let x = Math.cos(angle) * radius;
    let y = Math.sin(angle) * radius;

    // Fractal Harmonic: multi-frequency, multi-scale flow
    if (t > 0.03) {
      const fh1 =
        Math.sin(t * FH_FREQ1 + i * 0.31) * FH_AMP1 +
        Math.cos(t * FH_FREQ1 * 0.7 - i * 0.23) * (FH_AMP1 * 0.6);
      const fh2 =
        Math.sin(t * FH_FREQ2 + i * 0.41) * FH_AMP2 +
        Math.cos(t * FH_FREQ2 * 0.8 - i * 0.37) * (FH_AMP2 * 0.7);
      const fh3 =
        Math.sin(t * FH_FREQ3 + i * 0.53) * FH_AMP3 +
        Math.cos(t * FH_FREQ3 * 0.9 - i * 0.29) * (FH_AMP3 * 0.8);

      const flow = fh1 * 0.7 + fh2 * 0.6 + fh3 * 0.5;
      x += flow * 0.9;
      y += flow * 0.7;
    }

    // Depth: nonlinear + slight offset per line to avoid heavy intersections
    const z =
      -Math.pow(t, 1.22) * depth +
      40 +
      Math.sin(i * 0.3) * 2.5;

    points.push(new THREE.Vector3(x, y, z));
  }

  const geo = new THREE.BufferGeometry().setFromPoints(points);
  const line = new THREE.Line(geo, lineMat);
  scene.add(line);
  lines.push({ line, points });
}

// ===== Background Signals (dim, slow) =====
const autoGeo = new THREE.SphereGeometry(0.18, 12, 12);

function createAutoSignal() {
  const mat = new THREE.MeshBasicMaterial({
    color: autoSignalColor,
    transparent: true,
    opacity: 0.4
  });
  const mesh = new THREE.Mesh(autoGeo, mat);
  scene.add(mesh);

  const lineIndex = Math.floor(Math.random() * lines.length);
  const speed = 0.005 + Math.random() * 0.004;

  return {
    mesh,
    lineIndex,
    t: Math.random(),
    speed
  };
}

for (let i = 0; i < AUTO_SIGNAL_COUNT; i++) {
  autoSignals.push(createAutoSignal());
}

// ===== User Signals (light beam + trail) =====
const userGeo = new THREE.CylinderGeometry(0.05, 0.05, 1.8, 12);
const TRAIL_POINTS = 16;

function fireUserSignal() {
  if (!lines.length) return;

  let color = userSignalMain;
  const r = Math.random();
  if (r < 0.25) color = userSignalExtra1;
  else if (r < 0.5) color = userSignalExtra2;

  const mat = new THREE.MeshBasicMaterial({
    color,
    transparent: true,
    opacity: 1,
    blending: THREE.AdditiveBlending
  });
  const mesh = new THREE.Mesh(userGeo, mat);
  mesh.rotation.x = Math.PI / 2;
  scene.add(mesh);

  const lineIndex = Math.floor(Math.random() * lines.length);
  const lineData = lines[lineIndex];
  if (!lineData || !lineData.points || lineData.points.length < 2) {
    scene.remove(mesh);
    return;
  }

  const startPoint = lineData.points[0];
  mesh.position.copy(startPoint);
  const baseSpeed = 0.0012 + Math.random() * 0.0015;

  const trailPositions = new Float32Array(TRAIL_POINTS * 3);
  for (let i = 0; i < TRAIL_POINTS; i++) {
    trailPositions[i * 3] = startPoint.x;
    trailPositions[i * 3 + 1] = startPoint.y;
    trailPositions[i * 3 + 2] = startPoint.z;
  }

  const trailGeo = new THREE.BufferGeometry();
  trailGeo.setAttribute(
    "position",
    new THREE.BufferAttribute(trailPositions, 3)
  );
  const trailMat = new THREE.PointsMaterial({
    color,
    size: 0.22,
    transparent: true,
    opacity: 0.55,
    blending: THREE.AdditiveBlending,
    depthWrite: false
  });
  const trailPoints = new THREE.Points(trailGeo, trailMat);
  scene.add(trailPoints);

  userSignals.push({
    mesh,
    lineIndex,
    t: 0,
    baseSpeed,
    trailPositions,
    trailGeo,
    trailPoints
  });
}

window.addEventListener("keydown", () => {
  fireUserSignal();
});

// ===== Starfield Distribution =====
const starGeo = new THREE.BufferGeometry();
const starCount = 2000;
const starPositions = new Float32Array(starCount * 3);
const starColors = new Float32Array(starCount * 3);

const colorOptions = [
  new THREE.Color(0x99ccff),
  new THREE.Color(0xffffff),
  new THREE.Color(0xffddaa),
  new THREE.Color(0xff99cc)
];

for (let i = 0; i < starCount; i++) {
  // Slightly reduced radius, concentrated within view range
  const r = 140 + Math.random() * 80;
  const theta = Math.random() * Math.PI * 2;
  const phi = Math.acos(2 * Math.random() - 1);

  // Stars mainly distributed around Z ≈ -90
  const zOffset = -90;
  const x = r * Math.sin(phi) * Math.cos(theta);
  const y = r * Math.sin(phi) * Math.sin(theta);
  const z = r * Math.cos(phi) + zOffset;

  starPositions[i * 3] = x;
  starPositions[i * 3 + 1] = y;
  starPositions[i * 3 + 2] = z;

  const c = colorOptions[Math.floor(Math.random() * colorOptions.length)];
  starColors[i * 3] = c.r;
  starColors[i * 3 + 1] = c.g;
  starColors[i * 3 + 2] = c.b;
}

starGeo.setAttribute("position", new THREE.BufferAttribute(starPositions, 3));
starGeo.setAttribute("color", new THREE.BufferAttribute(starColors, 3));

const starMat = new THREE.PointsMaterial({
  size: 0.9,
  transparent: true,
  opacity: 1.0,
  vertexColors: true,
  blending: THREE.AdditiveBlending,
  depthWrite: false,
  depthTest: false
});

const stars = new THREE.Points(starGeo, starMat);
scene.add(stars);

// ===== Window Resize =====
window.addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

// ===== Animation =====
let t = 0;

function animate() {
  requestAnimationFrame(animate);

  t += 0.0018;

  // Camera motion
  camera.position.x = Math.sin(t * 1.4) * 6;
  camera.position.y = Math.sin(t * 0.9) * 4;
  camera.position.z = 40 + Math.sin(t * 0.6) * 4;
  camera.lookAt(0, 0, -90);

  // Starfield: slow rotation
  stars.rotation.z += 0.00025;

  // Background signals
  autoSignals.forEach((s) => {
    s.t += s.speed;
    if (s.t > 1) s.t = 0;

    const lineData = lines[s.lineIndex];
    const idx = Math.floor(s.t * (lineData.points.length - 1));
    const p = lineData.points[idx];

    s.mesh.position.copy(p);
    s.mesh.material.opacity = 0.2 + Math.pow(1.0 - s.t, 2.0) * 0.3;
  });

  // User signals
  for (let i = userSignals.length - 1; i >= 0; i--) {
    const s = userSignals[i];

    // Fixed speed: each beam keeps its own baseSpeed
    s.t += s.baseSpeed;

    if (s.t > 1) {
      scene.remove(s.mesh);
      scene.remove(s.trailPoints);
      userSignals.splice(i, 1);
      continue;
    }

    const lineData = lines[s.lineIndex];
    const idx = Math.floor(s.t * (lineData.points.length - 1));
    const p = lineData.points[idx];

    s.mesh.position.copy(p);

    const pulse = 0.12 * Math.sin(performance.now() * 0.01 + i);
    s.mesh.material.opacity =
      1.0 + Math.pow(1.0 - s.t, 2.0) * 1.1 + pulse;

    const tp = s.trailPositions;
    for (let k = TRAIL_POINTS - 1; k > 0; k--) {
      tp[k * 3] = tp[(k - 1) * 3];
      tp[k * 3 + 1] = tp[(k - 1) * 3 + 1];
      tp[k * 3 + 2] = tp[(k - 1) * 3 + 2];
    }
    tp[0] = p.x;
    tp[1] = p.y;
    tp[2] = p.z;

    s.trailGeo.attributes.position.needsUpdate = true;
  }

  renderer.render(scene, camera);
}

animate();



By VON(壹叔瘋神)

Comments


Copyright © 2025 VON(壹叔瘋神). All rights reserved.  
Operated under license by JIGEN Limited Liability Company
.

This website and its content are protected by applicable copyright laws and international treaties.

bottom of page