Three.js Text: 3D Text, SDF Text & troika-three-text

Three.js has two main ways to render real text in a 3D scene: TextGeometry, which extrudes a font into actual 3D geometry (good for chunky, extruded logo-style text), and troika-three-text, a community library that renders crisp, resolution-independent text using signed distance fields (SDF), which is the better choice for anything readable like labels, UI text or paragraphs. For text that should behave like normal HTML (selectable, accessible, styled with CSS), an HTML overlay positioned over the canvas is often simpler than any 3D text approach at all.

Last updated . Verified against three.js r181.

Read the FAQJump to code

TextGeometry: real extruded 3D text

TextGeometry (from the examples/addons) converts a loaded font (a Three.js-specific JSON font format, converted from a TTF/OTF via a conversion tool) into actual extruded 3D geometry: real depth, real bevels, a real mesh you can light and shadow like any other object. This is the right tool specifically when text needs to look and behave like a 3D object: a logo, an extruded sign, text that catches light and casts shadows.

The tradeoffs: geometry-heavy for long text (every character is real triangles), doesn't scale cleanly to small sizes (extruded bevels can look muddy at a distance), and re-generating the geometry for dynamically changing text is relatively expensive.

troika-three-text: crisp, scalable SDF text

troika-three-text renders text using signed distance fields: a texture-based technique that stays crisp at any scale or distance, similar to how vector fonts render sharply at any zoom level on the web, unlike a raster image. It's dramatically cheaper than TextGeometry for text that needs to update frequently (a score counter, a live data label) and supports standard typography features (word wrap, alignment, custom fonts via a normal font file) that TextGeometry doesn't.

For any text meant to be read rather than admired as a 3D object (labels, HUD text, captions in a 3D scene), this is almost always the better choice over TextGeometry.

When an HTML overlay is simpler than either

If text needs to be selectable, screen-reader accessible, styled with CSS, or interactive in ways 3D text makes needlessly hard (a real <button>, a text input), positioning a regular HTML element over the canvas (computed from a 3D world position projected to 2D screen coordinates) is often the pragmatic answer. React Three Fiber's drei library ships an <Html> component for exactly this. It's not "true" 3D text (it won't be occluded by 3D geometry correctly without extra work), but for UI-style text it avoids solving problems 3D text libraries weren't designed for.

Code

TextGeometry: extruded 3D text (r181)
1import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js'
2import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js'
3
4new FontLoader().load('/fonts/helvetiker_bold.typeface.json', (font) => {
5 const geometry = new TextGeometry('HELLO', {
6 font, size: 1, depth: 0.2, curveSegments: 8, bevelEnabled: true, bevelThickness: 0.02, bevelSize: 0.01,
7 })
8 const mesh = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial({ color: 0xffffff, metalness: 0.3 }))
9 scene.add(mesh)
10})
troika-three-text: crisp SDF text
1import { Text } from 'troika-three-text'
2
3const text = new Text()
4text.text = 'Score: 1,240'
5text.fontSize = 0.5
6text.color = 0xffffff
7text.anchorX = 'center'
8text.anchorY = 'middle'
9scene.add(text)
10text.sync() // required after changing text/properties

Learn this properly

Learn Practical TSL

Your First Node Material

Style extruded 3D text with a node material for effects like animated gradients.

Start the lesson (6 minutes)

Frequently asked questions

What's the best way to add text in Three.js?

For readable labels or UI-style text, troika-three-text (crisp SDF rendering, cheap to update). For extruded, logo-style 3D text that should catch light and cast shadows, TextGeometry. For fully interactive or accessible text, an HTML overlay positioned over the canvas is often simplest.

Why does TextGeometry text look blurry or muddy at a distance?

TextGeometry is real extruded polygon geometry, and its bevels and detail don't hold up well at small screen sizes or a distance. This is one of the main reasons troika-three-text (SDF-based, resolution-independent) is usually a better fit for readable text.

Can Three.js text update dynamically without a performance cost?

troika-three-text handles frequent text updates (like a live score or timer) cheaply. TextGeometry requires regenerating the mesh geometry on every text change, which is comparatively expensive for frequently updating text.

Keep reading