Troika Text
The troika-three-text package provides high quality text rendering in Three.js scenes, using signed distance fields (SDF) and antialiasing using standard derivatives.
Rather than relying on pre-generated SDF textures, this parses font files (.ttf, .otf, .woff) directly using Typr, and generates the SDF atlas for glyphs on-the-fly as they are used. It also handles proper kerning, ligature glyph substitution, right-to-left/bidirectional layout, joined scripts like Arabic, and will automatically load fallback fonts for full unicode coverage. All font parsing, SDF generation, and glyph layout is performed in a web worker to prevent frame drops.
Once the SDFs are generated, it assembles a geometry that positions all the glyphs, and patches any Three.js Material with the proper shader code for rendering the SDFs. This means you can still benefit from all the features of Three.js’s built-in materials like lighting, physically-based rendering, shadows, and fog.
Installation
npm install troika-three-text
Usage
import {Text} from 'troika-three-text'
You can then use the Text class like any other Three.js mesh:
// Create: const myText = new Text() myScene.add(myText) // Set properties to configure: myText.text = 'Hello world!' myText.fontSize = 0.2 myText.position.z = -2 myText.color = 0x9966FF // Update the rendering: myText.sync()
It’s a good idea to call the .sync() method after changing any properties that would affect the text’s layout. If you don’t, it will be called automatically on the next render frame, but calling it yourself can get the result sooner.
When you’re done with the Text instance, be sure to call dispose on it to prevent a memory leak:
myScene.remove(myText) myText.dispose()
Supported properties
Instances of Text support the following configuration properties:
text
The string of text to be rendered. Newlines and repeating whitespace characters are honored.
Default: none
anchorX
Defines the horizontal position in the text block that should line up with the local origin. Can be specified as a numeric x position in local units, a string percentage of the total text block width e.g. '25%', or one of the following keyword strings: 'left', 'center', or 'right'.
Default: 0
anchorY
Defines the vertical position in the text block that should line up with the local origin. Can be specified as a numeric y position in local units (note: down is negative y), a string percentage of the total text block height e.g. '25%', or one of the following keyword strings: 'top', 'top-baseline', 'top-cap', 'top-ex', 'middle', 'bottom-baseline', or 'bottom'.
Default: 0
clipRect
If specified, defines the [minX, minY, maxX, maxY] of a rectangle outside of which all pixels will be discarded. This can be used for example to clip overflowing text when whiteSpace='nowrap'.
Default: none
color
This is a shortcut for setting the color of the text’s material. You can use this if you don’t want to specify a whole custom material and just want to change its color.
Use the material property if you want to control aspects of the material other than its color.
Default: none – uses the color of the material
curveRadius
Defines a cylindrical radius along which the text’s plane will be curved. Positive numbers put the cylinder’s centerline (oriented vertically) that distance in front of the text, for a concave curvature, while negative numbers put it behind the text for a convex curvature. The centerline will be aligned with the text’s local origin; you can use anchorX to offset it.
Since each glyph is by default rendered with a simple quad, each glyph remains a flat plane internally. You can use glyphGeometryDetail to add more vertices for curvature inside glyphs.
Default: 0
depthOffset
This is a shortcut for setting the material’s polygonOffset and related properties, which can be useful in preventing z-fighting when this text is laid on top of another plane in the scene. Positive numbers are further from the camera, negatives closer.
Be aware that while this can help with z-fighting, it does not affect the rendering order; if the text renders before the content behind it, you may see antialiasing pixels that appear too dark or light. You may need to also change the text mesh’s renderOrder, or set its z position a fraction closer to the camera, to ensure the text renders after background objects.
Default: 0
direction
Sets the base direction for the text. The default value of “auto” will choose a direction based on the text’s content according to the bidi spec. A value of “ltr” or “rtl” will force the direction.
Default: 'auto'
fillOpacity
Controls the opacity of just the glyph’s fill area, separate from any configured strokeOpacity, outlineOpacity, and the material’s opacity. A fillOpacity of 0 will make the fill invisible, leaving just the stroke and/or outline.
Default: 1
font
The URL of a custom font file to be used. Supported font formats are:
- .ttf
- .otf
- .woff (.woff2 is not supported)
Default: The Roboto font loaded from Google Fonts CDN
fontSize
The em-height at which to render the font, in local world units.
Default: 0.1
fontStyle
Either "italic" or "normal". Currently only used to select the preferred style for the fallback Unicode fonts.
Default: "normal"
fontWeight
A numeric font weight, "normal", or "bold". Currently only used to select the preferred weight for the fallback Unicode fonts.
Default: "normal"
glyphGeometryDetail
The number of vertical/horizontal segments that make up each glyph’s rectangular plane. This can be increased to provide more geometrical detail for custom vertex shader effects, for example.
Default: 1
gpuAccelerateSDF
When true, the SDF generation process will be GPU-accelerated with WebGL when possible, making it much faster especially for complex glyphs, and falling back to a JavaScript version executed in web workers when support isn’t available. It should automatically detect support, but it’s still somewhat experimental, so you can set it to false to force it to use the JS version if you encounter issues with it.
Default: true
letterSpacing
Sets a uniform adjustment to spacing between letters after kerning is applied, in local world units. Positive numbers increase spacing and negative numbers decrease it.
Default: 0
lineHeight
Sets the height of each line of text. Can either be 'normal' which chooses a reasonable height based on the chosen font’s ascender/descender metrics, or a number that is interpreted as a multiple of the fontSize.
Default: 'normal'
material
Defines a Three.js Material instance to be used as a base when rendering the text. This material will be automatically replaced with a new material derived from it, that adds shader code to decrease the alpha for each fragment (pixel) outside the text glyphs, with antialiasing.
By default it will derive from a simple white `MeshBasicMaterial, but you can use any of the other mesh materials to gain other features like lighting, texture maps, etc.
Also see the color shortcut property.
Note that because your material instance is replaced by a derived material instance, any changes you make to your original material will not be reflected in the derived version. If you need to modify properties of the material afterward, be sure you get a new reference to the derived version:
// Bad: text.material = myOrigMaterial myOrigMaterial.opacity = 0.5 // Good: text.material = myOrigMaterial text.material.opacity = 0.5