Navigate

Search topics across all sections

GitHub
Text & HTML

Text3D

Ever seen a neon sign glowing in a shop window? The letters have real depth and thickness -- they pop out from the wall. Text3D works the same way. You pick a font, extrude it into a 3D shape, and it floats in your scene like a glowing sign you can walk around.

You add a Text3D component with your font file, but the text either doesn't show up at all, or it's shoved way off to the right side of the screen. You can barely see the edge of the first letter.

terminal
Text3D geometry renders but is not centered. Text starts at origin (0,0,0) and extends to the right, appearing partially off-screen.

Real-world

Imagine you are making a neon sign for a coffee shop. You start with a flat font file -- that is your blueprint. Then you send it to the sign maker who bends glass tubes into each letter and gives them real depth and thickness. Finally, you hang the sign in the window.

Text3D follows the exact same process: take a font, extrude it into 3D geometry with depth and optional bevels, then place it in your scene. The result is real geometry with vertices that can cast shadows, reflect light, and be made of any material you want -- chrome, glass, neon glow, you name it.

Font File

.ttf or .otf

Facetype.js

Convert to JSON

Text3D

Extrude into 3D

Material

Apply a surface

Neon Sign!

Visible in scene

Building Your Neon Sign

Let's craft a 3D title step by step. You only need three things: a font in JSON format, the Text3D component, and a material to paint it with.

Step 1: Convert your font

Text3D cannot read .ttf files directly. Head over to the Facetype.js converter, upload your font, and download the JSON file. Drop it into your /public/fonts/ folder.

Step 2: Create centered 3D text

Title.tsxTSX
<Center>
  <Text3D font="/fonts/Inter_Bold.json" size={1} height={0.2}>
    Hello R3F
    <meshStandardMaterial color="royalblue" />
  </Text3D>
</Center>

The Center wrapper is important. Without it, Text3D starts drawing from the left edge of the origin, like typing on a page. Center shifts everything so the text sits right in the middle of your scene.

Step 3: Add bevels for polish

BeveledSign.tsxTSX
<Text3D
  font="/fonts/Inter_Bold.json"
  size={1.5}
  height={0.3}
  bevelEnabled
  bevelThickness={0.02}
  bevelSize={0.02}
  bevelSegments={3}
>
  NEON
  <meshPhysicalMaterial metalness={0.9} roughness={0.05} />
</Text3D>

Bevels round the edges of each letter, like a real sign maker smoothing out the glass tubes. Keep bevelSegments low (3-5) to avoid generating too many triangles.

What you just learned

Text3D creates real 3D geometry from a font -- just like a neon sign has real depth and thickness.

You must convert fonts to typeface.json format using Facetype.js before Text3D can use them.

Always wrap Text3D in <Center> to prevent the text from drifting off to the side.

Bevels smooth the edges of letters, but high segment counts can create performance issues.

For text that changes frequently (counters, labels), use the flat <Text> component instead.

Question

If Text3D creates real geometry like a box or sphere, what happens when you try to update the text every frame? And why would that be different from just rotating the text?

Think about it...

You need to build a 3D scoreboard that updates the score every second. Should you use Text3D or the flat Text component?

Hint: Think about what 'real 3D geometry' means when the content changes...

Try These Challenges

Put what you learned into practice. Try each challenge in the demo above using the Leva controls, then check the solution.

Try This!

Beginner

Type your name in the text field

Try This!

Beginner

Set metalness to 1 — chrome text!

Try This!

Beginner

Max rotationSpeed — spinning sign

These are the patterns that trip up developers most often. Switch between Wrong and Fixed to compare the code side by side.

1
Text appears off-screen or at the edge
Forgetting to wrap Text3D in <Center>
Don't do this
Title.tsxTSX
<Text3D font="/fonts/Inter_Bold.json" size={1} height={0.2}>
  Hello R3F
  <meshStandardMaterial color="royalblue" />
</Text3D>
Text3D geometry starts from the bottom-left corner, like typing on a page. Without <Center>, the origin is at the left edge and the text drifts off to the right. Always wrap it in a <Center> component to auto-center on all axes.
2
Using a .ttf font file directly
Text3D requires typeface.json, not TTF/OTF
Don't do this
FontFormat.tsxTSX
<Text3D font="/fonts/Inter-Bold.ttf" size={1} height={0.2}>
  Hello
  <meshStandardMaterial />
</Text3D>
Text3D uses Three.js TextGeometry, which requires fonts in typeface.json format. Convert your fonts using the Facetype.js online tool and place the JSON in your public folder. The flat <Text> component from drei does accept TTF/OTF directly.
3
Dynamically changing text causes lag
Text3D rebuilds geometry on every content change
Don't do this
DynamicText.tsxTSX
function Counter() {
  const [count, setCount] = useState(0)
  useFrame(() => setCount(c => c + 1))

  return (
    <Text3D font="/fonts/Inter_Bold.json">
      {String(count)}
      <meshStandardMaterial />
    </Text3D>
  )
}
Text3D creates real 3D geometry with vertices. Changing the text forces a full geometry rebuild every frame, which is extremely expensive. For text that updates frequently, use the flat <Text> component from drei instead. It uses SDF rendering and handles dynamic content efficiently.

Best Practices

Always Use Center

Wrap Text3D in Center to prevent the text from appearing off-screen. Text3D geometry starts from the left edge by default, so centering is almost always what you want.

Keep Segments Low

Use curveSegments=12 and bevelSegments=3 as defaults. Each additional segment multiplies the vertex count. Only bump these up for hero text the camera gets very close to.

Reserve for Hero Elements

Use Text3D for titles, logos, and decorative text only. For labels, annotations, or anything that updates, the flat Text component is orders of magnitude cheaper to render.

Animate Transforms, Not Content

Moving, rotating, and scaling Text3D is free. Changing the actual text string forces a full geometry rebuild. If you need animated content, swap in the flat Text component.