bevy
bevy copied to clipboard
Support load .svg images
What problem does this solve or what need does it fill?
Allow bevy to load svg vector images
Describe the solution would you like?
Using resvg crate, bevy can easily support svg images
Describe the alternative(s) you've considered?
None
Additional context
I added a SvgTextureLoader and then rendered the image using resvg and now it works fine.
let texture_handle = asset_server.load("branding/bevy_logo_light.svg");
One troublesome question, since svg is vector, how do we determine the size of the image?
Before rendering the svg we have to determine the size
pub enum FitTo {
/// Keep original size.
Original,
/// Scale to width.
Width(u32),
/// Scale to height.
Height(u32),
/// Zoom by factor.
Zoom(f32),
}
Maybe we can?
// Default
asset_server.load("branding/bevy_logo_light.svg");
// Scale
asset_server.load("branding/bevy_logo_light.svg?10.0");
asset_server.load("branding/bevy_logo_light.svg#width=1000.");
Bad scenario: Re-render at each zoom?
WRT the re-render at each zoom problem, perhaps we could build off of mip-maps (#1685) to pre-cache the SVG rendered at different scales.
If we had that, it feels like there are three possibly sensible options:
- Use the nearest size.
- Recompute if no exact match is found; likely caching the result.
- Quickly interpolate between nearby sizes.
I think 2 is my preferred solution in most cases.
Just chiming in to say that this is not really what mipmaps are for. (the use case of using vector graphics like SVG in UI)
Mipmaps are for the GPU hardware to be able to automatically sample a texture at an appropriate resolution when UV-mapping onto 3d geometry (or for raster 2d sprites, when scaling down). Note that you don't really have much choice and control over which size to use when, as mipmaps are a GPU hardware feature and handled automatically. And your mipmap levels/sizes must strictly have specific sizes as expected by the GPU (1/2, 1/4, 1/8, etc., of the base texture).
Your (1) and (3) are things that the GPU hardware does automatically (you should try out the texture_filtering example from the mipmaps PR, which illustrates this ("linear with nearest mipmap" and "linear with linear mipmaps" (interpolation)). Choosing which one you want is just a parameter on the texture sampler. The GPU implements this functionality in hardware.
However, this wouldn't produce the best-looking result for using vector graphics like SVG in UI. Instead, you want to display it rendered natively at the correct size. In that sense, I agree with your (2) point, I just want to point out that it has nothing to do with mipmaps.
On the other hand, if you want to use the SVG to create a texture to be used in your scene / on a mesh, you should totally generate a mipmapped texture with the maximum size (base level) set to something reasonable of your liking. In that case, you should use mipmaps, and probably set the mipmap filtering to LINEAR (or in a 2d game, maybe NEAREST might work better than LINEAR, but anyway, those are just sampler settings).
Really, these are two different use cases: using a SVG in UI and using a SVG for textures in a game. So they call for different implementations. The former should be rendered natively at the correct size, similar to how we handle text. The latter makes sense as a mipmapped texture.
Thanks @jamadazi; this is very useful expertise :) I agree with your conclusions here.
https://github.com/RazrFalcon/resvg is licensed with MPL-2.0, is it okay to incorporate with bevy or should it be separate MPL-2.0 licensed crate?
There needs also to be a way to supply parameters (at least render width, height) for per-resource rendering.
Maybe the SvgAssetLoader could also have (default/user-configurable) presets for handling?
// single asset params
asset_server.load("branding/bevy_logo_light.svg#width=1024,height=512");
// preset
asset_server.load("branding/bevy_logo_light.svg#svg_preset=my_custom_config");
It's best to avoid MPL-2.0, you can find the list of licences accepted in Bevy here: https://github.com/bevyengine/bevy/blob/ba2916c45a6dcf23f7c4007e7ef2a6b0df393433/deny.toml#L16-L25
Relicensing wgpu from MPL was important as it needs to be patched to run on certain consoles. An svg renderer doesn't need to be patched in any way that needs to remain behind an NDA, so I don't see much of a problem with using MPL here. It is weak and not strong copyleft, so you only need to publish any changes to resvg, not any other dependency or the game itself.
MPL-2.0 also requires access to the source code of the parts licensed with it, so it would mean that all Bevy games will need to provide a link to the source code of resvg
The MIT and Apache-2.0 license require attribution notices to be preserved afaik. You could see a link to source code as just another kind of attrbution notice, so it doesn't really add any more obligations on the licensee (the creator of the game) provided that the source code of the MPL licensed dependencies is unchanged.
Maybe working with Lyon could be another option?
Seems to be fairly solid solid, but it also is considering switching from it's MIT/Apache 2.0 Model to MPL-2.0 aswell. But it is not decided as of today (2022-08-01)