Expand description
§Bevy Resvg
A simple library for rendering SVGs in Bevy using the amazing Resvg library.
§Why not bevy_svg?
I originally tried forking bevy_svg to add colour tinting support to the SVGs,
as proposed by bevy_svg/#54.
However, I quickly noticed that the bevy_svg had so much technical debt
(no offense to Weasy666, your library has
clearly worked for many, many people) due to its 5 years of existence that it
was just easier to start a new library from scratch.
Funnily enough, I’m actually publishing this crate onto
crates.io on bevy_svg’s 5-year anniversary
(January 24th)!
Bevy Resvg takes a completely different approach to rendering SVGs compared
to bevy_svg. Instead of tesselating the SVG into a mesh, it first renders the
SVG as a raster image using the Resvg
library. This has both advantages and (unfortunately) drawbacks over bevy_svg’s
approach:
§Comparison between Bevy Resvg and bevy_svg
| Feature | Bevy Resvg | bevy_svg | ||
|---|---|---|---|---|
| Source Lines of Code | 🔽 | 2331 | 🔼 | 191212 |
| Code Complexity | 😀 | 111 | 😵 | 14512 |
| Changing runtime color | ✅ | Supported | ❌ | Unsupported |
| Gradients | ✅ | Supported | ❌ | Unsupported |
| Semi-transparency | ✅ | Supported | ❌ | Unsupported |
| Positioning and sizing | ✅ | Native (Sprite-based) | ❌ | Janky and imprecise |
| Static SVG Spec Support | ✅ | Fully Supported | ⚠️ | Partial Support |
| Rendered quality (normal) | ✅ | Crisp | ✅ | Crisp |
| Rendered quality (zoomed) | ❌ | Blurry and Pixelated | ✅ | Crisp |
| 3D-Rendering | ❌ | Unsupported | ✅ | Supported |
| Hot-reloading of SVGs | ❌ | Unsupported | ❌ | Unsupported |
| Animated SVGs | ❌ | Unsupported | ❌ | Unsupported |
| Approach | 🖼️ | Rasterisation | 🔺 | Tesselation |
| Output | 🏃➡️ | Sprite | 🕸 | Mesh2d |
| Licence | 🟰 | MIT OR Apache-2.0 | 🟰 | MIT OR Apache-2.0 |
…to be expanded…
§When to use Bevy Resvg over bevy_svg
Although I am very proud of this small little crate (it’s my first ever library
to be published on crates.io!, I do realise that there are situations in
which bevy_svg simply makes more sense.
For starters, Bevy Resvg is a very young and immature project. If
you are looking for something more mature and battle-tested, you should probably
use bevy_svg.
Another feature missing from Bevy Resvg is 3D rendering, which has first-class
support in bevy_svg. Unfortunately, you can’t easily render to 3D objects with
Bevy Resvg, yet. Don’t worry, it’s on the Todo-list! In the meantime,
check out bevy_svg if you need to render to a 3D object.
Furthermore, if your game is dependent on zooming into the SVGs,
bevy_svg might fit your needs better (particularly until custom render size
target support is added). Bevy Resvg only performs
rasterisation once, mimicking the behaviour of e.g. the
Godot Engine.
This has the unfortunate side-effect of causing blurry images when zooming in.
bevy_svg, however, tesselates the SVGs into a crisp Mesh2d, which results in
sharper rendering when zoomed in.
However, if you are in need of rendering semi-transparent SVGs, then Bevy Resvg
is your only option (to my knowledge). Perhaps you even want to change the
runtime colour of your loaded SVGs. In that case, Bevy Resvg makes it super
simple! Just modify the outputted
Sprite’s color
field and you’ve got yourself a tinted SVG! That’s not possible (again, to my
knowledge) in bevy_svg. What about gradients? No problem! Resvg handles
gradients naturally too.
I’m not sure why (and, like many other things in this project, I haven’t
bothered to test why), but positioning and especially sizing SVGs with bevy_svg
as children of sprites felt clunky and required hard-coded values back when I
used bevy_svg. I have yet to encounter that issue with Bevy Resvg.
Also, although I have no data to back this up, I would assume that Bevy Resvg
might be a tiny bit faster than bevy_svg. Meshes feel more expensive than
simple textures to me, however I am no expert in this area.
§Usage
See the examples directory for examples of how to use the Bevy Resvg.
Currently, the only examples are:
simple.rs: shows the most basic usage of Bevy Resvgzoom.rs: shows what happens when you zoom too far into an SVG.
More examples are planned!
If you’re too lazy to click the link, here’s the contents of simple.rs:
use bevy::prelude::*;
use bevy_resvg::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, SvgPlugin))
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let svg: Handle<SvgFile> = asset_server.load("transparent.svg");
commands.spawn(Camera2d);
commands.spawn(Svg(svg));
}§Migration guide from bevy_svg
If you wish to migrate from bevy_svg to Bevy Resvg, you must do the following
actions:
[!IMPORTANT] 3D rendering is not yet supported in Bevy Resvg.
- Run
cargo remove bevy_svgandcargo add bevy_resvg. - If you were just using
bevy_svg::preludein your code, simply replace it withbevy_resvg::prelude. - Replace all occurences of
SvgwithSvgFile(make sure you’re doing whole-word replacing. You don’t want anSvgFilePlugin!). - Replace all occurences of
Svg2dwithSvg.
§Todos
- 3D-Rendering support
- Add more examples
- Add tests (there are currently none…)
-
Custom rendering size targets (not dependent on
viewBoxvalue) -
Expand comparison table
- Particularly, add performance comparisons
-
Handle more
AssetEvents-
Added -
Modified -
Removed -
Unused -
LoadedWithDependencies
-
-
usvg::Optionssupport- CSS support
§Minimum supported Rust version
Bevy Resvg’s MSRV is 1.89 due to Bevy’s MSRV.
§Contributing
See CONTRIBUTING.md.
§Licence
MIT OR Apache-2.0, at your option.