Crate bevy_smud

Crate bevy_smud 

Source
Expand description

§bevy_smud

crates.io MIT/Apache 2.0 crates.io docs.rs

Signed_Distance_Field/Function (SDF) 2D shape rendering for Bevy.

screenshot of a bird drawn with bevy_smud

Bevy smud is a way to conveniently construct and render sdf shapes with Bevy.

Given a shape function/expression, and a fill type, it generates shaders at run-time.

If you keep the number of different sdf and fill combinations relatively low it’s pretty performant. My machine easily handles 100k shapes at 60 fps, with 40 different shape/fill combinations in randomized order (see gallery example).

§Usage

An SDF is a way to map points in space to distances to a surface. If a point maps to a positive value, it’s outside the shape, if it’s negative, it’s inside the shape. These “mappings” can be described by functions, which takes a point as input and returns a distance to a surface. For instance, if you wanted to make a circle, it could be described as length(position - center) - radius. That way, all the points that are radius away from center would be 0 and would define the edge of the shape.

Many such functions describing geometric primitives are included in this library, they are imported automatically when using the single-expression or body shorthand for adding sdfs. For instance, the circle above could also be described as:

smud::sd_circle(p - center, 50.)

Similarly there are a bunch of other shapes (sd_ellipse, sd_box, sd_rounded_box, sd_egg etc. etc.)

Most of the built-in shapes are direct ports of the ones on this page, which includes screenshots of the various shapes. So that page might act as a good reference. The ports here use snake_case instead of camelCase.

To put together a shape, you can do:

use bevy::prelude::*;
use bevy_smud::prelude::*;

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

fn setup(
    mut commands: Commands,
    mut shaders: ResMut<Assets<Shader>>,
) {
    commands.spawn(Camera2d);

    let circle = shaders.add_sdf_expr("smud::sd_circle(p, 50.)");

    commands.spawn(SmudShape {
        color: Color::WHITE,
        sdf: circle,
        frame: Frame::Quad(55.),
        ..default()
    });
}

Make sure you reuse the shaders, i.e. don’t call add_sdf_expr every frame.

You can also define shapes in .wgsl files. Note that in order to use the built-in shapes, you have to import smud, and you must create a function named sdf that takes a smud::SdfInput and returns f32.

Other than that, make sure you understand how to combine shapes, use symmetries and change domains. For instance, the bevy in the screenshot above is built up of several circles, ellipses, and a vesica for the beak.

Also, check out the examples. In particular, the basic example should be a good place to start.

§Picking

Bevy_smud includes a picking backend that allows SDF shapes to respond to mouse/touch input. Add the SmudPickingPlugin to enable picking support:

use bevy::prelude::*;
use bevy_smud::prelude::*;

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, SmudPlugin, SmudPickingPlugin));
        // ...
}

The picking backend supports both frame-based picking (fast, uses shape bounds) and precise SDF-based picking (accurate, uses Rust distance functions that match the shape geometry). See the picking example for details.

§Showcase

Send me a PR if you want your project featured here:

  • Dis order: dis order screenshot

§Bevy version support

The main branch targets the latest bevy release.

bevybevy_smud
0.170.12, main
0.160.11
0.15no support
0.140.9
0.120.7
0.110.6
0.100.5
0.90.4
0.80.3
0.70.2
0.60.1

§Thanks!

Little of this crate is original work. It’s mostly a mishmash of bevy_sprite and Inigo Quilez sdf rendering primitives ported to wgsl. I just put the two together in a way I found convenient.

Modules§

prelude
Re-export of the essentials needed for rendering shapes
sdf
Signed Distance Field (SDF) functions for 2D shapes.

Structs§

SmudPlugin
Main plugin for enabling rendering of Sdf shapes
SmudShape
Main component used for describing an sdf shape

Enums§

BlendMode
Blend mode for shapes
Frame
Bounds for describing how far the fragment shader of a shape will reach, should be bigger than the shape unless you want to clip it
ShapeSystem
System set for shape rendering.

Constants§

DEFAULT_FILL_HANDLE
The default fill used by SmudShape
SIMPLE_FILL_HANDLE
Simple single-colored filled fill