-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Texture atlas preprocessing & the art production pipeline. #13713
Comments
Attacking this work probably breaks down into these steps.
|
Found my way at this issue and wanted to just comment on a few low-hanging fruit I noticed. First, Second, while the Third, there could probably easily be a dedicated asset processor for texture atlases (there aren't any at the moment, but this could be the first!) based upon the above two types. Finally, it's very weird that the type Would be more than happy to implement a couple of these, after I look more into the code. Just figured I'd star the discussion before I do, since I think it's worth making sure I didn't misread anything. |
@clarfonthey I have largely worked around Bevy’s texture atlases to get something usable for my game. My current workflow is custom but pretty good! I agree with your raised issues, and there are even more problems. It might even warrant its own working group. |
# Objective In order to derive `Reflect`, all of a struct's fields must implement `FromReflect`. [As part of looking into some of the work mentioned here](#13713 (comment)), I noticed that `TextureFormat` doesn't implement `Reflect`, and decided to split that into a separate PR. ## Solution I decided that `TextureFormat` should be a `reflect_value` since, although one variant has fields, most users will treat this as an opaque value set explicitly. It also substantially reduces the complexity of the implementation. For now, this implementation isn't actually used by any crates, so, I decided to not preemptively enable the feature on anything. But it's technically an option, now, and more `wgpu` types can be added in the future. ## Testing Everything compiles okay, and I can't really see how this could be done incorrectly given the above constraints.
…tureAtlasLayout` serializable (#15344) # Objective Mostly covers the first point in #13713 (comment) The idea here is that a lot of people want to load their own texture atlases, and many of them do this by deserializing some custom version of `TextureAtlasLayout`. This makes that a little easier by providing `serde` impls for them. ## Solution In order to make `TextureAtlasLayout` serializable, the custom texture mappings that are added by `TextureAtlasBuilder` were separated into their own type, `TextureAtlasSources`. The inner fields are made public so people can create their own version of this type, although because it embeds asset IDs, it's not as easily serializable. In particular, atlases that are loaded directly (e.g. sprite sheets) will not have a copy of this map, and so, don't need to construct it at all. As an aside, since this is the very first thing in `bevy_sprite` with `serde` impls, I've added a `serialize` feature to the crate and made sure it gets activated when the `serialize` feature is enabled on the parent `bevy` crate. ## Testing I was kind of shocked that there isn't anywhere in the code besides a single example that actually used this functionality, so, it was relatively straightforward to do. In #13713, among other places, folks have mentioned adding custom serialization into their pipelines. It would be nice to hear from people whether this change matches what they're doing in their code, and if it's relatively seamless to adapt to. I suspect that the answer is yes, but, that's mainly the only other kind of testing that can be added. ## Migration Guide `TextureAtlasBuilder` no longer stores a mapping back to the original images in `TextureAtlasLayout`; that functionality has been added to a new struct, `TextureAtlasSources`, instead. This also means that the signature for `TextureAtlasBuilder::finish` has changed, meaning that calls of the form: ```rust let (atlas_layout, image) = builder.build()?; ``` Will now change to the form: ```rust let (atlas_layout, atlas_sources, image) = builder.build()?; ``` And instead of performing a reverse-lookup from the layout, like so: ```rust let atlas_layout_handle = texture_atlases.add(atlas_layout.clone()); let index = atlas_layout.get_texture_index(&my_handle); let handle = TextureAtlas { layout: atlas_layout_handle, index, }; ``` You can perform the lookup from the sources instead: ```rust let atlas_layout = texture_atlases.add(atlas_layout); let index = atlas_sources.get_texture_index(&my_handle); let handle = TextureAtlas { layout: atlas_layout, index, }; ``` Additionally, `TextureAtlasSources` also has a convenience method, `handle`, which directly combines the index and an existing `TextureAtlasLayout` handle into a new `TextureAtlas`: ```rust let atlas_layout = texture_atlases.add(atlas_layout); let handle = atlas_sources.handle(atlas_layout, &my_handle); ``` ## Extra notes In the future, it might make sense to combine the three types returned by `TextureAtlasBuilder` into their own struct, just so that people don't need to assign variable names to all three parts. In particular, when creating a version that can be loaded directly (like #11873), we could probably use this new type.
…tureAtlasLayout` serializable (bevyengine#15344) # Objective Mostly covers the first point in bevyengine#13713 (comment) The idea here is that a lot of people want to load their own texture atlases, and many of them do this by deserializing some custom version of `TextureAtlasLayout`. This makes that a little easier by providing `serde` impls for them. ## Solution In order to make `TextureAtlasLayout` serializable, the custom texture mappings that are added by `TextureAtlasBuilder` were separated into their own type, `TextureAtlasSources`. The inner fields are made public so people can create their own version of this type, although because it embeds asset IDs, it's not as easily serializable. In particular, atlases that are loaded directly (e.g. sprite sheets) will not have a copy of this map, and so, don't need to construct it at all. As an aside, since this is the very first thing in `bevy_sprite` with `serde` impls, I've added a `serialize` feature to the crate and made sure it gets activated when the `serialize` feature is enabled on the parent `bevy` crate. ## Testing I was kind of shocked that there isn't anywhere in the code besides a single example that actually used this functionality, so, it was relatively straightforward to do. In bevyengine#13713, among other places, folks have mentioned adding custom serialization into their pipelines. It would be nice to hear from people whether this change matches what they're doing in their code, and if it's relatively seamless to adapt to. I suspect that the answer is yes, but, that's mainly the only other kind of testing that can be added. ## Migration Guide `TextureAtlasBuilder` no longer stores a mapping back to the original images in `TextureAtlasLayout`; that functionality has been added to a new struct, `TextureAtlasSources`, instead. This also means that the signature for `TextureAtlasBuilder::finish` has changed, meaning that calls of the form: ```rust let (atlas_layout, image) = builder.build()?; ``` Will now change to the form: ```rust let (atlas_layout, atlas_sources, image) = builder.build()?; ``` And instead of performing a reverse-lookup from the layout, like so: ```rust let atlas_layout_handle = texture_atlases.add(atlas_layout.clone()); let index = atlas_layout.get_texture_index(&my_handle); let handle = TextureAtlas { layout: atlas_layout_handle, index, }; ``` You can perform the lookup from the sources instead: ```rust let atlas_layout = texture_atlases.add(atlas_layout); let index = atlas_sources.get_texture_index(&my_handle); let handle = TextureAtlas { layout: atlas_layout, index, }; ``` Additionally, `TextureAtlasSources` also has a convenience method, `handle`, which directly combines the index and an existing `TextureAtlasLayout` handle into a new `TextureAtlas`: ```rust let atlas_layout = texture_atlases.add(atlas_layout); let handle = atlas_sources.handle(atlas_layout, &my_handle); ``` ## Extra notes In the future, it might make sense to combine the three types returned by `TextureAtlasBuilder` into their own struct, just so that people don't need to assign variable names to all three parts. In particular, when creating a version that can be loaded directly (like bevyengine#11873), we could probably use this new type.
In order to make Bevy a tier 1 engine for 2D games, a better texture atlas art production pipeline is needed.
Requirements:
Additional Features:
Many of these are features of the Esoteric atlas packer, which is very good.
The text was updated successfully, but these errors were encountered: