Three.js From Zero · Article s0-04
3D Text Playground
3D Text Playground is Article s0-04 of Three.js From Zero, a MasterAllArts free interactive lesson for artists learning creative 3D on the web.
Season 0 · Article 04 · Quick Wins
Drop your name into 3D — TextGeometry with the helvetiker font, bevels, extrusion, and a swirling material. The "first 3D thing I made and screenshotted" demo. Type your own text in the box.
What TextGeometry is and isn't
TextGeometry turns a font file into real 3D geometry — every glyph becomes a mesh you can light, shadow, transform. That's powerful and expensive. For body copy or labels you want SDF text (Article S7-08); for hero text and one-off badges, TextGeometry is the right answer.
Step 1 — Load the font
Three.js fonts are JSON files (typeface.json format). The classic helvetiker ships with Three.js examples and is available from the CDN. Use FontLoader:
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
const loader = new FontLoader();
loader.load(
'https://unpkg.com/three@0.170.0/examples/fonts/helvetiker_regular.typeface.json',
(font) => { /* font ready, build text */ },
);
The callback hands you a Font object. Keep a reference — you'll re-use it every time the user changes their text.
Step 2 — Build the geometry
const geo = new TextGeometry('Three.js', {
font,
size: 1, // glyph height in world units
depth: 0.25, // extrusion depth (used to be `height` in older versions)
curveSegments: 6, // glyph curve smoothness (4-12 sweet spot)
bevelEnabled: true,
bevelThickness: 0.03,
bevelSize: 0.015,
bevelSegments: 3,
});
geo.center(); // moves geometry origin to its bounding-box center
That geo.center() at the end is the difference between "text rotates around its corner" and "text rotates around its middle." Always call it for hero text.
height → depth. Old tutorials use height; both still work on r170 (height is deprecated and warns). Use depth.Step 3 — Material that earns the 3D
Flat MeshBasicMaterial on TextGeometry looks terrible — the whole point of extrusion is to catch light. Use MeshStandardMaterial with some metalness and roughness:
const material = new THREE.MeshStandardMaterial({
color: '#ec4899',
metalness: 0.7,
roughness: 0.2,
});
const mesh = new THREE.Mesh(geo, material);
scene.add(mesh);
The bevel + metallic surface is what makes the text feel premium. Without the bevel, the edges are razor sharp and look CG-cheap.
Step 4 — Regenerate on change, dispose the old
let textMesh = null;
function buildText(str, opts) {
if (textMesh) {
textMesh.geometry.dispose();
scene.remove(textMesh);
}
const geo = new TextGeometry(str || ' ', { font, ...opts });
geo.center();
textMesh = new THREE.Mesh(geo, material);
scene.add(textMesh);
}
Same disposal pattern as the galaxy generator — change-on-input means dispose-on-change. Note the str || ' ' guard: empty strings throw inside TextGeometry's path builder.
Step 5 — Make it move
In the loop, gently sway the text. A small Y rotation gives the bevel light something to reflect off:
renderer.setAnimationLoop((t) => {
if (textMesh) {
textMesh.rotation.y = Math.sin(t * 0.0006) * 0.25;
textMesh.rotation.x = Math.sin(t * 0.0004) * 0.1;
}
renderer.render(scene, camera);
});
Common first-time pitfalls
MeshStandardMaterial requires illumination — add an ambient + directional pair (intensity 0.3 / 1.0 is a good starting point).bevelSegments from 3 to 5–8 for smoother bevel curves. Don't go higher — vertex count explodes.geo.center(), or you set mesh.position before calling it. Center first, then position.Exercises
- Per-letter animation. Build one TextGeometry per character, position them sequentially, then stagger their rotations by index for a wave effect.
- Material swap on click. Three materials (matte plastic, gold metal, glass via
MeshPhysicalMaterialwith transmission). Cycle through them on canvas click. - Drop your name as a logo. Replace the placeholder, tighten the camera, screenshot it, ship as your portfolio header. That's the whole point of this article.
UP NEXT
S0-05 — Earth Shader → A spinning planet with atmospheric scattering and animated clouds. Custom shader territory.