Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support load .svg images #1139

Open
wyhaya opened this issue Dec 23, 2020 · 11 comments
Open

Support load .svg images #1139

wyhaya opened this issue Dec 23, 2020 · 11 comments
Labels
A-Assets Load files from disk to use for things like images, models, and sounds C-Feature A new feature, making something new possible

Comments

@wyhaya
Copy link
Contributor

wyhaya commented Dec 23, 2020

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");

Screen Shot

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?

@Moxinilian Moxinilian added A-Assets Load files from disk to use for things like images, models, and sounds C-Feature A new feature, making something new possible labels Dec 23, 2020
@alice-i-cecile
Copy link
Member

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:

  1. Use the nearest size.
  2. Recompute if no exact match is found; likely caching the result.
  3. Quickly interpolate between nearby sizes.

I think 2 is my preferred solution in most cases.

@inodentry
Copy link
Contributor

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.

@alice-i-cecile
Copy link
Member

Thanks @jamadazi; this is very useful expertise :) I agree with your conclusions here.

@blaind
Copy link
Contributor

blaind commented Jul 23, 2021

https:/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");

@mockersf
Copy link
Member

It's best to avoid MPL-2.0, you can find the list of licences accepted in Bevy here:

bevy/deny.toml

Lines 16 to 25 in ba2916c

allow = [
"MIT",
"Apache-2.0",
"BSD-3-Clause",
"ISC",
"Zlib",
"0BSD",
"BSD-2-Clause",
"CC0-1.0",
]

@bjorn3
Copy link
Contributor

bjorn3 commented Jul 23, 2021

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.

@mockersf
Copy link
Member

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

@bjorn3
Copy link
Contributor

bjorn3 commented Jul 23, 2021

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.

@WhatzGames
Copy link

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)

@TheBlckbird
Copy link
Contributor

As of 04/12/2024 Lyon did not switch to MPL-2.0. It is still using MIT/Apache 2.0

@torsteingrindvik
Copy link
Contributor

If someone else stumbles into this issue just looking for a quick way to use e.g. web icons, here's a PNG workaround assuming linux and inkscape is installed:

  1. Copy the SVG, example hourglass icon
  2. Pipe it into inkscape and output:
# You can pipe it directly from clipboard but for GitHub comments this is more readable
FOO='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M0 32C0 14.3 14.3 0 32 0H64 320h32c17.7 0 32 14.3 32 32s-14.3 32-32 32V75c0 42.4-16.9 83.1-46.9 113.1L237.3 256l67.9 67.9c30 30 46.9 70.7 46.9 113.1v11c17.7 0 32 14.3 32 32s-14.3 32-32 32H320 64 32c-17.7 0-32-14.3-32-32s14.3-32 32-32V437c0-42.4 16.9-83.1 46.9-113.1L146.7 256 78.9 188.1C48.9 158.1 32 117.4 32 75V64C14.3 64 0 49.7 0 32zM96 64V75c0 25.5 10.1 49.9 28.1 67.9L192 210.7l67.9-67.9c18-18 28.1-42.4 28.1-67.9V64H96zm0 384H288V437c0-25.5-10.1-49.9-28.1-67.9L192 301.3l-67.9 67.9c-18 18-28.1 42.4-28.1 67.9v11z"/></svg>'

# Convert
echo $FOO | inkscape --pipe -o foo.png

But note that e.g. fontawesome has the attribution in the SVG which is lost on conversion so the attribution should be placed elsewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Assets Load files from disk to use for things like images, models, and sounds C-Feature A new feature, making something new possible
Projects
None yet
Development

No branches or pull requests

10 participants