-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Implement percentage-closer soft shadows (PCSS). #13497
Conversation
5167130
to
0377266
Compare
[*Percentage-closer soft shadows*] are a technique from 2004 that allow shadows to become blurrier farther from the objects that cast them. It works by introducing a *blocker search* step that runs before the normal shadow map sampling. The blocker search step detects the difference between the depth of the fragment being rasterized and the depth of the nearby samples in the depth buffer. Larger depth differences result in a larger penumbra and therefore a blurrier shadow. To enable PCSS, fill in the `soft_shadow_size` value in `DirectionalLight`, `PointLight`, or `SpotLight`, as appropriate. This shadow size value represents the size of the light and should be tuned as appropriate for your scene. Higher values result in a wider penumbra (i.e. blurrier shadows). When using PCSS, temporal shadow maps (`ShadowFilteringMethod::Temporal`) are recommended. If you don't use `ShadowFilteringMethod::Temporal` and instead use `ShadowFilteringMethod::Gaussian`, Bevy will use the same technique as `Temporal`, but the result won't vary over time. This produces a rather noisy result. Doing better would likely require downsampling the shadow map, which would be complex and slower (and would require PR bevyengine#13003 to land first). In addition to PCSS, this commit makes the near Z plane for the shadow map configurable on a per-light basis. Previously, it had been hardcoded to 0.1 meters. This change was necessary to make the point light shadow map in the example look reasonable, as otherwise the shadows appeared far too aliased. A new example, `pcss`, has been added. It demonstrates the percentage-closer soft shadow technique with directional lights, point lights, spot lights, non-temporal operation, and temporal operation. The assets are my original work. Both temporal and non-temporal shadows are rather noisy in the example, and, as mentioned before, this is unavoidable without downsampling the depth buffer, which we can't do yet. Note also that the shadows don't look particularly great for point lights; the example simply isn't an ideal scene for them. Nevertheless, I felt that the benefits of the ability to do a side-by-side comparison of directional and point lights outweighed the unsightliness of the point light shadows in that example, so I kept the point light feature in. Fixes bevyengine#3631. [*Percentage-closer soft shadows*]: https://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf
I don't know the domain well- why do the shadows here: Have curve-like imperfections? I noticed the article you linked has this image which has a different type of noise: Is it related to the geometry which casts the shadow or something else? Also I was wondering how the shadows perform when the light source is moving. pcss-example-undulate.patch.txt Feel free to pcss-undulate.mp4I noticed an effect that spot lights have this effect where it looks like the shadow density changes a lot, perhaps related to shadow map resolution? |
The patterns are because of the interleaved gradient noise. This is generally considered more desirable than the white noise that it looks like your other example has. There isn't a whole lot we can do about the noise in this patch without generating mip chains for the shadow map, which would require #13003 (and even if that were in I wouldn't want to do it in the first patch because this patch is too big as it is). When I asked in Discord I was told that PCSS in games tends to be noisy; that's just the way it is. I think PCSS is mostly used in directional lights in practice. The results for point lights in particular just aren't as good. |
I considered allowing the user to move the light but I realized that this will cause problems with the Z near value, which is carefully tuned so that the palm tree makes maximum use of the shadow map. So I'm less inclined to make the light movable, though I could be convinced otherwise. |
I suspect what's going wrong with spot lights is that the blocker search starts missing blockers. I'm not sure if this is something that can reasonably be fixed; it's always possible that the blocker search can miss things. The solution is for artists to tweak the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found out that Godot has PCSS and they have an example showcasing it: https://github.com/godotengine/godot-demo-projects/tree/master/3d/lights_and_shadows
I put the GLTF files in this PR in that project and dropped the palm tree into Godot and tried experimenting with the PCSS lights in that example.
I couldn't try the spot light (likely due to godotengine/godot#80137) but I saw similar results when using their omni light (point light) and their sun (directional light).
I learned that it's very finicky to get decent looking shadows, and I had to resort to a mix of tuning their shadow blur and their shadow opacity (not sure if we have that in Bevy yet) and only specific combos of those along with light strength and positioning yielded OK results.
I'm convinced that PCSS is hard to get right (as a user) and that this PR adds value and if we can get better noise patterns further down the line that's really great.
EDIT: When we have a Bevy editor where we can interactively tune parameters like I could in Godot it will be a lot easier to spot problems so I'm not worried about any minor issues right now.
Approving on the basis of the above, as well as:
- Code quality to me looks great
- Adds great docs
- Great example
I haven't verified any math or looked in depth at the shaders- hoping rendering maintainers will do so.
Yeah. Unity doesn't implement PCSS at all and in this PR I pretty much learned why. PCSS is just really hard to tune. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, the code looks good to me. The new docs for the existing shadow stuff is really nice.
As mentioned on discord, the volumetric_fog and trransmission example currently crash. Once those are fixed and assuming conflicts are fixed I'll approve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good, just a small nit about clarifying some unused uncommented fields.
pub(crate) pad_a: f32, | ||
pub(crate) pad_b: f32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Is this intended to make the structure's size a multiple of 4 x f32? If so a comment and maybe a test might be good, assuming it's important and relied upon elsewhere. Maybe something like this would also make the intention clearer and more maintainable:
pub(crate) pad_a: f32, | |
pub(crate) pad_b: f32, | |
pub(crate) _reserved: [f32; 2], |
The test could be as simple as this:
#[cfg(test)]
const_assert_eq!(size_of::<GpuClusterableObject>() % size_of::<Vec4>(), 0);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A test isn't that necessary for that. Things break pretty quickly if the padding is wrong anyway. We have padding in a bunch of places for rendering code because of some webgl limitations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, no problem if it’s convention - although should it be commented all the same? I was thinking the test wasn't so much about ensuring it breaks, but ensuring the issue is determined statically and in the right location to fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me, just the fact that it's called pad_x
is enough documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Righto, again no problem if it's an established convention in the codebase.
I was initially unsure whether this was perhaps something like padding from the edge of the shadow when sampling to avoid boundary conditions. It required me to check it wasn't used to understand its purpose and intention, but if I was adding a new field I may not have checked so thoroughly and just added new fields rather than removing these.
Again, it's a nit, and not a huge issue. I just saw it as something that could be made clearer. My intention if it's clearer is that more people can get across these changes, review, and contribute. Being knowledgable about graphics doesn't mean you're knowledgable about conventions in this codebase, or rust, etc. My understanding of Rust convention, for example, is that fields like this would have an underscore prefix _pad_a
to indicate they're intentionally unused.
Please don't merge this yet as spot shadows are broken somehow due to merge fallout. |
4, | ||
5, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a change for this PR, but after this is merged would a PR be welcome to replace these values with constants? and defined in the shader with defines like this:
@group(0) @binding(#TONEMAPPING_LUT_TEXTURE_BINDING_INDEX) var dt_lut_texture: texture_3d<f32>; | |
@group(0) @binding(#TONEMAPPING_LUT_SAMPLER_BINDING_INDEX) var dt_lut_sampler: sampler; |
It might reduce merge conflict churn when there's lots of unrelated changes in a PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I recall, non-boolean defines are kind of annoying in our PBR shaders at the moment, but sure, it could be done in the future.
@alice-i-cecile I think I fixed DX12. |
This failure is because |
Should be fixed again. |
I love WebGL2 🥲 Thanks for fixing this up <3 |
Thank you to everyone involved with the authoring or reviewing of this PR! This work is relatively important and needs release notes! Head over to bevyengine/bevy-website#1688 if you'd like to help out. |
The PCSS PR bevyengine#13497 increased the size of clusterable objects from 64 bytes to 80 bytes but didn't decrease the UBO size to compensate, so we blew past the 16kB limit on WebGL 2. This commit fixes the issue by lowering the maximum number of clusterable objects to 204, which puts us under the 16kB limit again. Closes bevyengine#15998.
The PCSS PR #13497 increased the size of clusterable objects from 64 bytes to 80 bytes but didn't decrease the UBO size to compensate, so we blew past the 16kB limit on WebGL 2. This commit fixes the issue by lowering the maximum number of clusterable objects to 204, which puts us under the 16kB limit again. Closes #15998.
The PCSS PR #13497 increased the size of clusterable objects from 64 bytes to 80 bytes but didn't decrease the UBO size to compensate, so we blew past the 16kB limit on WebGL 2. This commit fixes the issue by lowering the maximum number of clusterable objects to 204, which puts us under the 16kB limit again. Closes #15998.
commit 78a4bea Author: ickshonpe <[email protected]> Date: Sun Oct 27 22:39:32 2024 +0000 Move `ContentSize` requirements from `Node` to the widget defining components (bevyengine#16083) # Objective Missed this in the required components PR review. `ContentSize` isn't used by regular UI nodes, only those with intrinsically sized content that needs a measure func. ## Solution Remove `ContentSize` from `Node`'s required components and add it to the required components of `Text` and `UiImage`. --------- Co-authored-by: Alice Cecile <[email protected]> commit c4c1c8f Author: mgi388 <[email protected]> Date: Mon Oct 28 09:38:07 2024 +1100 Undeprecate is_playing_animation (bevyengine#16121) # Objective - Fixes bevyengine#16098 ## Solution - Undeprecate `is_playing_animation` and copy the docs from `animation_is_playing` to it. ## Testing - CI ## Migration https://github.com/bevyengine/bevy-website/blob/68e9a34e3068ed2e7db5ae0b4b32feac94a589dd/release-content/0.15/migration-guides/_guides.toml#L13-L17 needs to be removed. commit 3d72f49 Author: ickshonpe <[email protected]> Date: Sun Oct 27 20:08:51 2024 +0000 Layout rounding debug example (bevyengine#16096) # Objective Simple example for debugging layout rounding errors. <img width="1039" height="752" alt="layout_rounding_debug" src="https://github.com/user-attachments/assets/12673000-e267-467e-b25b-3f8001c1347c"> Any white lines are gaps in the layout caused by coordinate rounding errors. commit 86ee8e4 Author: ickshonpe <[email protected]> Date: Sun Oct 27 19:14:46 2024 +0000 Move `UiImage` from `ui_node` to the `widget::image` module (bevyengine#16084) # Objective `UiImage` isn't just a general image component now, it's the defining component for the image widget so it belongs in the image widget's module. commit d01db9b Author: Hexroll by Pen, Dice & Paper <[email protected]> Date: Sun Oct 27 19:08:34 2024 +0000 Adding alpha_threshold to OrderIndependentTransparencySettings for user-level optimization (bevyengine#16090) # Objective Order independent transparency can filter fragment writes based on the alpha value and it is currently hard-coded to anything higher than 0.0. By making that value configurable, users can optimize fragment writes, potentially reducing the number of layers needed and improving performance in favor of some transparency quality. ## Solution This PR adds `alpha_threshold` to the OrderIndependentTransparencySettings component and uses the struct to configure a corresponding shader uniform. This uniform is then used instead of the hard-coded value. To configure OIT with a custom alpha threshold, use: ```rust fn setup(mut commands: Commands) { commands.spawn(( Camera3d::default(), OrderIndependentTransparencySettings { layer_count: 8, alpha_threshold: 0.2, }, )); } ``` ## Testing I tested this change using the included OIT example, as well as with two additional projects. ## Migration Guide If you previously explicitly initialized OrderIndependentTransparencySettings with your own `layer_count`, you will now have to add either a `..default()` statement or an explicit `alpha_threshold` value: ```rust fn setup(mut commands: Commands) { commands.spawn(( Camera3d::default(), OrderIndependentTransparencySettings { layer_count: 16, ..default() }, )); } ``` --------- Co-authored-by: JMS55 <[email protected]> commit 3fc2bd7 Author: Rob Parrett <[email protected]> Date: Sun Oct 27 12:06:19 2024 -0700 Cosmetic tweaks to `query_gltf_primitives` (bevyengine#16102) # Objective This example is really confusing to look at and tell at a glance whether it's broken or not. It's displaying a strange shape -- a cube with two vertices stretched in a couple dimensions at an odd angle, and doing its vertex position modification in a way where the intent isn't obvious. ## Solution - Change the gltf geometry so that the object is a recognizable regular shape - Change the vertex modification so that the entire cube top is being "lifted" from the cube - Adjust colors, lighting, and camera location so we can see what's going on - Also remove some irrelevant shadow and environment map setup ## Before ![Image](https://github.com/user-attachments/assets/e5dd5075-0480-49d4-b1ed-cf1fe6106f3c) ## After <img width="1280" alt="image" src="https://github.com/user-attachments/assets/59cab60d-efbc-47c3-8688-e4544b462421"> commit 7451900 Author: Miles Silberling-Cook <[email protected]> Date: Sun Oct 27 15:05:31 2024 -0400 Emit picking event streams (bevyengine#16105) # Objective In `bevy_mod_picking` events are accessible through event listeners or `EventReader`s. When I replaced event listeners with observers, I removed the `EventReader` for simplicity. This adds it back. ## Solution All picking events are now properly registered, and can be accessed through `EventReader<Pointer<E>>`. `Pointer` now tracks the entity the event targeted initially, and this can also be helpful in observers (which don't currently do this). ## Testing The picking examples run fine. This shouldn't really change anything. --------- Co-authored-by: Aevyrie <[email protected]> commit 54b323e Author: Aevyrie <[email protected]> Date: Sun Oct 27 12:03:48 2024 -0700 Mesh picking fixes (bevyengine#16110) # Objective - Mesh picking is noisy when a non triangle list is used - Mesh picking runs even when users don't need it - Resolve bevyengine#16065 ## Solution - Don't add the mesh picking plugin by default - Remove error spam commit a644ac7 Author: Tau Gärtli <[email protected]> Date: Sun Oct 27 20:01:50 2024 +0100 More `#[doc(fake_variadic)]` goodness (bevyengine#16108) This PR adds `#[doc(fake_variadic)]` to that were previously not supported by rustdoc. Thanks to an [upstream contribution](rust-lang/rust#132115) by yours truly, `#[doc(fake_variadic)]` is now supported on impls such as `impl QueryData for AnyOf<(T, ...)>` 🎉 Requires the latest nightly compiler (2024-10-25) which is already available on [docs.rs](https://docs.rs/about/builds). ![image](https://github.com/user-attachments/assets/68589c7e-f68f-44fb-9a7b-09d24ccf19c9) ![image](https://github.com/user-attachments/assets/f09d20d6-d89b-471b-9a81-4a72c8968178) This means that the impl sections for `QueryData` and `QueryFilter` are now nice and tidy ✨ --- I also added `fake_variadic` to some impls that use `all_tuples_with_size`, however I'm not entirely happy because the docs are slightly misleading now: ![image](https://github.com/user-attachments/assets/fac93d08-dc02-430f-9f34-c97456256c56) Note that the docs say `IntoBindGroupLayoutEntryBuilderArray<1>` instead of `IntoBindGroupLayoutEntryBuilderArray<N>`. commit 60b2c7c Author: François Mockers <[email protected]> Date: Fri Oct 25 22:14:39 2024 +0200 fix bevy_dev_tools build (bevyengine#16099) # Objective - bevy_dev_tools 0.15.0-rc.1 failed to build docs - it use bevy_text feature in bevy_ui but it's not enabled by default - https://docs.rs/crate/bevy_dev_tools/0.15.0-rc.1 - ## Solution - enable bevy_text feature of bevy_ui commit 7c59317 Author: BD103 <[email protected]> Date: Fri Oct 25 16:11:51 2024 -0400 Fix `bevy_picking` plugin suffixes (bevyengine#16082) # Objective - `MeshPickingBackend` and `SpritePickingBackend` do not have the `Plugin` suffix - `DefaultPickingPlugins` is masquerading as a `Plugin` when in reality it should be a `PluginGroup` - Fixes bevyengine#16081. ## Solution - Rename some structures: |Original Name|New Name| |-|-| |`MeshPickingBackend`|`MeshPickingPlugin`| |`MeshPickingBackendSettings`|`MeshPickingSettings`| |`SpritePickingBackend`|`SpritePickingPlugin`| |`UiPickingBackendPlugin`|`UiPickingPlugin`| - Make `DefaultPickingPlugins` a `PluginGroup`. - Because `DefaultPickingPlugins` is within the `DefaultPlugins` plugin group, I also added support for nested plugin groups to the `plugin_group!` macro. ## Testing - I used ripgrep to ensure all references were properly renamed. - For the `plugin_group!` macro, I used `cargo expand` to manually inspect the expansion of `DefaultPlugins`. --- ## Migration Guide > [!NOTE] > > All 3 of the changed structures were added after 0.14, so this does not need to be included in the 0.14 to 0.15 migration guide. - `MeshPickingBackend` is now named `MeshPickingPlugin`. - `MeshPickingBackendSettings` is now named `MeshPickingSettings`. - `SpritePickingBackend` is now named `SpritePickingPlugin`. - `UiPickingBackendPlugin` is now named `UiPickingPlugin`. - `DefaultPickingPlugins` is now a a `PluginGroup` instead of a `Plugin`. commit 611ba8b Author: Ludwig DUBOS <[email protected]> Date: Fri Oct 25 22:08:14 2024 +0200 Add `AsyncSeekForwardExt` trait to allows a similar API to the previous Bevy version (bevyengine#16027) # Objective This PR introduces an `AsyncSeekForwardExt` trait, which I forgot in my previous PR bevyengine#14194. This new trait is analogous to `AsyncSeekExt` and allows all implementors of `AsyncSeekForward` to directly use the `seek_forward` function in async contexts. ## Solution - Implement a new `AsyncSeekForwardExt` trait - Automatically implement this trait for all types that implement `AsyncSeekForward` ## Showcase This new trait allows a similar API to the previous Bevy version: ```rust #[derive(Default)] struct UniverseLoader; #[derive(Asset, TypePath, Debug)] struct JustALilAsteroid([u8; 128]); impl AssetLoader for UniverseLoader { type Asset = JustALilAsteroid; type Settings = (); type Error = std::io::Error; async fn load<'a>( &'a self, reader: &'a mut Reader<'a>, _settings: &'a Self::Settings, _context: &'a mut LoadContext<'_>, ) -> Result<Self::Asset, Self::Error> { // read the asteroids entry table let entry_offset: u64 = /* ... */; let current_offset: u64 = reader.seek_forward(0).await?; // jump to the entry reader.seek_forward(entry_offset - current_offset).await?; let mut asteroid_buf = [0; 128]; reader.read_exact(&mut asteroid_buf).await?; Ok(JustALilAsteroid(asteroid_buf)) } fn extensions(&self) -> &[&str] { &["celestial"] } } ``` commit c6a66a7 Author: Patrick Walton <[email protected]> Date: Thu Oct 24 14:16:00 2024 -0700 Place percentage-closer soft shadows behind a feature gate to save on samplers. (bevyengine#16068) The two additional linear texture samplers that PCSS added caused us to blow past the limit on Apple Silicon macOS and WebGL. To fix the issue, this commit adds a `--feature pbr_pcss` feature gate that disables PCSS if not present. Closes bevyengine#15345. Closes bevyengine#15525. Closes bevyengine#15821. --------- Co-authored-by: Carter Anderson <[email protected]> Co-authored-by: IceSentry <[email protected]> commit 897404e Author: Patrick Walton <[email protected]> Date: Thu Oct 24 14:00:11 2024 -0700 Reduce the clusterable object UBO size below 16384 for WebGL 2. (bevyengine#16069) The PCSS PR bevyengine#13497 increased the size of clusterable objects from 64 bytes to 80 bytes but didn't decrease the UBO size to compensate, so we blew past the 16kB limit on WebGL 2. This commit fixes the issue by lowering the maximum number of clusterable objects to 204, which puts us under the 16kB limit again. Closes bevyengine#15998. commit 9274bfe Author: Carter Anderson <[email protected]> Date: Wed Oct 23 18:24:17 2024 -0500 Move TextureAtlas into UiImage and remove impl Component for TextureAtlas (bevyengine#16072) # Objective Fixes bevyengine#16064 ## Solution - Add TextureAtlas to `UiImage::texture_atlas` - Add `TextureAtlas::from_atlas_image` for parity with `Sprite` - Rename `UiImage::texture` to `UiImage::image` for parity with `Sprite` - Port relevant implementations and uses - Remove `derive(Component)` for `TextureAtlas` --- ## Migration Guide Before: ```rust commands.spawn(( UiImage::new(image), TextureAtlas { index, layout }, )); ``` After: ```rust commands.spawn(UiImage::from_atlas_image(image, TextureAtlas { index, layout })); ``` Before: ```rust commands.spawn(UiImage { texture: some_image, ..default() }) ``` After: ```rust commands.spawn(UiImage { image: some_image, ..default() }) ``` commit 2cdad48 Author: Viktor Gustavsson <[email protected]> Date: Wed Oct 23 23:51:39 2024 +0200 Ensure ghost nodes are skipped when getting parent clipping rect (bevyengine#16058) # Objective - Follow up on bevyengine#16044 - `extract_uinode_borders` uses `bevy_hierarchy` directly instead of going through the traversal utilities, meaning it won't handle `GhostNode`s properly. ## Solution - Replaced the use of `bevy_hierarchy::Parent` with `UIChildren::get_parent` ## Testing - Ran the `overflow` example, clipping looks ok. --- --------- Co-authored-by: Carter Anderson <[email protected]> commit c9a3f34 Author: ickshonpe <[email protected]> Date: Wed Oct 23 21:41:42 2024 +0100 Fixes for a few minor borders and outlines bugs (bevyengine#16071) # Objective 1. Nodes with `Display::None` set are removed from the layout and have no position or size. Outlines should not be drawn for a node with `Display::None` set. 2. The outline and border colors are checked for transparency together. If only one of the two is transparent, both will get queued. 3. The `node.is_empty()` check is insufficient to check if a border is present since a non-zero sized node can have a zero width border. ## Solution 1. Add a check to `extract_uinode_borders` and ignore the node if `Display::None` is set. 2. Filter the border and outline optional components by `is_fully_transparent`. 3. Check if all the border widths are zero instead. ## Testing I added dark cyan outlines around the left and right sections in the `display_and_visibility` example. If you run the example and set the outermost node to `Display::None` on the right, then you'll see the that the outline on the left disappears. commit 7577895 Author: Carter Anderson <[email protected]> Date: Wed Oct 23 15:05:28 2024 -0500 Use CosmicFontSystem in public bevy_text APIs and remove cosmic_text re-export (bevyengine#16063) # Objective Fixes bevyengine#16006 ## Solution We currently re-export `cosmic_text`, which is seemingly motivated by the desire to use `cosmic_text::FontSystem` in `bevy_text` public APIs instead of our `CosmicFontSystem` resource wrapper type. This change makes `bevy_text` a "true" abstraction over `cosmic_text` (it in fact, was already built to be that way generally and has this one "leak"). This allows us to remove the `cosmic_text` re-export, which helps clean up the Rust Analyzer imports and generally makes this a "cleaner" API. commit 3fb6cef Author: JMS55 <[email protected]> Date: Wed Oct 23 12:18:49 2024 -0700 Meshlet fill cluster buffers rewritten (bevyengine#15955) # Objective - Make the meshlet fill cluster buffers pass slightly faster - Address bevyengine#15920 for meshlets - Added PreviousGlobalTransform as a required meshlet component to avoid extra archetype moves, slightly alleviating bevyengine#14681 for meshlets - Enforce that MeshletPlugin::cluster_buffer_slots is not greater than 2^25 (glitches will occur otherwise). Technically this field controls post-lod/culling cluster count, and the issue is on pre-lod/culling cluster count, but it's still valid now, and in the future this will be more true. Needs to be merged after bevyengine#15846 and bevyengine#15886 ## Solution - Old pass dispatched a thread per cluster, and did a binary search over the instances to find which instance the cluster belongs to, and what meshlet index within the instance it is. - New pass dispatches a workgroup per instance, and has the workgroup loop over all meshlets in the instance in order to write out the cluster data. - Use a push constant instead of arrayLength to fix the linked bug - Remap 1d->2d dispatch for software raster only if actually needed to save on spawning excess workgroups ## Testing - Did you test these changes? If so, how? - Ran the meshlet example, and an example with 1041 instances of 32217 meshlets per instance. Profiled the second scene with nsight, went from 0.55ms -> 0.40ms. Small savings. We're pretty much VRAM bandwidth bound at this point. - How can other people (reviewers) test your changes? Is there anything specific they need to know? - Run the meshlet example ## Changelog (non-meshlets) - PreviousGlobalTransform now implements the Default trait commit 6d42830 Author: JMS55 <[email protected]> Date: Wed Oct 23 09:56:50 2024 -0700 Meshlet builder improvements redux (bevyengine#15886) Take a bunch more improvements from @zeux's nanite.cpp code. * Use position-only vertices (discard other attributes) to determine meshlet connectivity for grouping * Rather than using the lock borders flag when simplifying meshlet groups, provide the locked vertices ourselves. The lock borders flag locks the entire border of the meshlet group, but really we only want to lock the edges between meshlet groups - outwards facing edges are fine to unlock. This gives a really significant increase to the DAG quality. * Add back stuck meshlets (group has only a single meshlet, simplification failed) to the simplification queue to allow them to get used later on and have another attempt at simplifying * Target 8 meshlets per group instead of 4 (second biggest improvement after manual locks) * Provide a seed to metis for deterministic meshlet building * Misc other improvements We can remove the usage of unsafe after the next upstream meshopt release, but for now we need to use the ffi function directly. I'll do another round of improvements later, mainly attribute-aware simplification and using spatial weights for meshlet grouping. Need to merge bevyengine#15846 first. commit 50d38f2 Author: akimakinai <[email protected]> Date: Wed Oct 23 08:29:58 2024 +0900 Fix point light count limit (bevyengine#16062) # Objective - I made a mistake in bevyengine#15902, specifically [this diff](bevyengine@e2faedb) -- the `point_light_count` variable is used for all point lights, not just shadow mapped ones, so I cannot add `.min(max_texture_cubes)` there. (Despite `spot_light_count` having `.min(..)`) It may have broken code like this (where `index` is index of `point_light` vec): https://github.com/bevyengine/bevy/blob/9930df83ed42008f7eb2c02cc7350040f0250c2e/crates/bevy_pbr/src/render/light.rs#L848-L850 and also causes panic here: https://github.com/bevyengine/bevy/blob/9930df83ed42008f7eb2c02cc7350040f0250c2e/crates/bevy_pbr/src/render/light.rs#L1173-L1174 ## Solution - Adds `.min(max_texture_cubes)` directly to the loop where texture views for point lights are created. ## Testing - `lighting` example (with the directional light removed; original example doesn't crash as only 1 directional-or-spot light in total is shadow-mapped on webgl) no longer crashes on webgl commit 2223f6e Author: JMS55 <[email protected]> Date: Tue Oct 22 16:05:40 2024 -0700 Meshlet fix software rasterization (bevyengine#16049) # Objective 1. Prevent weird glitches with stray pixels scattered around the scene ![image](https://github.com/user-attachments/assets/f12adb38-5996-4dc7-bea6-bd326b7317e1) 2. Prevent weird glitchy full-screen triangles that pop-up and destroy perf (SW rasterizing huge triangles is slow) ![image](https://github.com/user-attachments/assets/d3705427-13a5-47bc-a54b-756f0409da0b) ## Solution 1. Use floating point math in the SW rasterizer bounding box calculation to handle negative verticss, and add backface culling 2. Force hardware raster for clusters that clip the near plane, and let the hardware rasterizer handle the clipping I also adjusted the SW rasterizer threshold to < 64 pixels (little bit better perf in my test scene, but still need to do a more comprehensive test), and enabled backface culling for the hardware raster pipeline. ## Testing - Did you test these changes? If so, how? - Yes, on an example scene. Issues no longer occur. - Are there any parts that need more testing? - No. - How can other people (reviewers) test your changes? Is there anything specific they need to know? - Run the meshlet example. commit fe4f44b Author: François Mockers <[email protected]> Date: Wed Oct 23 00:37:04 2024 +0200 crate publish order: bevy_animation depends on bevy_animation_derive (bevyengine#16060) # Objective - bevy_animation publication fails because of missed dependency - bevy_animation depends on bevy_animation_derive which is published after ## Solution - Reorder crates bevy_animation and bevy_animation_derive commit fac0b34 Author: François Mockers <[email protected]> Date: Tue Oct 22 22:21:19 2024 +0200 remove reference to missing file in bevy_remote cargo.toml (bevyengine#16057) # Objective - bevy_remote Cargo.toml file references a readme that doesn't exist - This is blocking releasing the rc ## Solution - Remove the reference commit 9d54fe0 Author: JMS55 <[email protected]> Date: Tue Oct 22 13:14:30 2024 -0700 Meshlet new error projection (bevyengine#15846) * New error projection code taken from @zeux's meshoptimizer nanite.cpp demo for determining LOD (thanks zeux!) * Builder: `compute_lod_group_data()` * Runtime: `lod_error_is_imperceptible()` commit 9930df8 Author: ickshonpe <[email protected]> Date: Mon Oct 21 23:54:09 2024 +0100 UI borders and outlines clipping fix (bevyengine#16044) # Objective fixes bevyengine#15502 Clipped borders and outlines aren't drawn correctly. ### Borders aren't clipped Spawn two nodes with the same dimensions and border thickness, but clip on of the nodes so that only its top left quarter is visible: <img width="194" alt="clip" src="https://github.com/user-attachments/assets/2d3f6d28-aa20-44df-967a-677725828294"> You can see that instead of clipping the border, instead the border is scaled to fit inside of the unclipped section. ```rust use bevy::color::palettes::css::BLUE; use bevy::prelude::*; use bevy::winit::WinitSettings; fn main() { App::new() .add_plugins(DefaultPlugins) .insert_resource(WinitSettings::desktop_app()) .add_systems(Startup, setup) .run(); } fn setup(mut commands: Commands) { commands.spawn(Camera2d); commands .spawn(Node { width: Val::Percent(100.), height: Val::Percent(100.), justify_content: JustifyContent::Center, align_items: AlignItems::Center, ..Default::default() }) .with_children(|commands| { commands .spawn(Node { column_gap: Val::Px(10.), ..Default::default() }) .with_children(|commands| { commands .spawn(Node { width: Val::Px(100.), height: Val::Px(100.), overflow: Overflow::clip(), ..Default::default() }) .with_child(( Node { position_type: PositionType::Absolute, width: Val::Px(100.), height: Val::Px(100.), border: UiRect::all(Val::Px(10.)), ..Default::default() }, BackgroundColor(Color::WHITE), BorderColor(BLUE.into()), )); commands .spawn(Node { width: Val::Px(50.), height: Val::Px(50.), overflow: Overflow::clip(), ..Default::default() }) .with_child(( Node { position_type: PositionType::Absolute, width: Val::Px(100.), height: Val::Px(100.), border: UiRect::all(Val::Px(10.)), ..Default::default() }, BackgroundColor(Color::WHITE), BorderColor(BLUE.into()), )); }); }); } ``` You can also see this problem in the `overflow` example. If you hover over any of the clipped nodes you'll see that the outline only wraps the visible section of the node ### Outlines are clipped incorrectly A UI nodes Outline's are drawn outside of its bounds, so applying the local clipping rect to the outline doesn't make any sense. Instead an `Outline` should be clipped using its parent's clipping rect. ## Solution * Pass the `point` value into the vertex shader instead of calculating it in the shader. * In `extract_uinode_borders` use the parents clipping rect when clipping outlines. The extra parameter isn't a great solution I think, but I wanted to fix borders for the 0.15 release and this is the most minimal approach I could think of without replacing the whole shader and prepare function. ## Showcase <img width="149" alt="clipp" src="https://github.com/user-attachments/assets/19fbd3cc-e7cd-42e1-a5e0-fd92aad04dcd"> --------- Co-authored-by: Alice Cecile <[email protected]> commit d0af199 Author: Stepan Koltsov <[email protected]> Date: Mon Oct 21 16:57:52 2024 +0100 Add a test for Mesh::triangles and fix for TriangleStrip (bevyengine#16026) # Objective - Illustrate behavior with a test - Fix a bug revealed by a test ## Solution - Add a test and fix ## Testing Test added. commit 465d113 Author: Stepan Koltsov <[email protected]> Date: Mon Oct 21 03:17:59 2024 +0100 Replace TwoIterators with Either in bevy_animation (bevyengine#16036) # Objective - Less code - Better iterator (implements `size_hint` for example) ## Solution - Use `either` - This change is free because `bevy_animation` depends on `bevy_asset`, which already depends on `either` ## Testing CI # Conflicts: # Cargo.toml
commit 069291d Author: Clar Fon <[email protected]> Date: Mon Oct 28 17:15:00 2024 -0400 Reduce compile time of bevy_ptr::OwnedPtr::make function (bevyengine#15644) ## Methodology A good metric that correlates with compile time is the amount of code generated by the compiler itself; even if the end binary is exactly the same size, having more copies of the same code can really slow down compile time, since it has to figure out whether it needs to include them or not. The measurement for this used was the [`cargo-llvm-lines` crate](https://docs.rs/crate/cargo-llvm-lines) which can measure which functions are generating the most lines of LLVM IR, which generally means more code compiled. The example compiled was the `breakout` game, to choose something that touches a decent portion of the engine. ## Solution Based upon the measurements, `bevy_ptr::OwnedPtr::make` was taking up 4061 lines of LLVM IR in the example code. So, I separated part of this function into a less-monomorphised version to reduce the amount of generated code. This was by far the most lines emitted by any single function. ## Results After this change, only 2560 lines are emitted, accounting for a 36% decrease. I tried timing the results and it seemed like it did decrease compile times a bit, but honestly, the data is really noisy and I can't be bothered to compile bevy for hours on end to get enough data points. The tweak feels like an improvement, so, I'll offer it, however small. commit 1add4bf Author: ickshonpe <[email protected]> Date: Mon Oct 28 21:05:25 2024 +0000 Rename `ComputedNode::calculated_size` to `size` (bevyengine#16131) # Objective Remove `calculated_` from the name `ComputedNode::calculated_size` as redundant, It's obvious from context that it's the resolved size value and it's inconsistant since none of other fields of `ComputedNode` have a `calculated_` prefix. ## Alternatives Rename all the fields of `ComputedNode` to `calculated_*`, this seems worse. commit 33c4945 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Oct 28 13:01:25 2024 +0100 Bump crate-ci/typos from 1.26.0 to 1.26.8 (bevyengine#16128) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.26.0 to 1.26.8. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/crate-ci/typos/releases">crate-ci/typos's releases</a>.</em></p> <blockquote> <h2>v1.26.8</h2> <h2>[1.26.8] - 2024-10-24</h2> <h2>v1.26.3</h2> <h2>[1.26.3] - 2024-10-24</h2> <h3>Fixes</h3> <ul> <li>Accept <code>additionals</code></li> </ul> <h2>v1.26.2</h2> <h2>[1.26.2] - 2024-10-24</h2> <h3>Fixes</h3> <ul> <li>Accept <code>tesselate</code> variants</li> </ul> <h2>v1.26.1</h2> <h2>[1.26.1] - 2024-10-23</h2> <h3>Fixes</h3> <ul> <li>Respect <code>--force-exclude</code> for binary files</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's changelog</a>.</em></p> <blockquote> <h2>[1.26.8] - 2024-10-24</h2> <h2>[1.26.7] - 2024-10-24</h2> <h2>[1.26.6] - 2024-10-24</h2> <h2>[1.26.5] - 2024-10-24</h2> <h2>[1.26.4] - 2024-10-24</h2> <h2>[1.26.3] - 2024-10-24</h2> <h3>Fixes</h3> <ul> <li>Accept <code>additionals</code></li> </ul> <h2>[1.26.2] - 2024-10-24</h2> <h3>Fixes</h3> <ul> <li>Accept <code>tesselate</code> variants</li> </ul> <h2>[1.26.1] - 2024-10-23</h2> <h3>Fixes</h3> <ul> <li>Respect <code>--force-exclude</code> for binary files</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/crate-ci/typos/commit/0d9e0c2c1bd7f770f6eb90f87780848ca02fc12c"><code>0d9e0c2</code></a> chore: Release</li> <li><a href="https://github.com/crate-ci/typos/commit/e5385b07a020af945231c06d33ec490fb77fc7b0"><code>e5385b0</code></a> chore(ci): Fix new release process</li> <li><a href="https://github.com/crate-ci/typos/commit/f08d1171e28430953c39c15beb330811e20ecfe2"><code>f08d117</code></a> chore: Release</li> <li><a href="https://github.com/crate-ci/typos/commit/e6e172498c285b815f8cbe3ada1bf51f02fd3b9a"><code>e6e1724</code></a> chore(ci): Fix new release process</li> <li><a href="https://github.com/crate-ci/typos/commit/02afc59fd4633b33c1f7b14b96f46402477dcc75"><code>02afc59</code></a> chore: Release</li> <li><a href="https://github.com/crate-ci/typos/commit/f981a1cd200c62b7ce895f09d269b3ee688ccad9"><code>f981a1c</code></a> chore(ci): Fix new release process</li> <li><a href="https://github.com/crate-ci/typos/commit/afbc96c5d3760227ecd31b4ed5f80415beeaaa86"><code>afbc96c</code></a> chore: Release</li> <li><a href="https://github.com/crate-ci/typos/commit/d3dcaaeb2d5bb61eadbd393a8803745af7c81290"><code>d3dcaae</code></a> chore(ci): Fix new release process</li> <li><a href="https://github.com/crate-ci/typos/commit/fb8217bd5e6531ce9c1992dd571f7f23d8fdc9c4"><code>fb8217b</code></a> chore: Release</li> <li><a href="https://github.com/crate-ci/typos/commit/88ea8ea67dcd07e71f5c9e397a2669c639786dd8"><code>88ea8ea</code></a> chore(ci): Stage releases until done</li> <li>Additional commits viewable in <a href="https://github.com/crate-ci/typos/compare/v1.26.0...v1.26.8">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.26.0&new-version=1.26.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 4b0efda Author: mamekoro <[email protected]> Date: Mon Oct 28 12:26:35 2024 +0900 Make some associated functions of `Color` const (bevyengine#16091) # Objective Make the following functions `const` that will be useful to define colors as constants. - `Color::srgb_from_array` - `Color::srgba_u8` - `Color::srgb_u8` The last two require Rust 1.82.0. ## Solution - Make them `const` - Change MSRV to 1.82.0 ## Testing I tested bevy_color only. My machine does not have enough RAM capacity to test the whole bevy. `cargo test -p bevy_color` commit 78a4bea Author: ickshonpe <[email protected]> Date: Sun Oct 27 22:39:32 2024 +0000 Move `ContentSize` requirements from `Node` to the widget defining components (bevyengine#16083) # Objective Missed this in the required components PR review. `ContentSize` isn't used by regular UI nodes, only those with intrinsically sized content that needs a measure func. ## Solution Remove `ContentSize` from `Node`'s required components and add it to the required components of `Text` and `UiImage`. --------- Co-authored-by: Alice Cecile <[email protected]> commit c4c1c8f Author: mgi388 <[email protected]> Date: Mon Oct 28 09:38:07 2024 +1100 Undeprecate is_playing_animation (bevyengine#16121) # Objective - Fixes bevyengine#16098 ## Solution - Undeprecate `is_playing_animation` and copy the docs from `animation_is_playing` to it. ## Testing - CI ## Migration https://github.com/bevyengine/bevy-website/blob/68e9a34e3068ed2e7db5ae0b4b32feac94a589dd/release-content/0.15/migration-guides/_guides.toml#L13-L17 needs to be removed. commit 3d72f49 Author: ickshonpe <[email protected]> Date: Sun Oct 27 20:08:51 2024 +0000 Layout rounding debug example (bevyengine#16096) # Objective Simple example for debugging layout rounding errors. <img width="1039" height="752" alt="layout_rounding_debug" src="https://github.com/user-attachments/assets/12673000-e267-467e-b25b-3f8001c1347c"> Any white lines are gaps in the layout caused by coordinate rounding errors. commit 86ee8e4 Author: ickshonpe <[email protected]> Date: Sun Oct 27 19:14:46 2024 +0000 Move `UiImage` from `ui_node` to the `widget::image` module (bevyengine#16084) # Objective `UiImage` isn't just a general image component now, it's the defining component for the image widget so it belongs in the image widget's module. commit d01db9b Author: Hexroll by Pen, Dice & Paper <[email protected]> Date: Sun Oct 27 19:08:34 2024 +0000 Adding alpha_threshold to OrderIndependentTransparencySettings for user-level optimization (bevyengine#16090) # Objective Order independent transparency can filter fragment writes based on the alpha value and it is currently hard-coded to anything higher than 0.0. By making that value configurable, users can optimize fragment writes, potentially reducing the number of layers needed and improving performance in favor of some transparency quality. ## Solution This PR adds `alpha_threshold` to the OrderIndependentTransparencySettings component and uses the struct to configure a corresponding shader uniform. This uniform is then used instead of the hard-coded value. To configure OIT with a custom alpha threshold, use: ```rust fn setup(mut commands: Commands) { commands.spawn(( Camera3d::default(), OrderIndependentTransparencySettings { layer_count: 8, alpha_threshold: 0.2, }, )); } ``` ## Testing I tested this change using the included OIT example, as well as with two additional projects. ## Migration Guide If you previously explicitly initialized OrderIndependentTransparencySettings with your own `layer_count`, you will now have to add either a `..default()` statement or an explicit `alpha_threshold` value: ```rust fn setup(mut commands: Commands) { commands.spawn(( Camera3d::default(), OrderIndependentTransparencySettings { layer_count: 16, ..default() }, )); } ``` --------- Co-authored-by: JMS55 <[email protected]> commit 3fc2bd7 Author: Rob Parrett <[email protected]> Date: Sun Oct 27 12:06:19 2024 -0700 Cosmetic tweaks to `query_gltf_primitives` (bevyengine#16102) # Objective This example is really confusing to look at and tell at a glance whether it's broken or not. It's displaying a strange shape -- a cube with two vertices stretched in a couple dimensions at an odd angle, and doing its vertex position modification in a way where the intent isn't obvious. ## Solution - Change the gltf geometry so that the object is a recognizable regular shape - Change the vertex modification so that the entire cube top is being "lifted" from the cube - Adjust colors, lighting, and camera location so we can see what's going on - Also remove some irrelevant shadow and environment map setup ## Before ![Image](https://github.com/user-attachments/assets/e5dd5075-0480-49d4-b1ed-cf1fe6106f3c) ## After <img width="1280" alt="image" src="https://github.com/user-attachments/assets/59cab60d-efbc-47c3-8688-e4544b462421"> commit 7451900 Author: Miles Silberling-Cook <[email protected]> Date: Sun Oct 27 15:05:31 2024 -0400 Emit picking event streams (bevyengine#16105) # Objective In `bevy_mod_picking` events are accessible through event listeners or `EventReader`s. When I replaced event listeners with observers, I removed the `EventReader` for simplicity. This adds it back. ## Solution All picking events are now properly registered, and can be accessed through `EventReader<Pointer<E>>`. `Pointer` now tracks the entity the event targeted initially, and this can also be helpful in observers (which don't currently do this). ## Testing The picking examples run fine. This shouldn't really change anything. --------- Co-authored-by: Aevyrie <[email protected]> commit 54b323e Author: Aevyrie <[email protected]> Date: Sun Oct 27 12:03:48 2024 -0700 Mesh picking fixes (bevyengine#16110) # Objective - Mesh picking is noisy when a non triangle list is used - Mesh picking runs even when users don't need it - Resolve bevyengine#16065 ## Solution - Don't add the mesh picking plugin by default - Remove error spam commit a644ac7 Author: Tau Gärtli <[email protected]> Date: Sun Oct 27 20:01:50 2024 +0100 More `#[doc(fake_variadic)]` goodness (bevyengine#16108) This PR adds `#[doc(fake_variadic)]` to that were previously not supported by rustdoc. Thanks to an [upstream contribution](rust-lang/rust#132115) by yours truly, `#[doc(fake_variadic)]` is now supported on impls such as `impl QueryData for AnyOf<(T, ...)>` 🎉 Requires the latest nightly compiler (2024-10-25) which is already available on [docs.rs](https://docs.rs/about/builds). ![image](https://github.com/user-attachments/assets/68589c7e-f68f-44fb-9a7b-09d24ccf19c9) ![image](https://github.com/user-attachments/assets/f09d20d6-d89b-471b-9a81-4a72c8968178) This means that the impl sections for `QueryData` and `QueryFilter` are now nice and tidy ✨ --- I also added `fake_variadic` to some impls that use `all_tuples_with_size`, however I'm not entirely happy because the docs are slightly misleading now: ![image](https://github.com/user-attachments/assets/fac93d08-dc02-430f-9f34-c97456256c56) Note that the docs say `IntoBindGroupLayoutEntryBuilderArray<1>` instead of `IntoBindGroupLayoutEntryBuilderArray<N>`. commit 60b2c7c Author: François Mockers <[email protected]> Date: Fri Oct 25 22:14:39 2024 +0200 fix bevy_dev_tools build (bevyengine#16099) # Objective - bevy_dev_tools 0.15.0-rc.1 failed to build docs - it use bevy_text feature in bevy_ui but it's not enabled by default - https://docs.rs/crate/bevy_dev_tools/0.15.0-rc.1 - ## Solution - enable bevy_text feature of bevy_ui commit 7c59317 Author: BD103 <[email protected]> Date: Fri Oct 25 16:11:51 2024 -0400 Fix `bevy_picking` plugin suffixes (bevyengine#16082) # Objective - `MeshPickingBackend` and `SpritePickingBackend` do not have the `Plugin` suffix - `DefaultPickingPlugins` is masquerading as a `Plugin` when in reality it should be a `PluginGroup` - Fixes bevyengine#16081. ## Solution - Rename some structures: |Original Name|New Name| |-|-| |`MeshPickingBackend`|`MeshPickingPlugin`| |`MeshPickingBackendSettings`|`MeshPickingSettings`| |`SpritePickingBackend`|`SpritePickingPlugin`| |`UiPickingBackendPlugin`|`UiPickingPlugin`| - Make `DefaultPickingPlugins` a `PluginGroup`. - Because `DefaultPickingPlugins` is within the `DefaultPlugins` plugin group, I also added support for nested plugin groups to the `plugin_group!` macro. ## Testing - I used ripgrep to ensure all references were properly renamed. - For the `plugin_group!` macro, I used `cargo expand` to manually inspect the expansion of `DefaultPlugins`. --- ## Migration Guide > [!NOTE] > > All 3 of the changed structures were added after 0.14, so this does not need to be included in the 0.14 to 0.15 migration guide. - `MeshPickingBackend` is now named `MeshPickingPlugin`. - `MeshPickingBackendSettings` is now named `MeshPickingSettings`. - `SpritePickingBackend` is now named `SpritePickingPlugin`. - `UiPickingBackendPlugin` is now named `UiPickingPlugin`. - `DefaultPickingPlugins` is now a a `PluginGroup` instead of a `Plugin`. commit 611ba8b Author: Ludwig DUBOS <[email protected]> Date: Fri Oct 25 22:08:14 2024 +0200 Add `AsyncSeekForwardExt` trait to allows a similar API to the previous Bevy version (bevyengine#16027) # Objective This PR introduces an `AsyncSeekForwardExt` trait, which I forgot in my previous PR bevyengine#14194. This new trait is analogous to `AsyncSeekExt` and allows all implementors of `AsyncSeekForward` to directly use the `seek_forward` function in async contexts. ## Solution - Implement a new `AsyncSeekForwardExt` trait - Automatically implement this trait for all types that implement `AsyncSeekForward` ## Showcase This new trait allows a similar API to the previous Bevy version: ```rust #[derive(Default)] struct UniverseLoader; #[derive(Asset, TypePath, Debug)] struct JustALilAsteroid([u8; 128]); impl AssetLoader for UniverseLoader { type Asset = JustALilAsteroid; type Settings = (); type Error = std::io::Error; async fn load<'a>( &'a self, reader: &'a mut Reader<'a>, _settings: &'a Self::Settings, _context: &'a mut LoadContext<'_>, ) -> Result<Self::Asset, Self::Error> { // read the asteroids entry table let entry_offset: u64 = /* ... */; let current_offset: u64 = reader.seek_forward(0).await?; // jump to the entry reader.seek_forward(entry_offset - current_offset).await?; let mut asteroid_buf = [0; 128]; reader.read_exact(&mut asteroid_buf).await?; Ok(JustALilAsteroid(asteroid_buf)) } fn extensions(&self) -> &[&str] { &["celestial"] } } ``` commit c6a66a7 Author: Patrick Walton <[email protected]> Date: Thu Oct 24 14:16:00 2024 -0700 Place percentage-closer soft shadows behind a feature gate to save on samplers. (bevyengine#16068) The two additional linear texture samplers that PCSS added caused us to blow past the limit on Apple Silicon macOS and WebGL. To fix the issue, this commit adds a `--feature pbr_pcss` feature gate that disables PCSS if not present. Closes bevyengine#15345. Closes bevyengine#15525. Closes bevyengine#15821. --------- Co-authored-by: Carter Anderson <[email protected]> Co-authored-by: IceSentry <[email protected]> commit 897404e Author: Patrick Walton <[email protected]> Date: Thu Oct 24 14:00:11 2024 -0700 Reduce the clusterable object UBO size below 16384 for WebGL 2. (bevyengine#16069) The PCSS PR bevyengine#13497 increased the size of clusterable objects from 64 bytes to 80 bytes but didn't decrease the UBO size to compensate, so we blew past the 16kB limit on WebGL 2. This commit fixes the issue by lowering the maximum number of clusterable objects to 204, which puts us under the 16kB limit again. Closes bevyengine#15998. commit 9274bfe Author: Carter Anderson <[email protected]> Date: Wed Oct 23 18:24:17 2024 -0500 Move TextureAtlas into UiImage and remove impl Component for TextureAtlas (bevyengine#16072) # Objective Fixes bevyengine#16064 ## Solution - Add TextureAtlas to `UiImage::texture_atlas` - Add `TextureAtlas::from_atlas_image` for parity with `Sprite` - Rename `UiImage::texture` to `UiImage::image` for parity with `Sprite` - Port relevant implementations and uses - Remove `derive(Component)` for `TextureAtlas` --- ## Migration Guide Before: ```rust commands.spawn(( UiImage::new(image), TextureAtlas { index, layout }, )); ``` After: ```rust commands.spawn(UiImage::from_atlas_image(image, TextureAtlas { index, layout })); ``` Before: ```rust commands.spawn(UiImage { texture: some_image, ..default() }) ``` After: ```rust commands.spawn(UiImage { image: some_image, ..default() }) ``` commit 2cdad48 Author: Viktor Gustavsson <[email protected]> Date: Wed Oct 23 23:51:39 2024 +0200 Ensure ghost nodes are skipped when getting parent clipping rect (bevyengine#16058) # Objective - Follow up on bevyengine#16044 - `extract_uinode_borders` uses `bevy_hierarchy` directly instead of going through the traversal utilities, meaning it won't handle `GhostNode`s properly. ## Solution - Replaced the use of `bevy_hierarchy::Parent` with `UIChildren::get_parent` ## Testing - Ran the `overflow` example, clipping looks ok. --- --------- Co-authored-by: Carter Anderson <[email protected]> commit c9a3f34 Author: ickshonpe <[email protected]> Date: Wed Oct 23 21:41:42 2024 +0100 Fixes for a few minor borders and outlines bugs (bevyengine#16071) # Objective 1. Nodes with `Display::None` set are removed from the layout and have no position or size. Outlines should not be drawn for a node with `Display::None` set. 2. The outline and border colors are checked for transparency together. If only one of the two is transparent, both will get queued. 3. The `node.is_empty()` check is insufficient to check if a border is present since a non-zero sized node can have a zero width border. ## Solution 1. Add a check to `extract_uinode_borders` and ignore the node if `Display::None` is set. 2. Filter the border and outline optional components by `is_fully_transparent`. 3. Check if all the border widths are zero instead. ## Testing I added dark cyan outlines around the left and right sections in the `display_and_visibility` example. If you run the example and set the outermost node to `Display::None` on the right, then you'll see the that the outline on the left disappears. commit 7577895 Author: Carter Anderson <[email protected]> Date: Wed Oct 23 15:05:28 2024 -0500 Use CosmicFontSystem in public bevy_text APIs and remove cosmic_text re-export (bevyengine#16063) # Objective Fixes bevyengine#16006 ## Solution We currently re-export `cosmic_text`, which is seemingly motivated by the desire to use `cosmic_text::FontSystem` in `bevy_text` public APIs instead of our `CosmicFontSystem` resource wrapper type. This change makes `bevy_text` a "true" abstraction over `cosmic_text` (it in fact, was already built to be that way generally and has this one "leak"). This allows us to remove the `cosmic_text` re-export, which helps clean up the Rust Analyzer imports and generally makes this a "cleaner" API. commit 3fb6cef Author: JMS55 <[email protected]> Date: Wed Oct 23 12:18:49 2024 -0700 Meshlet fill cluster buffers rewritten (bevyengine#15955) # Objective - Make the meshlet fill cluster buffers pass slightly faster - Address bevyengine#15920 for meshlets - Added PreviousGlobalTransform as a required meshlet component to avoid extra archetype moves, slightly alleviating bevyengine#14681 for meshlets - Enforce that MeshletPlugin::cluster_buffer_slots is not greater than 2^25 (glitches will occur otherwise). Technically this field controls post-lod/culling cluster count, and the issue is on pre-lod/culling cluster count, but it's still valid now, and in the future this will be more true. Needs to be merged after bevyengine#15846 and bevyengine#15886 ## Solution - Old pass dispatched a thread per cluster, and did a binary search over the instances to find which instance the cluster belongs to, and what meshlet index within the instance it is. - New pass dispatches a workgroup per instance, and has the workgroup loop over all meshlets in the instance in order to write out the cluster data. - Use a push constant instead of arrayLength to fix the linked bug - Remap 1d->2d dispatch for software raster only if actually needed to save on spawning excess workgroups ## Testing - Did you test these changes? If so, how? - Ran the meshlet example, and an example with 1041 instances of 32217 meshlets per instance. Profiled the second scene with nsight, went from 0.55ms -> 0.40ms. Small savings. We're pretty much VRAM bandwidth bound at this point. - How can other people (reviewers) test your changes? Is there anything specific they need to know? - Run the meshlet example ## Changelog (non-meshlets) - PreviousGlobalTransform now implements the Default trait commit 6d42830 Author: JMS55 <[email protected]> Date: Wed Oct 23 09:56:50 2024 -0700 Meshlet builder improvements redux (bevyengine#15886) Take a bunch more improvements from @zeux's nanite.cpp code. * Use position-only vertices (discard other attributes) to determine meshlet connectivity for grouping * Rather than using the lock borders flag when simplifying meshlet groups, provide the locked vertices ourselves. The lock borders flag locks the entire border of the meshlet group, but really we only want to lock the edges between meshlet groups - outwards facing edges are fine to unlock. This gives a really significant increase to the DAG quality. * Add back stuck meshlets (group has only a single meshlet, simplification failed) to the simplification queue to allow them to get used later on and have another attempt at simplifying * Target 8 meshlets per group instead of 4 (second biggest improvement after manual locks) * Provide a seed to metis for deterministic meshlet building * Misc other improvements We can remove the usage of unsafe after the next upstream meshopt release, but for now we need to use the ffi function directly. I'll do another round of improvements later, mainly attribute-aware simplification and using spatial weights for meshlet grouping. Need to merge bevyengine#15846 first. commit 50d38f2 Author: akimakinai <[email protected]> Date: Wed Oct 23 08:29:58 2024 +0900 Fix point light count limit (bevyengine#16062) # Objective - I made a mistake in bevyengine#15902, specifically [this diff](bevyengine@e2faedb) -- the `point_light_count` variable is used for all point lights, not just shadow mapped ones, so I cannot add `.min(max_texture_cubes)` there. (Despite `spot_light_count` having `.min(..)`) It may have broken code like this (where `index` is index of `point_light` vec): https://github.com/bevyengine/bevy/blob/9930df83ed42008f7eb2c02cc7350040f0250c2e/crates/bevy_pbr/src/render/light.rs#L848-L850 and also causes panic here: https://github.com/bevyengine/bevy/blob/9930df83ed42008f7eb2c02cc7350040f0250c2e/crates/bevy_pbr/src/render/light.rs#L1173-L1174 ## Solution - Adds `.min(max_texture_cubes)` directly to the loop where texture views for point lights are created. ## Testing - `lighting` example (with the directional light removed; original example doesn't crash as only 1 directional-or-spot light in total is shadow-mapped on webgl) no longer crashes on webgl commit 2223f6e Author: JMS55 <[email protected]> Date: Tue Oct 22 16:05:40 2024 -0700 Meshlet fix software rasterization (bevyengine#16049) # Objective 1. Prevent weird glitches with stray pixels scattered around the scene ![image](https://github.com/user-attachments/assets/f12adb38-5996-4dc7-bea6-bd326b7317e1) 2. Prevent weird glitchy full-screen triangles that pop-up and destroy perf (SW rasterizing huge triangles is slow) ![image](https://github.com/user-attachments/assets/d3705427-13a5-47bc-a54b-756f0409da0b) ## Solution 1. Use floating point math in the SW rasterizer bounding box calculation to handle negative verticss, and add backface culling 2. Force hardware raster for clusters that clip the near plane, and let the hardware rasterizer handle the clipping I also adjusted the SW rasterizer threshold to < 64 pixels (little bit better perf in my test scene, but still need to do a more comprehensive test), and enabled backface culling for the hardware raster pipeline. ## Testing - Did you test these changes? If so, how? - Yes, on an example scene. Issues no longer occur. - Are there any parts that need more testing? - No. - How can other people (reviewers) test your changes? Is there anything specific they need to know? - Run the meshlet example. commit fe4f44b Author: François Mockers <[email protected]> Date: Wed Oct 23 00:37:04 2024 +0200 crate publish order: bevy_animation depends on bevy_animation_derive (bevyengine#16060) # Objective - bevy_animation publication fails because of missed dependency - bevy_animation depends on bevy_animation_derive which is published after ## Solution - Reorder crates bevy_animation and bevy_animation_derive commit fac0b34 Author: François Mockers <[email protected]> Date: Tue Oct 22 22:21:19 2024 +0200 remove reference to missing file in bevy_remote cargo.toml (bevyengine#16057) # Objective - bevy_remote Cargo.toml file references a readme that doesn't exist - This is blocking releasing the rc ## Solution - Remove the reference commit 9d54fe0 Author: JMS55 <[email protected]> Date: Tue Oct 22 13:14:30 2024 -0700 Meshlet new error projection (bevyengine#15846) * New error projection code taken from @zeux's meshoptimizer nanite.cpp demo for determining LOD (thanks zeux!) * Builder: `compute_lod_group_data()` * Runtime: `lod_error_is_imperceptible()` commit 9930df8 Author: ickshonpe <[email protected]> Date: Mon Oct 21 23:54:09 2024 +0100 UI borders and outlines clipping fix (bevyengine#16044) # Objective fixes bevyengine#15502 Clipped borders and outlines aren't drawn correctly. ### Borders aren't clipped Spawn two nodes with the same dimensions and border thickness, but clip on of the nodes so that only its top left quarter is visible: <img width="194" alt="clip" src="https://github.com/user-attachments/assets/2d3f6d28-aa20-44df-967a-677725828294"> You can see that instead of clipping the border, instead the border is scaled to fit inside of the unclipped section. ```rust use bevy::color::palettes::css::BLUE; use bevy::prelude::*; use bevy::winit::WinitSettings; fn main() { App::new() .add_plugins(DefaultPlugins) .insert_resource(WinitSettings::desktop_app()) .add_systems(Startup, setup) .run(); } fn setup(mut commands: Commands) { commands.spawn(Camera2d); commands .spawn(Node { width: Val::Percent(100.), height: Val::Percent(100.), justify_content: JustifyContent::Center, align_items: AlignItems::Center, ..Default::default() }) .with_children(|commands| { commands .spawn(Node { column_gap: Val::Px(10.), ..Default::default() }) .with_children(|commands| { commands .spawn(Node { width: Val::Px(100.), height: Val::Px(100.), overflow: Overflow::clip(), ..Default::default() }) .with_child(( Node { position_type: PositionType::Absolute, width: Val::Px(100.), height: Val::Px(100.), border: UiRect::all(Val::Px(10.)), ..Default::default() }, BackgroundColor(Color::WHITE), BorderColor(BLUE.into()), )); commands .spawn(Node { width: Val::Px(50.), height: Val::Px(50.), overflow: Overflow::clip(), ..Default::default() }) .with_child(( Node { position_type: PositionType::Absolute, width: Val::Px(100.), height: Val::Px(100.), border: UiRect::all(Val::Px(10.)), ..Default::default() }, BackgroundColor(Color::WHITE), BorderColor(BLUE.into()), )); }); }); } ``` You can also see this problem in the `overflow` example. If you hover over any of the clipped nodes you'll see that the outline only wraps the visible section of the node ### Outlines are clipped incorrectly A UI nodes Outline's are drawn outside of its bounds, so applying the local clipping rect to the outline doesn't make any sense. Instead an `Outline` should be clipped using its parent's clipping rect. ## Solution * Pass the `point` value into the vertex shader instead of calculating it in the shader. * In `extract_uinode_borders` use the parents clipping rect when clipping outlines. The extra parameter isn't a great solution I think, but I wanted to fix borders for the 0.15 release and this is the most minimal approach I could think of without replacing the whole shader and prepare function. ## Showcase <img width="149" alt="clipp" src="https://github.com/user-attachments/assets/19fbd3cc-e7cd-42e1-a5e0-fd92aad04dcd"> --------- Co-authored-by: Alice Cecile <[email protected]> commit d0af199 Author: Stepan Koltsov <[email protected]> Date: Mon Oct 21 16:57:52 2024 +0100 Add a test for Mesh::triangles and fix for TriangleStrip (bevyengine#16026) # Objective - Illustrate behavior with a test - Fix a bug revealed by a test ## Solution - Add a test and fix ## Testing Test added. commit 465d113 Author: Stepan Koltsov <[email protected]> Date: Mon Oct 21 03:17:59 2024 +0100 Replace TwoIterators with Either in bevy_animation (bevyengine#16036) # Objective - Less code - Better iterator (implements `size_hint` for example) ## Solution - Use `either` - This change is free because `bevy_animation` depends on `bevy_asset`, which already depends on `either` ## Testing CI
…yengine#13497)"" This reverts commit 92ffc96.
Percentage-closer soft shadows are a technique from 2004 that allow shadows to become blurrier farther from the objects that cast them. It works by introducing a blocker search step that runs before the normal shadow map sampling. The blocker search step detects the difference between the depth of the fragment being rasterized and the depth of the nearby samples in the depth buffer. Larger depth differences result in a larger penumbra and therefore a blurrier shadow.
To enable PCSS, fill in the
soft_shadow_size
value inDirectionalLight
,PointLight
, orSpotLight
, as appropriate. This shadow size value represents the size of the light and should be tuned as appropriate for your scene. Higher values result in a wider penumbra (i.e. blurrier shadows).When using PCSS, temporal shadow maps (
ShadowFilteringMethod::Temporal
) are recommended. If you don't useShadowFilteringMethod::Temporal
and instead useShadowFilteringMethod::Gaussian
, Bevy will use the same technique asTemporal
, but the result won't vary over time. This produces a rather noisy result. Doing better would likely require downsampling the shadow map, which would be complex and slower (and would require PR #13003 to land first).In addition to PCSS, this commit makes the near Z plane for the shadow map configurable on a per-light basis. Previously, it had been hardcoded to 0.1 meters. This change was necessary to make the point light shadow map in the example look reasonable, as otherwise the shadows appeared far too aliased.
A new example,
pcss
, has been added. It demonstrates the percentage-closer soft shadow technique with directional lights, point lights, spot lights, non-temporal operation, and temporal operation. The assets are my original work.Both temporal and non-temporal shadows are rather noisy in the example, and, as mentioned before, this is unavoidable without downsampling the depth buffer, which we can't do yet. Note also that the shadows don't look particularly great for point lights; the example simply isn't an ideal scene for them. Nevertheless, I felt that the benefits of the ability to do a side-by-side comparison of directional and point lights outweighed the unsightliness of the point light shadows in that example, so I kept the point light feature in.
Fixes #3631.
Changelog
Added
Percentage-closer soft shadows (PCSS) are now supported, allowing shadows to become blurrier as they stretch away from objects. To use them, set the
soft_shadow_size
field inDirectionalLight
,PointLight
, orSpotLight
, as applicable.The near Z value for shadow maps is now customizable via the
shadow_map_near_z
field inDirectionalLight
,PointLight
, andSpotLight
.Screenshots
PCSS off:
PCSS on: