npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

r3f-webgpu-text

v1.0.2

Published

MSDF WebGPU text components for React Three Fiber.

Downloads

453

Readme

r3f-webgpu-text

Created by Anderson Mancini

Live demo: https://r3f-webgpu-text.vercel.app

MSDF WebGPU text components for React Three Fiber. Render crisp, scalable 3D text in WebGPU scenes with an API inspired by Drei's <Text />.

Built on top of three-msdf-text-utils, which provides MSDF geometry and WebGPU materials for vanilla Three.js. This package brings the same capabilities to R3F as ready-to-use React components.

Features

  • WebGPU-first — uses MSDFTextNodeMaterial from three-msdf-text-utils/webgpu
  • Drei-like API — familiar props: fontSize, anchorX, anchorY, maxWidth, lineHeight, etc.
  • Font caching — shared loader avoids duplicate fetches across instances
  • Performance modes — single text, batched instancing, and character-level instancing
  • TypeScript — full type definitions included

Requirements

  • React 18+
  • React Three Fiber 8+
  • Three.js 0.172+ with WebGPU support
  • A browser with WebGPU enabled
  • MSDF font atlas files (.json + .png)

Installation

npm install r3f-webgpu-text three-msdf-text-utils

You also need peer dependencies if not already installed:

npm install three @react-three/fiber react react-dom

Quick start

import * as THREE from 'three/webgpu'
import { Canvas, extend } from '@react-three/fiber'
import { WebGPUText } from 'r3f-webgpu-text'

extend(THREE)

function Scene() {
  return (
    <WebGPUText
      position={[0, 1, 0]}
      fontSize={0.5}
      color="#ffffff"
      fontData="/fonts/MyFont-msdf.json"
      fontAtlas="/fonts/MyFont.png"
    >
      Hello WebGPU
    </WebGPUText>
  )
}

export default function App() {
  return (
    <Canvas
      gl={async (props) => {
        const renderer = new THREE.WebGPURenderer(props)
        await renderer.init()
        return renderer
      }}
    >
      <Scene />
    </Canvas>
  )
}

Place your MSDF font files in your app's public/fonts/ folder (or any URL-accessible path).

Components

<WebGPUText />

Renders a single text label. Best for individual labels, titles, and UI elements.

<WebGPUText
  position={[0, 1, 0]}
  fontSize={0.5}
  color="#ffffff"
  anchorX="center"
  anchorY="middle"
  textAlign="center"
  lineHeight={1.1}
  letterSpacing={0}
  maxWidth={5}
  fontData="/fonts/Manrope-Medium-msdf.json"
  fontAtlas="/fonts/Manrope-Medium.png"
>
  Hello World
</WebGPUText>

| Prop | Type | Default | Description | |------|------|---------|-------------| | children | string | — | Text content | | position | [x, y, z] | [0, 0, 0] | World position | | rotation | [x, y, z] | [0, 0, 0] | Rotation in radians | | fontSize | number | 1 | Text size in world units | | color | string | "#ffffff" | Text color | | opacity | number | 1 | Text opacity | | anchorX | "left" \| "center" \| "right" \| number | "center" | Horizontal anchor | | anchorY | "top" \| "middle" \| "bottom" \| ... \| number | "middle" | Vertical anchor | | textAlign | "left" \| "center" \| "right" | "center" | Text alignment | | lineHeight | number | 1.1 | Line height multiplier | | letterSpacing | number | 0 | Letter spacing | | maxWidth | number | — | Max width before wrapping | | fontData | string | — | Path/URL to BMFont JSON | | fontAtlas | string | — | Path/URL to MSDF atlas PNG | | renderOrder | number | 0 | Render order | | visible | boolean | true | Visibility |

<WebGPUBatchedText />

Renders many text labels efficiently. Identical strings (same text, size, color, anchors) are grouped into a single InstancedMesh — one draw call per group.

<WebGPUBatchedText
  texts={[
    { text: "Hello", position: [0, 0, 0], fontSize: 0.5 },
    { text: "Hello", position: [2, 0, 0], fontSize: 0.5 },
    { text: "World", position: [4, 0, 0], fontSize: 0.5, color: "#ff6600" },
  ]}
  fontData="/fonts/Manrope-Medium-msdf.json"
  fontAtlas="/fonts/Manrope-Medium.png"
/>

| Prop | Type | Default | Description | |------|------|---------|-------------| | texts | BatchedTextItem[] | [] | Array of text configs | | fontData | string | — | Path/URL to BMFont JSON | | fontAtlas | string | — | Path/URL to MSDF atlas PNG | | defaultFontSize | number | 0.02 | Default font size for items | | defaultColor | string | "#ffffff" | Default color for items |

Each item in texts supports: text, position, rotation, scale, fontSize, color, anchorX, anchorY, textAlign, lineHeight, letterSpacing.

<WebGPUInstancedText />

Character-level instancing. Creates one InstancedMesh per unique character — roughly ~70 draw calls regardless of how many different text strings you render. Ideal for large numbers of labels (maps, dashboards, debug overlays).

<WebGPUInstancedText
  texts={[
    { text: "HELLO", position: [0, 0, 0] },
    { text: "WORLD", position: [1, 0, 0] },
  ]}
  lookAtCamera={true}
  fontData="/fonts/Manrope-Medium-msdf.json"
  fontAtlas="/fonts/Manrope-Medium.png"
/>

| Prop | Type | Default | Description | |------|------|---------|-------------| | texts | InstancedTextItem[] | [] | Array of text configs | | lookAtCamera | boolean | false | Billboard effect — text faces camera | | charset | string | alphanumeric + punctuation | Allowed characters | | fontData | string | — | Path/URL to BMFont JSON | | fontAtlas | string | — | Path/URL to MSDF atlas PNG | | defaultFontSize | number | 0.02 | Default font size | | defaultColor | string | "#ffffff" | Default color |

Performance guide

| Scenario | Component | Draw calls | |----------|-----------|------------| | 1–20 labels | <WebGPUText /> | 1 per label | | Many identical strings | <WebGPUBatchedText /> | 1 per unique string group | | Hundreds/thousands of different labels | <WebGPUInstancedText /> | ~1 per unique character |

Tips:

  • Use <WebGPUText /> for simple scenes and interactive labels
  • Use <WebGPUBatchedText /> when many texts share the same content and styling
  • Use <WebGPUInstancedText /> for dense label clouds (maps, data viz, debug text)
  • Always host font files locally — avoid loading fonts from remote URLs in production

Generating MSDF fonts

You need a BMFont JSON file and a matching PNG atlas generated as MSDF. Use msdf-bmfont-xml:

npx msdf-bmfont-xml -f json -m 512,512 -s 42 -o public/fonts/MyFont MyFont.ttf

This produces:

  • MyFont-msdf.json — glyph metrics and kerning
  • MyFont.png — MSDF texture atlas

Pass the paths to fontData and fontAtlas props.

Utilities

import {
  loadFontCached,
  clearFontCache,
  parseAnchor,
  DEFAULT_FONT_DATA,
  DEFAULT_FONT_ATLAS,
} from 'r3f-webgpu-text'

// Preload a font
await loadFontCached('/fonts/MyFont-msdf.json', '/fonts/MyFont.png')

// Clear cache (e.g. on route change)
clearFontCache()

Demo

Live demo: https://r3f-webgpu-text.vercel.app

Run the included demo locally:

git clone https://github.com/ektogamat/r3f-webgpu-text.git
cd r3f-webgpu-text
npm install
npm run dev

Open the URL shown in the terminal (requires WebGPU).

Build the demo for deployment:

npm run build:demo

Development

# Run demo dev server
npm run dev

# Build library to dist/
npm run build

# Build demo to demo-dist/
npm run build:demo

Author

Created by Anderson Mancini.

License

MIT © Anderson Mancini