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 tessellating the SVG into a mesh, it first renders the
SVG as a raster image using the Resvg
library.
§Why not Bevy Vello then?
I actually only found out about Bevy Vello after publishing this crate. For those unaware (like I was earlier!), Bevy Vello is a Bevy plugin that can render numerous types of vector graphics, from text to SVGs to even Lotties using the Vello crate. Vello focuses on GPU compute, making it very quick. Thanks to this performance, it can perform Just-in-Time (JIT) rasterisation of the vector graphics, allowing for crisp graphics at any resolution.
However, Vello isn’t perfect. Most importantly, it doesn’t support as much of the Static SVG Spec as Resvg does. If you need to load complex SVGs, Bevy Resvg is simply going to be the best choice.
Here’s a complete comparison between the three:
§Comparison between Bevy Resvg, bevy_svg, and Bevy Vello
| Feature | Bevy Resvg | bevy_svg | Bevy Vello | |||
|---|---|---|---|---|---|---|
| Source Lines of Code | 🔽 | 9381 | 🔼 | 190412 | ⏫ | 636113 |
| Code Complexity | 😀 | 601 | 😵💫 | 14512 | 😵 | 40913 |
| Hot-reloading of SVGs | ✅ | Supported | ✅ | Supported | ❌ | Unsupported |
| Changing runtime colour | ✅ | Supported | ❌ | Unsupported | ❌ | Unsupported |
| Custom CSS injection | ✅ | Supported | ❌ | Unsupported | ❌ | Unsupported |
| Gradients | ✅ | Supported | ❌ | Unsupported | ⚠️ | Inaccurate |
| Semi-transparency | ✅ | Supported | ❌ | Unsupported | ✅ | Supported |
| Positioning and sizing | ✅ | Native (Sprite & ImageNode-based) | ❌ | Janky and imprecise | ✅ | Native (Image-based) |
| Static SVG Spec Support | ✅ | Fully Supported | ⚠️ | Partial Support | ⚠️ | Partial Support |
| Rendered quality (normal) | ✅ | Crisp | ✅ | Crisp | ✅ | Crisp |
| Rendered quality (zoomed) | ❌ | Blurry and Pixelated | ✅ | Crisp | ✅ | Crisp |
| 3D-Rendering | ❌ | Unsupported | ✅ | Supported | ✅ | Supported |
| Animated SVGs | ❌ | Unsupported | ❌ | Unsupported | ❌ | Unsupported |
| Approach | 🖼️ | Rasterisation (once) | 🔺 | Tessellation | ⚙️ | Rasterisation (JIT every frame) |
| Output | 🏃➡️ | Sprite (2D) or ImageNode (UI) | 🕸 | Mesh2d | 🔀 | Mesh2d with image-based texture |
| Licence | 🟰 | MIT OR Apache-2.0 | 🟰 | MIT OR Apache-2.0 | 🟰 | MIT OR Apache-2.0 |
[!NOTE] In order to be able to hot-reload your SVGs, you must enable the
file_watcherBEVY FEATURE (not a feature available in this crate).As a side note, you probably want to enable entire
devcollection (again, the Bevy feature, there is no feature calleddevin this crate). It comes with a handful of goods, including debug logs and dev tools.
…to be expanded…
§Okay, but when should I actually use Bevy Resvg over the others?
This is a very complex question to answer. Your best bet is probably going to be to just add one to your list of dependencies and try it out; all three projects are quite interchangeable with each other.
If you’re not up for waiting for 3 separate crates to compile, and you want some more concrete examples than the comparison table above, then check out some of the longer explanations below.
§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. 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, tessellates the SVGs into a crisp Mesh2d, which results in
sharper rendering when zoomed in.
If you wish to mitigate the blur, you can set a custom target render size via
SvgFileLoaderSettings.target_render_size. This allows you to render a larger
image up front. However, this has the caveat of requiring you to manually
determine how far a user is likely to zoom in on your SVGs. See the
custom_size example for a demonstration of this.
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.
During testing, I found that bevy_svg couldn’t load complex Inkscape-generated
SVGs, while Bevy Resvg handled them flawlessly just like any other SVG file.
Although you should not ship Inkscape-generated SVGs in your released game, it
can be beneficial to not have to export your SVGs as standard SVGs from Inkscape
each time you want to test a new design.
§When to use Bevy Resvg over Bevy Vello
To be written…
§Usage
See the examples directory for examples of how to use the Bevy Resvg.
Currently, the only examples are:
color_change: shows how to update the colour tint of anSvgwhen an event (spacebar pressed) occurscolor_hue_tween: showcase of anSvgthat continuously tweens through all huescolor_ui_change: shows how to update the colour tint of aUiSvgwhen an event (spacebar pressed) occurscolor_ui_hue_tween: showcase of anUiSvgthat continuously tweens through all huescolor_ui: shows how to apply a static colour tint to aUiSvgcolor: shows how to apply a static colour tint to anSvgcrisp_shapes: shows how to customiseusvg::Optionsto render SVGs with crisp edges and with anti-aliasing turned off.custom_aspect_ratio: shows how to render an SVG to a custom target size with a non-native aspect ratiocustom_size: shows how to render an SVG to a custom target sizecustom_style_sheet: shows how to customiseusvg::Optionswhile loading an SVG by settingstyle_sheetsimple: shows the most basic usage of Bevy Resvgui: shows how to renderUiSvgs in UI nodeszoom: 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 occurrences of
SvgwithSvgFile(make sure you’re doing whole-word replacing. You don’t want anSvgFilePlugin!). - Replace all occurrences of
Svg2dwith eitherSvgorUiSvg(depending on how you’re using it). This step requires a bit of care so that you don’t use the wrong one!
§Todos
- 3D-Rendering support
- JIT support! (because it’s cool, I doubt that it is performant lol)
- Add more examples
- Add tests (there are currently none…)
-
Custom rendering size targets (not dependent on
viewBoxvalue) - UI rendering
-
Expand comparison table
- Particularly, add performance comparisons
-
Handle more
AssetEvents-
Added -
Modified -
Removed -
Unused -
LoadedWithDependencies
-
-
usvg::Optionssupport 4- 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.
Calculated using scc, only counting Rust code. ↩ 1 2 3 4 5 6
Based on commit
b3a3748inWeasy666/bevy_svg↩ 1 2Based on tagged release
v0.13.0inlinebender/bevy_vellobecause later versions of Bevy Vello refuse to compile on my machine. ↩ 1 2The advanced
image_href_resolver,font_resolver, andfontdbsettings are not available due to missing serde support inusvg. If you require changing these settings, please use theresvg-optionbranch. It’s unfortunately not released on crates.io due to it[patch]ingusvg, which is not allowed on crates.io. Please follow the instructions inresvg-option/USAGE.mdto set upresvg-option. ↩
Re-exports§
pub use resvg;
Modules§
- effects
- Runtime modification of
SVGfiles. - error
- Error utilities for this crate.
- plugin
- The
Pluginfor initialising the Bevy logic and configuration provided by this crate. - prelude
- Import this module as
use bevy_resvg::prelude::*to get convenient imports. - raster
- Tools and helpers for loading, rastering, and rendering
SVGfiles. - settings
AssetLoadersettings forSvgFile