Skip to content

Text3D

TextGeometry is one of the ways we can add 3D text in our scene.

However, it is not part of the core of ThreeJS. So to use it you would need to import it from the three/addons/controls/TextGeometry module.

This creates a problem because TresJS automatically creates a catalog of the core of Three so you can use them as components.

Fortunately, TresJS provides a way to extend the catalog of components. You can do it by using the extend method from the core library.

For more information about extending your TresJS catalog, refer to the extending section.

Using TextGeometry

To use TextGeometry you need to import it from the three/addons/geometries/TextGeometry module.

js
import { TextGeometry } from 'three/addons/geometries/TextGeometry'

Then you need to extend the catalogue of components using the extend method.

js
import { extend } from '@tresjs/core'
import { TextGeometry } from 'three/addons/geometries/TextGeometry'

extend({ TextGeometry })

TextGeometry requires only one argument - the font. You can find an example below.

js
const fontPath = 'https://raw.githubusercontent.com/Tresjs/assets/main/fonts/FiraCodeRegular.json'

const loader = new FontLoader()

const font = await new Promise((resolve, reject) => {
  try {
    loader.load(fontPath, (font) => {
      resolve(font)
    })
  }
  catch (error) {
    reject(console.error('cientos', error))
  }
})

Next you can use the TresTextGeometry component inside a TresMesh in your scene

vue
<template>
  <TresCanvas
    shadows
    alpha
  >
    <TresMesh>
      <TresTextGeometry
        :args="['TresJS', { font, ...fontOptions }]"
        center
      />
    </TresMesh>
  </TresCanvas>
</template>

then as in the example you can pass an object with the desired configurations.

ts
const fontOptions = {
  size: 0.5,
  height: 0.2,
  curveSegments: 5,
  bevelEnabled: true,
  bevelThickness: 0.05,
  bevelSize: 0.02,
  bevelOffset: 0,
  bevelSegments: 4,
}

We can also pass a matcapTexture to add final details, using the TresMeshNormalMaterial inside the TresMesh.

html
<script setup lang="ts">
  const matcapTexture = await useTexture([
    'https://raw.githubusercontent.com/Tresjs/assets/main/textures/matcaps/7.png',
  ])
</script>

<template>
  <TresMesh>
    <TresTextGeometry :args="['TresJS', { font, ...fontOptions }]" center />
    <TresMeshNormalMaterial :matcap="matcapTexture" />
  </TresMesh>
</template>

So the final code would look something like this:

vue
<script setup lang="ts">
import MyText from './MyText.vue'
</script>

<template>
  <TresCanvas
    clear-color="#82DBC5"
    shadows
    alpha
  >
    <TresPerspectiveCamera :position="[11, 11, 11]" />
    <OrbitControls />
    <Suspense>
      <MyText />
    </Suspense>
  </TresCanvas>
</template>
vue
<script setup lang="ts">
import { extend } from '@tresjs/core'
import { TextGeometry } from 'three/addons/geometries/TextGeometry'
import { FontLoader } from 'three/addons/loaders/FontLoader'
import { useTexture } from '/@/composables'

extend({ TextGeometry })

const fontPath = 'https://raw.githubusercontent.com/Tresjs/assets/main/fonts/FiraCodeRegular.json'

const fontOptions = {
  size: 0.5,
  height: 0.2,
  curveSegments: 5,
  bevelEnabled: true,
  bevelThickness: 0.05,
  bevelSize: 0.02,
  bevelOffset: 0,
  bevelSegments: 4,
}

const loader = new FontLoader()

const font = await new Promise((resolve, reject) => {
  try {
    loader.load(fontPath, (font) => {
      resolve(font)
    })
  }
  catch (error) {
    reject(console.error('cientos', error))
  }
})

const matcapTexture = await useTexture(['https://raw.githubusercontent.com/Tresjs/assets/main/textures/matcaps/7.png'])
</script>

<template>
  <TresMesh>
    <TresTextGeometry
      :args="['TresJS', { font, ...fontOptions }]"
      center
    />
    <TresMeshNormalMaterial :matcap="matcapTexture" />
  </TresMesh>
</template>

We know this seems like a lot of work, but good news is, there is a much more simple way

Text3D from cientos

The cientos package provides a component called <Text3D />, which is a wrapper of the TextGeometry from the three-stdlib module.

The nicest part? You don't need to extend the catalog and just pass the font argument. It just works. 💯 (if not text is provided, the text will be TresJS)

vue
<script setup lang="ts">
import { Text3D } from '@tresjs/cientos'
</script>

<template>
  <TresCanvas
    shadows
    alpha
  >
    <Suspense>
      <Text3D :font="fontPath" />
    </Suspense>
  </TresCanvas>
</template>

We can pass the options as props

html
<Text3D :font="fontPath" :text="my 3d text" :size="0.8" />

in case the options are not provided, the default values will be:

size: 0.5,
height: 0.2,
curveSegments: 5,
bevelEnabled: true,
bevelThickness: 0.05,
bevelSize: 0.02,
bevelOffset: 0,
bevelSegments: 4,

By default text in ThreeJS starts at the mesh initial position, so it's [0,0,0] and the text will start there but we can center it by just passing the flag "center"

vue
<Text3D :font="fontPath" :text="my 3d text" center />