bevy_fontmesh 0.1.0

Simple and focused Bevy plugin for generating 3D text meshes from fonts
Documentation

bevy_fontmesh

CI Crates.io Documentation License: MIT

A simple and focused Bevy plugin for generating 3D text meshes from fonts. Powered by fontmesh.

Philosophy

This plugin does one thing only: generating mesh geometry from fonts. It intentionally leaves materials, lighting, transforms, and rendering to Bevy's standard systems.

Quick Start

Add to your Cargo.toml:

[dependencies]
bevy = "0.17"
bevy_fontmesh = "0.1"

Basic usage:

use bevy::prelude::*;
use bevy_fontmesh::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(FontMeshPlugin)
        .add_systems(Startup, setup)
        .run();
}

fn setup(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // Camera
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(0.0, 0.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
    ));

    // Light
    commands.spawn((
        PointLight {
            intensity: 2000.0,
            ..default()
        },
        Transform::from_xyz(4.0, 8.0, 4.0),
    ));

    // 3D Text
    commands.spawn(TextMeshBundle {
        text_mesh: TextMesh {
            text: "Hello, World!".to_string(),
            font: asset_server.load("fonts/FiraMono-Medium.ttf"),
            style: TextMeshStyle {
                depth: 0.5,
                subdivision: 20,
                anchor: TextAnchor::Center,
                justify: JustifyText::Center,
            },
        },
        material: MeshMaterial3d(materials.add(StandardMaterial {
            base_color: Color::srgb(0.8, 0.2, 0.3),
            ..default()
        })),
        ..default()
    });
}

Text Anchoring

Control where the text is positioned relative to its transform:

TextMeshStyle {
    anchor: TextAnchor::TopLeft,      // Top-left corner
    anchor: TextAnchor::Center,        // Center of text bounds
    anchor: TextAnchor::BottomRight,   // Bottom-right corner
    anchor: TextAnchor::Custom(Vec2::new(0.5, 0.0)), // Custom pivot (0-1 range)
    ..default()
}

Available anchors: TopLeft, TopCenter, TopRight, CenterLeft, Center, CenterRight, BottomLeft, BottomCenter, BottomRight, Custom(Vec2).

Text Justification

Control alignment for multiline text:

TextMesh {
    text: "Line 1\nLine 2\nLine 3".to_string(),
    style: TextMeshStyle {
        justify: JustifyText::Left,    // Left-aligned
        justify: JustifyText::Center,   // Centered
        justify: JustifyText::Right,    // Right-aligned
        ..default()
    },
    ..default()
}

Styling Parameters

TextMeshStyle {
    depth: 0.5,         // Extrusion depth (0.0 for flat text)
    subdivision: 20,    // Curve quality (higher = smoother, more vertices)
    anchor: TextAnchor::Center,
    justify: JustifyText::Left,
}
  • depth: Controls the Z-depth of the extruded mesh. Use 0.0 for flat 2D-style text.
  • subdivision: Number of segments used to approximate curves. Higher values produce smoother glyphs but increase vertex count.

Examples

Run the included examples:

# Basic 3D text
cargo run --example basic

# Multiline text with anchoring
cargo run --example multiline

# Text justification demo
cargo run --example justification

# All anchor points visualized
cargo run --example anchors

# Performance stress test (100 text meshes)
cargo run --release--example stress_test

Supported Font Formats

  • TrueType (.ttf)

Note: OpenType fonts (.otf) with TrueType outlines are supported, but OpenType fonts with CFF/PostScript outlines are not currently supported (this is a limitation of the underlying ttf-parser library used by fontmesh).

Place your fonts in an assets/fonts/ directory and load them with asset_server.load("fonts/yourfont.ttf").

Limitations

This plugin is intentionally simple. It does not provide:

  • Text kerning or ligatures (uses basic glyph advances)
  • Right-to-left (RTL) text layout
  • Dynamic text effects (shadows, outlines)
  • 2D text rendering
  • Text wrapping by width

For advanced typography needs, consider implementing additional logic on top of the generated meshes.

Performance

The plugin regenerates meshes only when TextMesh components change. For static text, there's no per-frame overhead beyond normal Bevy rendering.

Bevy Version Compatibility

bevy_fontmesh Bevy
0.1 0.17

License

MIT License - see LICENSE for details.