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.