Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/johanhelsing/bevy_smud
Sdf 2d shape renderer for Bevy
https://github.com/johanhelsing/bevy_smud
2d bevy bevy-plugin game-development sdf shaders shapes signed-distance-field
Last synced: about 1 month ago
JSON representation
Sdf 2d shape renderer for Bevy
- Host: GitHub
- URL: https://github.com/johanhelsing/bevy_smud
- Owner: johanhelsing
- License: other
- Created: 2022-01-26T16:33:55.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-08-09T05:17:14.000Z (3 months ago)
- Last Synced: 2024-09-26T20:45:21.120Z (about 2 months ago)
- Topics: 2d, bevy, bevy-plugin, game-development, sdf, shaders, shapes, signed-distance-field
- Language: Rust
- Homepage:
- Size: 233 KB
- Stars: 140
- Watchers: 4
- Forks: 10
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# bevy_smud
[![crates.io](https://img.shields.io/crates/v/bevy_smud.svg)](https://crates.io/crates/bevy_smud)
![MIT/Apache 2.0](https://img.shields.io/badge/license-MIT%2FApache-blue.svg)
[![crates.io](https://img.shields.io/crates/d/bevy_smud.svg)](https://crates.io/crates/bevy_smud)
[![docs.rs](https://img.shields.io/docsrs/bevy_smud)](https://docs.rs/bevy_smud)[Signed_Distance_Field/Function][SDF] (SDF) 2D shape rendering for [Bevy](https://bevyengine.org).
![screenshot of a bird drawn with bevy_smud](https://johanhelsing.studio/assets/bevy_smud_banner.png)
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](https://github.com/johanhelsing/bevy_smud/blob/main/examples/gallery.rs) 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:
```wgsl
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](https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm), 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:
```rust no_run
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>,
) {
commands.spawn(Camera2dBundle::default());let circle = shaders.add_sdf_expr("sd_circle(p, 50.)");
commands.spawn(ShapeBundle {
shape: SmudShape {
color: Color::WHITE,
sdf: circle,
frame: Frame::Quad(55.),
..default()
},
..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`](https://github.com/johanhelsing/bevy_smud/blob/main/assets/smud.wgsl), and you must create a function named `sdf` that takes a `vec2` and returns `f32`.
Other than that, make sure you understand how to combine shapes, use symmetries and change domains. For instance, the [bevy](https://github.com/johanhelsing/bevy_smud/blob/main/assets/bevy.wgsl) in the screenshot above is built up of several circles, ellipses, and a vesica for the beak.
Also, check out the [examples](https://github.com/johanhelsing/bevy_smud/blob/main/examples). In particular, the [basic](https://github.com/johanhelsing/bevy_smud/blob/main/examples/basic.rs) example should be a good place to start.
## Showcase
Send me a PR if you want your project featured here:
- Dis order: [![dis order screenshot](https://johanhelsing.studio/assets/dis-order.png)](https://jhelsing.itch.io/dis-order)
## Word of caution
This crate is still fairly experimental.
If you want something more finished, you should probably check out [bevy_prototype_lyon](https://github.com/Nilirad/bevy_prototype_lyon).
## Bevy version support
The `main` branch targets the latest bevy release.
|bevy|bevy_smud|
|----|---------|
|0.14|0.9, main|
|0.12|0.7 |
|0.11|0.6 |
|0.10|0.5 |
|0.9 |0.4 |
|0.8 |0.3 |
|0.7 |0.2 |
|0.6 |0.1 |## Thanks!
Little of this crate is original work. It's mostly a mishmash of [`bevy_sprite`](https://github.com/bevyengine/bevy/tree/main/crates/bevy_sprite) and [Inigo Quilez sdf rendering primitives](https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm) ported to wgsl. I just put the two together in a way I found convenient.
[SDF]: https://en.wikipedia.org/wiki/Signed_distance_function