Creating the Text Sphere

There's something honest about ASCII art: no gradients, no anti-aliasing, just characters on a grid. But it sits flat, stuck in terminal windows. I wanted to change that. What if the characters could float in 3D space instead?

Why a Sphere

A sphere made sense. It's mathematically clean, easy to recognize, and rotates well. The plan: scatter text characters across its surface, then spin the whole thing.

The Tools

Three.js handles the 3D rendering. I considered pure CSS or raw WebGL, but Three.js hits the sweet spot between control and convenience.

Each character is a Sprite, not mesh geometry. Sprites let me adjust individual opacity and transformations without killing performance.

const sprite = new THREE.Sprite(material);
sprite.position.copy(points[i]);
sprite.scale.set(1.0, 1.0, 1);

The Hard Part: Even Distribution

Scattering points evenly across a sphere is tricky. Random placement looks messy. Grid mapping creates obvious patterns. The solution: the Fibonacci lattice, the same spiral pattern you see in sunflowers.

const fibonacciSphere = (samples: number) => {
  const points = [];
  const phi = Math.PI * (3 - Math.sqrt(5));
  for (let i = 0; i < samples; i++) {
    const y = 1 - (i / (samples - 1)) * 2;
    const radius = Math.sqrt(1 - y * y);
    const theta = phi * i;
    const x = Math.cos(theta) * radius;
    const z = Math.sin(theta) * radius;
    points.push(new THREE.Vector3(x, y, z).multiplyScalar(10));
  }
  return points;
};

Each character finds its place without clumping or obvious rows.

Making It Feel 3D

Static characters look flat even when arranged in 3D. The fix: fade characters based on their angle to the camera. Characters facing you appear solid. Characters facing away go transparent.

const worldNormal = sprite.userData.normal.clone()
  .applyQuaternion(sceneData.spriteGroup.quaternion);
const dot = worldNormal.dot(cameraDirection);
const brightness = Math.max(0, -dot);
const frontOpacity = brightness * brightness;
sprite.material.opacity = minOpacity + (1 - minOpacity) * frontOpacity;

Simple math, strong effect. Characters seem to emerge from and sink into the surface as the sphere rotates.

The Characters

Greetings from different languages float together on the surface. The circular elements use numbers, universal and language-neutral. Each character contributes to the shape while carrying its own meaning.

Keeping It Fast

Three.js scenes get heavy quickly. A few optimizations:

  • Cache textures to avoid redundant canvas operations
  • Share sprite materials where possible
  • Generate only the points needed
  • Clean up properly on unmount to prevent memory leaks

What I Learned

Constraints help. The monospace limitation forced creative solutions instead of blocking them. The component works because the characters feel like they belong in 3D, like they were always meant to float and spin.

Every rotation shows new arrangements. Your eye catches familiar letters in unfamiliar contexts. That discovery keeps it interesting.