Three.js From Zero · Article s7-08
S7-08 Text in 3D
Text Rendering in 3D
Crisp text at any distance or zoom. Canvas texture blurs when scaled. Bitmap fonts pixelate. MSDF (multi-channel signed distance field) gives you vector-sharp text at any scale for ~20KB.
1. The text-in-3D problem
- TextGeometry: extrudes a font into 3D mesh. Heavy, crisp, static.
- CanvasTexture: draw text on a canvas, map to a plane. Fast, blurry when scaled up.
- Bitmap fonts: pre-baked glyph atlas, pixelated at scale.
- SDF/MSDF: signed distance field. Crisp at any scale. Best.
2. Signed Distance Field (SDF)
Each texel stores the distance to the nearest glyph edge. Shader: threshold at 0.5 → filled pixel. Because it's a continuous field, bilinear filtering gives smooth edges at any zoom.
// Fragment
float d = texture(uFontAtlas, vUv).r;
float alpha = smoothstep(0.5 - fwidth, 0.5 + fwidth, d);
gl_FragColor = vec4(color, alpha);
3. MSDF (multi-channel)
Single-channel SDF rounds corners. Multi-channel stores three distance fields in RGB, each for a different edge direction. Shader picks the median. Sharp corners preserved.
4. Troika Three Text (recommended)
import { Text } from 'troika-three-text';
const label = new Text();
label.text = 'Hello 3D!';
label.font = '/fonts/Inter.ttf';
label.fontSize = 0.3;
label.color = 0xffffff;
label.anchorX = 'center';
label.anchorY = 'middle';
label.sync(); // build MSDF atlas in worker
scene.add(label);
Builds the atlas on the fly from any TTF. Handles wrapping, alignment, clipping. 20kb library.
5. TextGeometry (built-in, heavy)
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
const font = await new FontLoader().loadAsync('helvetiker.json');
const geo = new TextGeometry('Hello!', { font, size: 0.3, height: 0.05 });
scene.add(new THREE.Mesh(geo, material));
Extruded 3D letters. Great for logos. Heavy and not re-editable.
6. Live demo
Demo uses CanvasTexture for portability. In production use troika-three-text for MSDF.
7. When each wins
| Method | Use |
|---|---|
| TextGeometry | 3D logo, decorative title |
| CanvasTexture | Quick label, low-frequency updates |
| Troika Text (MSDF) | Dynamic labels, UI text, production |
| three-bmfont-text | Legacy, many codebases |
| HTML overlay | Small amounts, screen-space |
8. Text on curves
Troika can lay text along a spline. Also supports maxWidth wrapping, overflow clipping, per-glyph callbacks.
9. Emoji & non-Latin
- TrueType fonts handle most scripts out of box.
- Emoji: colored fonts (COLRv1) work in Troika.
- RTL (Arabic/Hebrew): Troika has a bidi option.
- CJK: atlas can balloon. Preload subset for efficiency.
10. Takeaways
- MSDF is the modern way. Vector-sharp at any scale.
- Troika Three Text: drop-in, handles everything.
- TextGeometry for 3D extruded logos only.
- CanvasTexture for quick + low-update labels.
- HTML overlay for small screen-space text.