Commit Graph

12 Commits

Author SHA1 Message Date
Carter Anderson 535cf401cc Reframe old "scene" terminology as "world serialization" (#23630)
Part 2 of #23619 

In **Bevy 0.19** we are landing a subset of Bevy's Next Generation Scene
system (often known as BSN), which now lives in the `bevy_scene` /
`bevy::scene` crate. However the old `bevy_scene` system still needs to
stick around for a bit longer, as it provides some features that Bevy's
Next Generation Scene system doesn't (yet!):

1. It is not _yet_ possible to write a World _to_ BSN, so the old system
is still necessary for "round trip World serialization".
2. The GLTF scene loader has not yet been ported to BSN, so the old
system is still necessary to spawn GLTF scenes in Bevy.

For this reason, we have renamed the old `bevy_scene` crate to
`bevy_world_serialization`. If you were referencing `bevy_scene::*` or
`bevy::scene::*` types, rename those paths to
`bevy_world_serialization::*` and `bevy::world_serialization::*`
respectively.

Additionally, to avoid confusion / conflicts with the new scene system,
all "scene" terminology / types have been reframed as "world
serialization":

- `Scene` -> `WorldAsset` (as this was always just a World wrapper)
- `SceneRoot` -> `WorldAssetRoot`
- `DynamicScene` -> `DynamicWorld`
    - `DynamicScene::from_scene` -> `DynamicWorld::from_world_asset`
- `DynamicSceneBuilder` -> `DynamicWorldBuilder`
- `DynamicSceneRoot` -> `DynamicWorldRoot`
- `SceneInstanceReady` -> `WorldInstanceReady`
- `SceneLoader` -> `WorldAssetLoader`
- `ScenePlugin` -> `WorldSerializationPlugin`
- `SceneRootTemplate` -> `WorldAssetRootTemplate`
- `SceneSpawner` -> `WorldInstanceSpawner`
- `SceneFilter` -> `WorldFilter`
- `SceneLoaderError` -> `WorldAssetLoaderError`
- `SceneSpawnError` -> `WorldInstanceSpawnError`

Note that I went with `bevy_world_serialization` over
`bevy_ecs_serialization`, as that is what all of the internal features
described themselves as. I think it is both more specific and does a
better job of making itself decoupled from `bevy_ecs` proper.
2026-04-04 00:31:47 +00:00
Greeble 9d2db8838f Improve frustum culling of skinned meshes through per-joint bounds (#21837)
## Objective

Mostly fix #4971 by adding a new option for updating skinned mesh `Aabb`
components from joint transforms.


https://github.com/user-attachments/assets/c25b31fa-142d-462b-9a1d-012ea928f839

This fixes cases where vertex positions are only modified through
skinning. It doesn't fix other cases like morph targets and vertex
shaders.

The PR kind of upstreams
[`bevy_mod_skinned_aabb`](https://github.com/greeble-dev/bevy_mod_skinned_aabb),
but with some changes to make it simpler and more reliable.

### Dependencies

- (MERGED) #21732 (or something similar) is desirable to make the new
option work with `RenderAssetUsages::RENDER_WORLD`-only meshes.
- This PR is authored as if 21732 has landed. But if that doesn't happen
then I can adjust this PR to note the limitation.
- (Optional) #21845 adds an option related to skinned mesh bounds.
  - Either PR can land first - the second will need to be updated.

## Background

If a main world entity has a `Mesh3d` component then it's automatically
assigned an `Aabb` component. This is done by `bevy_camera` or
`bevy_gltf`. The `Aabb` is used by `bevy_camera` for frustum culling. It
can also be used by `bevy_picking` as an optimization, and by third
party crates.

But there's a problem - the `Aabb` can be wrong if something changes the
mesh's vertex positions after the `Aabb` is calculated. This can be done
by vertex shaders - notably skinning and morph targets - or by mutating
the `Mesh` asset (#4294).

For the skinning case, the most common solution has been to disable
frustum culling via the `NoFrustumCulling` component. This is simple,
and might even be the most efficient approach for apps where meshes tend
to stay on-screen. But it's annoying to implement, bad for apps where
meshes are often off-screen, and it only fixes frustum culling - it
doesn't help other systems that use the `Aabb`.

## Solution

This PR adds a reliable and reasonably efficient method of updating the
`Aabb` of a skinned mesh from its animated joint transforms. See the
"How does it work" section for more detail.

The glTF loader can add skinned bounds automatically if a new
`GltfSkinnedMeshBoundsPolicy` option is enabled in `GltfPlugin` or
`GltfLoaderSettings`:

```rust
app.add_plugins(DefaultPlugins.set(GltfPlugin {
    skinned_mesh_bounds_policy: GltfSkinnedMeshBoundsPolicy::Dynamic,
    ..default()
}))
```

_The new glTF loader option is enabled by default_. I think this is the
right choice for several reasons:

- Bugs caused by skinned mesh culling have been a regular pain for both
new and experienced users. Now the most common case Just Works(tm).
- The CPU cost is modest (see later section), and sophisticated users
can opt-out.
- GPU limited apps might see a performance increase if the user was
previously disabling culling.

Non-glTF cases require some manual steps. The user must ask `Mesh` to
generate the skinned bounds, and then add the `DynamicSkinnedMeshBounds`
marker component to their mesh entity.

```rust
mesh.generate_skinned_mesh_bounds()?;
let mesh_asset = mesh_assets.add(mesh);
entity.insert((Mesh3d(mesh_asset), DynamicSkinnedMeshBounds));
```

See the `custom_skinned_mesh` example for real code.

## Bonus Features

### `GltfSkinnedMeshBoundsPolicy::NoFrustumCulling`

This is a convenience for users who prefer the `NoFrustumCulling`
workaround, but want to avoid the hassle of adding it after a glTF scene
has been spawned.

```rust
app.add_plugins(DefaultPlugins.set(GltfPlugin {
    skinned_mesh_bounds_policy: GltfSkinnedMeshBoundsPolicy::NoFrustumCulling,
    ..default()
}))
```

PR #21845 is also adding an option related to skinned mesh bounds. I'm
fine if that PR lands first - I'll update this PR to include the option.

### Gizmos

`bevy_gizmos::SkinnedMeshBoundsGizmoPlugin` can draw the per-joint
AABBs.

```rust
fn toggle_skinned_mesh_bounds(mut config: ResMut<GizmoConfigStore>) {
    config.config_mut::<SkinnedMeshBoundsGizmoConfigGroup>().1.draw_all ^= true;
}
```

The name is debatable. It's not technically drawing the bounds of the
skinned mesh - it's drawing the per-joint bounds that contribute to the
bounds of the skinned mesh.

## Testing

```sh
cargo run --example test_skinned_mesh_bounds

# Press `B` to show mesh bounds, 'J' to show joint bounds.
cargo run --example scene_viewer --features "free_camera" -- "assets/models/animated/Fox.glb"
cargo run --example scene_viewer --features "free_camera" -- "assets/models/SimpleSkin/SimpleSkin.gltf"

# More complicated mesh downloaded from https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/RecursiveSkeletons
cargo run --example scene_viewer --features "free_camera" -- "RecursiveSkeletons.glb"

cargo run --example custom_skinned_mesh
```

I also hacked `custom_skinned_mesh` to simulate awkward cases like
rotated and off-screen entities.

## How Does It Work?

<details><summary>Click to expand</summary>

### Summary

`Mesh::generated_skinned_mesh_bounds` calculates an AABB for each joint
in the mesh - the AABB encloses all the vertices skinned to that joint.
Then every frame, `bevy_camera::update_skinned_mesh_bounds` uses the
current joint transforms to calculate an `Aabb` that encloses all the
joint AABBs.

This approach is reliable, in that the final `Aabb` will always enclose
the skinned vertices. But it can be larger than necessary. In practice
it's tight enough to be useful, and rarely more than 50% bigger.

This approach works even with non-rigid transforms and soft skinning. If
there's any doubt then I can add more detail.

### Awkward Bits

The solution is not as simple and efficient as it could be.

#### Problem 1: Joint transforms are world-space, `Aabb` is
entity-space.

- Ideally we'd use the world-space joint transforms to calculate a
world-space `Aabb`, but that's not possible.
- The obvious solution is to transform the joints to entity-space, so
the `Aabb` is directly calculated in entity-space.
  - But that means an extra matrix multiply per joint.
- This PR calculates the `Aabb` in world-space and then transforms it to
entity-space.
- That avoids a matrix multiply per-joint, but can increase the size of
the `Aabb`.

#### Problem 2: Joint AABBs are in a surprising(?) space.

- When creating joint AABBs from a mesh, the intuitive solution would be
to calculate them in joint-space.
- Then the update just has to transform them by the world-space joint
transform.
- But to calculate them in joint-space we need both the bind pose vertex
positions and the bind pose joint transforms.
- These two parts are in separate assets - `Mesh` and
`SkinnedMeshInverseBindposes` - and those assets can be mixed and
matched.
- So we'd need to calculate a `SkinnedMeshBoundsAsset` for each
combination of `Mesh` and `SkinnedMeshInverseBindposes`.
- (`bevy_mod_skinned_aabb` uses this approach - it's slow and fragile.)
- This PR calculates joint AABBs in *mesh-space* (or more strictly
speaking: bind pose space).
  - That can be done with just the `Mesh` asset.
- One downside is that the update needs an extra matrix multiply so we
can go from mesh-space to world-space.
- However, this might become a performance advantage if frustum culling
changes - see the "Future Options" section.
- Another minor downside is that mesh-space AABBs (red in the screenshot
below) tend to be bigger than joint-space AABBs (green), since joints
with one long axis might be at an awkward angle in mesh-space.

<img width="1085" height="759" alt="image"
src="https://github.com/user-attachments/assets/a02a28c3-8882-412c-9be1-64109b767da7"
/>

### Future Options

For frustum culling there's a cheeky way to optimize and simplify
skinned bounds - put frustum culling in the renderer and calculate a
world-space AABB during `extract_skins`. The joint transform will be
already loaded and in the right space, so we can avoid an entity lookup
and matrix multiply. I estimate this would make skinned bounds 3x
faster.

Another option is to change main world frustum culling to use a
world-space AABB. So there would be a new `GlobalAabb` component that
gets updated each frame from `Aabb` and the entity transform (which is
basically the same as transform propagation and the relationship between
`Transform` and `GlobalTransform`). This has some advantages and
disadvantages but I won't get into them here - I think putting frustum
culling into the renderer is a better option.

(Note that putting frustum culling into the renderer doesn't mean
removing the current main world visibility system - it just means the
main world system would be separate opt-in system)

</details>

## Performance

<details><summary>Click to expand</summary>

### Initialization

Creating the skinned bounds asset for `Fox.glb` (576 verts, 22 skinned
joints) takes **0.03ms**. Loading the whole glTF takes 8.7ms, so this is
a **<1% increase**.

### Per-Frame

The `many_foxes` example has 1000 skinned meshes, each with 22 skinned
joints. Updating the skinned bounds takes **0.086ms**. This is a
throughput of roughly 250,000 joints per millisecond, using two threads.

<img width="2404" height="861" alt="image"
src="https://github.com/user-attachments/assets/c27165ae-dc6c-4f6b-bbfb-4e211ab0263c"
/>

The whole animation update takes 3.67ms (where "animation update" =
advancing players + graph evaluation + transform propagation). So we can
kinda sorta claim that this PR increases the cost of skinned animation
by roughly **3%**. But that's very hand-wavey and situation dependent.

This was tested on an AMD Ryzen 7900 but with
`TaskPoolOptions::with_num_threads(6)` to simulate a lower spec CPU.
Comparing against a few other threading options:

- Non-parallel: **0.141ms**.
- 6 threads (2 compute threads): **0.086ms**.
- 24 threads (15 compute threads): **0.051ms**.

So the parallel iterator is better but quickly hits diminishing returns
as the number of threads increases.

### Future Options

The "How Does It Work" section mentions moving skinned mesh bounds into
the renderer's skin extraction. Based on some microbenchmarks, I
estimate this would reduce non-parallel `many_foxes` from 0.141ms to
0.049ms, so roughly 3x faster. Requiring AVX2 (to enable broadcast
loads) or pre-splatting (to fake broadcast loads for SSE) would knock
off another 25%. And fancier SIMD approaches could do better again.

There's also approaches that trade reliability for performance. For
character rigs, an effective optimization is to fold face and finger
joints into a single bound on the head and hand joints. This can reduce
the number of joints required by 50-80%.

</details>

## FAQ

<details><summary>Click to expand</summary>

#### Why can't it be automatically added to any mesh? Then the glTF
importer and custom mesh generators wouldn't need special logic.

`bevy_mod_skinned_aabb` took the automatic approach, and I don't think
the outcome was good. It needs some surprisingly fiddly and fragile
logic to decide when an entity has the right combination of assets in
the right loaded state. And it can never work with
`RenderAssetUsages::RENDER_WORLD`.

So this PR takes a more modest and manual approach. I think there's
plenty of scope to generalise and automate as the asset pipeline
matures. If the glTF importer becomes a purer glTF -> BSN transform,
then adding skinned bounds could be a general scene/asset transform
that's shared with other importers and custom mesh generators.

#### Why is the data in `Mesh`? Shouldn't it go in `SkinnedMesh` or
`SkinnedMeshInverseBindposes`?

That might seem intuitive, but it wouldn't work in practice - the data
is derived from `Mesh` alone. `SkinnedMesh` doesn't work because it's
per mesh instance, so the data would be duplicated.
`SkinnedMeshInverseBindposes` doesn't work because it can be shared
between multiple meshes.

The names are a bit misleading - `Mesh` does contain some skinning data,
while `SkinnedMesh` and `SkinnedMeshInverseBindposes` are more like
joint bindings one step removed from the vertex data.

#### Why not put the bounds on the joint entities?

This is surprisingly tricky in practice because multiple meshes can be
bound to the same joint entity. So there would need to be logic that
tracks the bindings and updates the bounds as meshes are added and
removed.

#### Why is the `DynamicSkinnedMeshBounds` component required?

It's an optimisation for users who want to opt out. It might also be
useful for future expansion, like adding options to approximate the
bounds with an AABB attached to a single joint.

#### Why are the update system and `DynamicSkinnedMeshBounds` component
in `bevy_camera`? Shouldn't they be in `bevy_mesh`?

`bevy_camera` is the owner and main user of `Aabb`, and already has some
mesh related logic (`calculate_bounds` automatically adds an `Aabb` to
mesh entities). So putting it in `bevy_camera` is consistent with the
current structure. I'd agree that it's a little awkward though and could
change in future.

</details>

## What Do Other Engines Do?

<details><summary>Click to expand</summary>

- **Unreal**: Automatically uses [collision
shapes](https://dev.epicgames.com/documentation/en-us/unreal-engine/physics-asset-editor-in-unreal-engine)
attached to joints, which is similar to this PR in practice but fragile
and inefficient. Also supports various fixed bounds options.
- **Unity**: Fixed bounds attached to the root bone. Automatically
calculated from animation poses or specified manually
([documentation](https://docs.unity3d.com/6000.4/Documentation/Manual/troubleshooting-skinned-mesh-renderer-visibility.html)).
- **Godot**: Appears to use roughly the same method as this PR, although
I didn't 100% confirm. See
[`MeshStorage::mesh_get_aabb`](https://github.com/godotengine/godot/blob/fafc07335bdecacd96b548c4119fbe1f47ee5866/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp#L650)
and
[`RendererSceneCull::_update_instance_aabb`](https://github.com/godotengine/godot/blob/235a32ad11f40ecba26d6d9ceea8ab245c13adb0/servers/rendering/renderer_scene_cull.cpp#L1991).
- **O3DE**: Fixed bounds attached to root bone, plus option to
approximate the AABB from joint origins and a fudge factor.
- **Northlight** (Remedy, Alan Wake 2): Specifically for vegetation,
calculates bounds from joint extents on GPU
([source](https://gdcvault.com/play/1034310/Large-Scale-GPU-Based-Skinning),
slide 48)

An approach that's been proposed several times for Bevy is copying
Unity's "fixed AABB from animation poses". I think this is more
complicated and less reliable than many people expect. More complicated
because linking animations to meshes can often be difficult. Less
reliable because it doesn't account for ragdolls and procedural
animation. But it could still be viable for for simple cases like a
single self-contained glTF with basic animation.

</details>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-01-26 04:25:59 +00:00
Aevyrie a88af65738 Contact Shadows (#22382)
# Objective

- Implement contact shadows to add fine shadow detail where shadow
cascades cannot.

## Solution

- Extend our existing pbr implementation using our existing raymarching
functions.

---

## Showcase

<img width="1824" height="1180" alt="image"
src="https://github.com/user-attachments/assets/e93b79c5-c596-4a9e-b94d-20bdde1d863b"
/>

<img width="1824" height="1180" alt="image"
src="https://github.com/user-attachments/assets/0fd7dffa-60b8-4b92-8fad-7f993d4d89dd"
/>


https://github.com/user-attachments/assets/e74b190d-9ae3-4aaf-97f0-b520930a0667


https://github.com/user-attachments/assets/e80ccb26-bbaa-4d25-a823-8ea12354c5b9


https://github.com/user-attachments/assets/b04f4b00-92bd-4a2f-b7dd-5157d8fbe0ab

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/b7629908-dd32-48db-8ee7-a4d2dd8f66c2"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/3de0258e-9191-4180-ac57-41b32e1205bd"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/951477f9-e9a9-426f-ae8d-18ae50cc7b85"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/2291453c-da57-4fcc-a6b0-f60f6eac6cbb"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/5820cdff-ea54-4294-b520-2a8d8dc24996"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/3ea16481-7689-4e99-87e2-1589f1532e4c"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: charlotte 🌸 <charlotte.c.mcelwain@gmail.com>
2026-01-13 21:51:39 +00:00
Trashtalk217 d431f7e139 Split AmbientLight into two (#21595)
# Objective

For resources-as-components (#19731), structs mustn't doubly derive both
`Component` and `Resource`.

## Solution

Split `AmbientLight` in two: `AmbientLight` (the resource) and
`AmbientLightOverride` (the component).

## Testing

I initially made two structs `AmbientLightComponent` and
`AmbientLightResource`, and replaced every mention with the relevant one
to ensure that I didn't confuse the two.

## Notes

- I don't know if the names are correct. I kept the easiest name for the
resource, as that's the one most often used.
- I haven't provided any conversion methods as there are already plans
to replace the component variant with something else.

---------

Co-authored-by: atlv <email@atlasdostal.com>
2025-10-21 23:04:39 +00:00
atlv f6b77e4e49 bevy_post_process (#20778)
# Objective

Split out post process effects from bevy_core_pipeline because they are
not core pipelines.

## Solution

@IceSentry proposed something like this, not sure if the split is
exactly as he envisioned but this seems reasonable to me.

The goal is to move absolutely everything possible out of
bevy_core_pipelines to unblock bevy_pbr/bevy_sprite_render compilation.

Future PRs may attempt to move more little bits out.

## Testing
2025-09-05 04:26:08 +00:00
TheBlckbird 13877fa84d Add a new trait to accept more types in the Val-helper functions (#20551)
# Objective

- Allow the `Val`-helper functions to accept more types besides just
`f32`

Fixes #20549

## Solution

- Adds a new trait that can be implemented for numbers
- That trait has a method that converts `self` to `f32`

## Testing

- I tested it using Rust's testing framework (although I didn't leave
the tests in, as I don't deem them important enough)

<details>
  <summary>Rust test</summary>

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_val_helpers_work() {
        let p = px(10_u8);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10_u16);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10_u32);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10_u64);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10_u128);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10_i8);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10_i16);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10_i32);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10_i64);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10_i128);
        assert_eq!(p, Val::Px(10.0));

        let p = px(10.3_f32);
        assert_eq!(p, Val::Px(10.3));

        let p = px(10.6_f64);
        assert_eq!(p, Val::Px(10.6));
    }
}
```
</details>

---

## Showcase

```rust
// Same as Val::Px(10.)
px(10);
px(10_u8);
px(10.0);
```
2025-08-29 20:18:57 +00:00
atlv 68b848217f Yeet RenderAssetUsages re-export (#20498)
# Objective

- Forgor to yeet this

## Solution

- rember and yeet

## Testing

cargo check --examples --all-features
2025-08-11 01:42:08 +00:00
atlv 03dd839b82 Use bevy::camera in examples instead of bevy::render::camera re-export (#20477)
# Objective

- Prepare for removing re-exports

## Solution

- title

## Testing

- cargo check --examples
2025-08-09 21:09:48 +00:00
atlv acc8f6d455 Stop using mesh re-exports in-repo and add bevy_mesh prelude (#20473)
# Objective

- prepare to remove bevy_mesh re-export from bevy_render. This will be
done in 0.18, but we might as well prepare for it now.

## Solution

- Add a prelude and use bevy_mesh directly. After this pr and #20471, we
will be ready.

## Testing

- cargo check --examples
2025-08-09 17:46:27 +00:00
Greeble 0f75142560 Add test for invalid skinned meshes (#18763)
## Objective

Add a test that would have caught #16929 and #18712.

## Solution

The PR adds a `test_invalid_skinned_mesh` example that creates various
valid and invalid skinned meshes. This is designed to catch panics via
CI, and can be inspected visually. It also tests skinned meshes + motion
blur.


![417958065-37df8799-b068-48b8-87a4-1f144e883c9c](https://github.com/user-attachments/assets/22b2fa42-628b-48a4-9013-76d6524cecf5)

The screenshot shows all the tests, but two are currently disabled as
they cause panics. #18074 will re-enable them.

### Concerns

- The test is not currently suitable for screenshot comparison.
- I didn't add the test to CI. I'm a bit unsure if this should be part
of the PR or a follow up discussion.
- Visual inspection requires understanding why some meshes are
deliberately broken and what that looks like.
- I wasn't sure about naming conventions. I put `test` in the name so
it's not confused with a real example.

## Testing

```
cargo run --example test_invalid_skinned_mesh
```

Tested on Win10/Nvidia, across Vulkan, WebGL/Chrome, WebGPU/Chrome.
2025-07-07 19:28:52 +00:00
Griffin a15d152635 Deferred Renderer (#9258)
# Objective

- Add a [Deferred
Renderer](https://en.wikipedia.org/wiki/Deferred_shading) to Bevy.
- This allows subsequent passes to access per pixel material information
before/during shading.
- Accessing this per pixel material information is needed for some
features, like GI. It also makes other features (ex. Decals) simpler to
implement and/or improves their capability. There are multiple
approaches to accomplishing this. The deferred shading approach works
well given the limitations of WebGPU and WebGL2.

Motivation: [I'm working on a GI solution for
Bevy](https://youtu.be/eH1AkL-mwhI)

# Solution
- The deferred renderer is implemented with a prepass and a deferred
lighting pass.
- The prepass renders opaque objects into the Gbuffer attachment
(`Rgba32Uint`). The PBR shader generates a `PbrInput` in mostly the same
way as the forward implementation and then [packs it into the
Gbuffer](https://github.com/DGriffin91/bevy/blob/ec1465559f2c82001830e908fc02ff1d7c2efe51/crates/bevy_pbr/src/render/pbr.wgsl#L168).
- The deferred lighting pass unpacks the `PbrInput` and [feeds it into
the pbr()
function](https://github.com/DGriffin91/bevy/blob/ec1465559f2c82001830e908fc02ff1d7c2efe51/crates/bevy_pbr/src/deferred/deferred_lighting.wgsl#L65),
then outputs the shaded color data.

- There is now a resource
[DefaultOpaqueRendererMethod](https://github.com/DGriffin91/bevy/blob/ec1465559f2c82001830e908fc02ff1d7c2efe51/crates/bevy_pbr/src/material.rs#L599)
that can be used to set the default render method for opaque materials.
If materials return `None` from
[opaque_render_method()](https://github.com/DGriffin91/bevy/blob/ec1465559f2c82001830e908fc02ff1d7c2efe51/crates/bevy_pbr/src/material.rs#L131)
the `DefaultOpaqueRendererMethod` will be used. Otherwise, custom
materials can also explicitly choose to only support Deferred or Forward
by returning the respective
[OpaqueRendererMethod](https://github.com/DGriffin91/bevy/blob/ec1465559f2c82001830e908fc02ff1d7c2efe51/crates/bevy_pbr/src/material.rs#L603)

- Deferred materials can be used seamlessly along with both opaque and
transparent forward rendered materials in the same scene. The [deferred
rendering
example](https://github.com/DGriffin91/bevy/blob/deferred/examples/3d/deferred_rendering.rs)
does this.

- The deferred renderer does not support MSAA. If any deferred materials
are used, MSAA must be disabled. Both TAA and FXAA are supported.

- Deferred rendering supports WebGL2/WebGPU. 

## Custom deferred materials
- Custom materials can support both deferred and forward at the same
time. The
[StandardMaterial](https://github.com/DGriffin91/bevy/blob/ec1465559f2c82001830e908fc02ff1d7c2efe51/crates/bevy_pbr/src/render/pbr.wgsl#L166)
does this. So does [this
example](https://github.com/DGriffin91/bevy_glowy_orb_tutorial/blob/deferred/assets/shaders/glowy.wgsl#L56).
- Custom deferred materials that require PBR lighting can create a
`PbrInput`, write it to the deferred GBuffer and let it be rendered by
the `PBRDeferredLightingPlugin`.
- Custom deferred materials that require custom lighting have two
options:
1. Use the base_color channel of the `PbrInput` combined with the
`STANDARD_MATERIAL_FLAGS_UNLIT_BIT` flag.
[Example.](https://github.com/DGriffin91/bevy_glowy_orb_tutorial/blob/deferred/assets/shaders/glowy.wgsl#L56)
(If the unlit bit is set, the base_color is stored as RGB9E5 for extra
precision)
2. A Custom Deferred Lighting pass can be created, either overriding the
default, or running in addition. The a depth buffer is used to limit
rendering to only the required fragments for each deferred lighting
pass. Materials can set their respective depth id via the
[deferred_lighting_pass_id](https://github.com/DGriffin91/bevy/blob/b79182d2a32cac28c4213c2457a53ac2cc885332/crates/bevy_pbr/src/prepass/prepass_io.wgsl#L95)
attachment. The custom deferred lighting pass plugin can then set [its
corresponding
depth](https://github.com/DGriffin91/bevy/blob/ec1465559f2c82001830e908fc02ff1d7c2efe51/crates/bevy_pbr/src/deferred/deferred_lighting.wgsl#L37).
Then with the lighting pass using
[CompareFunction::Equal](https://github.com/DGriffin91/bevy/blob/ec1465559f2c82001830e908fc02ff1d7c2efe51/crates/bevy_pbr/src/deferred/mod.rs#L335),
only the fragments with a depth that equal the corresponding depth
written in the material will be rendered.

Custom deferred lighting plugins can also be created to render the
StandardMaterial. The default deferred lighting plugin can be bypassed
with `DefaultPlugins.set(PBRDeferredLightingPlugin { bypass: true })`

---------

Co-authored-by: nickrart <nickolas.g.russell@gmail.com>
2023-10-12 22:10:38 +00:00
Edgar Geier cb0db07c5b Fix dependency of shadow mapping on the optional PrepassPlugin (#7878)
# Objective

Unfortunately, there are three issues with my changes introduced by #7784.

1.  The changes left some dead code. This is already taken care of here: #7875.
2. Disabling prepass causes failures because the shadow mapping relies on the `PrepassPlugin` now.
3. Custom materials use the `prepass.wgsl` shader, but this does not always define a fragment entry point.

This PR fixes 2. and 3. and resolves #7879.

## Solution

- Add a regression test with disabled prepass.
- Split `PrepassPlugin` into two plugins:
  - `PrepassPipelinePlugin` contains the part that is required for the shadow mapping to work and is unconditionally added.
  - `PrepassPlugin` now only adds the systems and resources required for the "real" prepasses.
- Add a noop fragment entry point to `prepass.wgsl`, used if `NORMAL_PASS` is not defined.


Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-03-03 15:08:54 +00:00