Commit graph

99 commits

Author SHA1 Message Date
Rob Parrett
1170b30785 Fix panic when using globals uniform in wasm builds (#6460)
# Objective

Fixes #5393 

## Solution

- Add padding to `GlobalsUniform` / `Globals` to make it 16-byte aligned.

Still not super clear on whether this is a `naga` thing or an `encase` thing or what. But now that we're offering `globals` up to users and #5393 is not just breaking an example, maybe we should do this sort of workaround?
2022-11-07 19:44:14 +00:00
Marco Buono
1bd3d85769 Take DirectionalLight's GlobalTransform into account when calculating shadow map volume (not just direction) (#6384)
# Objective

This PR fixes #5789, by enabling movable (and scalable) directional light shadow volumes.

## Solution

This PR changes `ExtractedDirectionalLight` to hold a copy of the `DirectionalLight` entity's `GlobalTransform`, instead of just a `direction` vector. This allows the shadow map volume (as defined by the light's `shadow_projection` field) to be transformed honoring translation _and_ scale transforms, and not just rotation.

It also augments the texel size calculation (used to determine the `shadow_normal_bias`) so that it now takes into account the upper bound of the x/y/z scale of the `GlobalTransform`.

This change makes the directional light extraction code more consistent with point and spot lights (that already use `transform`), and allows easily moving and scaling the shadow volume along with a player entity based on camera distance/angle, immediately enabling more real world use cases until we have a more sophisticated adaptive implementation, such as the one described in #3629.

**Note:** While it was previously possible to update the projection achieving a similar effect, depending on the light direction and distance to the origin, the fact that the shadow map camera was always positioned at the origin with a hardcoded `Vec3::Y` up value meant you would get sub-optimal or inconsistent/incorrect results.

---

## Changelog

### Changed

- `DirectionalLight` shadow volumes now honor translation and scale transforms

## Migration Guide

- If your directional lights were positioned at the origin and not scaled (the default, most common scenario) no changes are needed on your part; it just works as before;
- If you previously had a system for dynamically updating directional light shadow projections, you might now be able to simplify your code by updating the directional light entity's transform instead;
- In the unlikely scenario that a scene with directional lights that previously rendered shadows correctly has missing shadows, make sure your directional lights are positioned at (0, 0, 0) and are not scaled to a size that's too large or too small.
2022-11-04 20:12:26 +00:00
Robert Swain
fc56c686af bevy_pbr: Fix incorrect and unnecessary normal-mapping code (#5766)
# Objective

- Fixes #4019 
- Fix lighting of double-sided materials when using a negative scale
- The FlightHelmet.gltf model's hose uses a double-sided material. Loading the model with a uniform scale of -1.0, and comparing against Blender, it was identified that negating the world-space tangent, bitangent, and interpolated normal produces incorrect lighting. Discussion with Morten Mikkelsen clarified that this is both incorrect and unnecessary.

## Solution

- Remove the code that negates the T, B, and N vectors (the interpolated world-space tangent, calculated world-space bitangent, and interpolated world-space normal) when seeing the back face of a double-sided material with negative scale.
- Negate the world normal for a double-sided back face only when not using normal mapping

### Before, on `main`, flipping T, B, and N

<img width="932" alt="Screenshot 2022-08-22 at 15 11 53" src="https://user-images.githubusercontent.com/302146/185965366-f776ff2c-cfa1-46d1-9c84-fdcb399c273c.png">

### After, on this PR

<img width="932" alt="Screenshot 2022-08-22 at 15 12 11" src="https://user-images.githubusercontent.com/302146/185965420-8be493e2-3b1a-4188-bd13-fd6b17a76fe7.png">

### Double-sided material without normal maps

https://user-images.githubusercontent.com/302146/185988113-44a384e7-0b55-4946-9b99-20f8c803ab7e.mp4

---

## Changelog

- Fixed: Lighting of normal-mapped, double-sided materials applied to models with negative scale
- Fixed: Lighting and shadowing of back faces with no normal-mapping and a double-sided material

## Migration Guide

`prepare_normal` from the `bevy_pbr::pbr_functions` shader import has been reworked.

Before:
```rust
    pbr_input.world_normal = in.world_normal;

    pbr_input.N = prepare_normal(
        pbr_input.material.flags,
        in.world_normal,
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
        in.world_tangent,
#endif
#endif
        in.uv,
        in.is_front,
    );
```

After:
```rust
    pbr_input.world_normal = prepare_world_normal(
        in.world_normal,
        (material.flags & STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u,
        in.is_front,
    );

    pbr_input.N = apply_normal_mapping(
        pbr_input.material.flags,
        pbr_input.world_normal,
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
        in.world_tangent,
#endif
#endif
        in.uv,
    );
```
2022-11-03 20:37:32 +00:00
ira
262b3fc40d Fix mesh.wgsl error for meshes without normals (#6439)
# Objective
Split `model` assignment out of `#ifdef VERTEX_NORMALS`.
Remove outdated code/comments talking about required mesh attributes. 

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-11-03 12:38:47 +00:00
Kurt Kühnert
701ed8c59f Increase the MAX_DIRECTIONAL_LIGHTS from 1 to 10 (#6066)
# Objective

Currently we are limiting the amount of direction lights in a scene to one.

## Solution

Increase the amount of direction lights from 1 to 10. 
This still is not a perfect solution, but should unblock many use cases.
We could probably just store the directional lights similar to the point lights in an storage buffer, allowing for an variable amount of directional lights.


Co-authored-by: Kurt Kühnert <51823519+Ku95@users.noreply.github.com>
2022-11-03 07:09:51 +00:00
Griffin
5640ec855e Add FXAA postprocessing (#6393)
# Objective

- Add post processing passes for FXAA (Fast Approximate Anti-Aliasing)
- Add example comparing MSAA and FXAA

## Solution

When the FXAA plugin is added, passes for FXAA are inserted between the main pass and the tonemapping pass. Supports using either HDR or LDR output from the main pass.

---

## Changelog

- Add a new FXAANode that runs after the main pass when the FXAA plugin is added.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-11-02 06:51:28 +00:00
JoJoJet
336049da68 Remove outdated uses of single-tuple bundles (#6406)
# Objective

Bevy still has many instances of using single-tuples `(T,)` to create a bundle. Due to #2975, this is no longer necessary.

## Solution

Search for regex `\(.+\s*,\)`. This should have found every instance.
2022-10-29 18:15:28 +00:00
Jakob Hellermann
e71c4d2802 fix nightly clippy warnings (#6395)
# Objective

- fix new clippy lints before they get stable and break CI

## Solution

- run `clippy --fix` to auto-fix machine-applicable lints
- silence `clippy::should_implement_trait` for `fn HandleId::default<T: Asset>`

## Changes
- always prefer `format!("{inline}")` over `format!("{}", not_inline)`
- prefer `Box::default` (or `Box::<T>::default` if necessary) over `Box::new(T::default())`
2022-10-28 21:03:01 +00:00
Jakob Hellermann
838b318863 separate tonemapping and upscaling passes (#3425)
Attempt to make features like bloom https://github.com/bevyengine/bevy/pull/2876 easier to implement.

**This PR:**
- Moves the tonemapping from `pbr.wgsl` into a separate pass
- also add a separate upscaling pass after the tonemapping which writes to the swap chain (enables resolution-independant rendering and post-processing after tonemapping)
- adds a `hdr` bool to the camera which controls whether the pbr and sprite shaders render into a `Rgba16Float` texture

**Open questions:**
- ~should the 2d graph work the same as the 3d one?~ it is the same now
- ~The current solution is a bit inflexible because while you can add a post processing pass that writes to e.g. the `hdr_texture`, you can't write to a separate `user_postprocess_texture` while reading the `hdr_texture` and tell the tone mapping pass to read from the `user_postprocess_texture` instead. If the tonemapping and upscaling render graph nodes were to take in a `TextureView` instead of the view entity this would almost work, but the bind groups for their respective input textures are already created in the `Queue` render stage in the hardcoded order.~ solved by creating bind groups in render node

**New render graph:**

![render_graph](https://user-images.githubusercontent.com/22177966/147767249-57dd4229-cfab-4ec5-9bf3-dc76dccf8e8b.png)
<details>
<summary>Before</summary>

![render_graph_old](https://user-images.githubusercontent.com/22177966/147284579-c895fdbd-4028-41cf-914c-e1ffef60e44e.png)
</details>

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-10-26 20:13:59 +00:00
Torstein Grindvik
cb5e2d84be Use wgsl saturate (#6318)
# Objective

Use saturate wgsl function now implemented in naga (version 0.10.0). There is now no need for one in utils.wgsl.

naga's version allows usage for not only scalars but vectors as well.

## Solution

Remove the utils.wgsl saturate function.

## Changelog

Remove saturate function from utils.wgsl in favor of saturate in naga v0.10.0.
2022-10-22 08:37:51 +00:00
Charles
740ae9a37f remove mandatory mesh attributes (#6127)
# Objective

- It's possible to create a mesh without positions or normals, but currently bevy forces these attributes to be present on any mesh.

## Solution

- Don't assume these attributes are present and add a shader defs for each attributes
- I updated 2d and 3d meshes to use the same logic.

---

## Changelog

- Meshes don't require any attributes

# Notes
I didn't update the pbr.wgsl shader because I'm not sure how to handle it. It doesn't really make sense to use it without positions or normals.
2022-10-10 17:58:15 +00:00
VitalyR
f5322cd757 get proper texture format after the renderer is initialized, fix #3897 (#5413)
# Objective
There is no Srgb support on some GPU and display protocols with `winit` (for example, Nvidia's GPUs with Wayland). Thus `TextureFormat::bevy_default()` which returns `Rgba8UnormSrgb` or `Bgra8UnormSrgb` will cause panics on such platforms. This patch will resolve this problem. Fix https://github.com/bevyengine/bevy/issues/3897.

## Solution

Make `initialize_renderer` expose `wgpu::Adapter` and `first_available_texture_format`, use the `first_available_texture_format` by default.

## Changelog

* Fixed https://github.com/bevyengine/bevy/issues/3897.
2022-10-10 16:10:05 +00:00
robtfm
29098b7a11 fix spot dir nan bug (#6167)
# Objective

fix error with pbr shader's spotlight direction calculation when direction.y ~= 0

## Solution

in pbr_lighting.wgsl, clamp `1-x^2-z^2` to `>= 0` so that we can safely `sqrt` it
2022-10-05 12:00:07 +00:00
Charles
197392a2cd use alpha mask even when unlit (#6047)
# Objective

- Alpha mask was previously ignored when using an unlit material. 
- Fixes https://github.com/bevyengine/bevy/issues/4479

## Solution

- Extract the alpha discard to a separate function and use it when unlit is true

## Notes
I tried calling `alpha_discard()` before the `if` in pbr.wgsl, but I had errors related to having a `discard` at the beginning before doing the texture sampling. I'm not sure if there's a way to fix that instead of having the function being called in 2 places.
2022-09-28 05:54:11 +00:00
Charles
8073362039 add globals to mesh view bind group (#5409)
# Objective

- It's often really useful to have access to the time when writing shaders.

## Solution

- Add a UnifformBuffer in the mesh view bind group
- This buffer contains the time, delta time and a wrapping frame count

https://user-images.githubusercontent.com/8348954/180130314-97948c2a-2d11-423d-a9c4-fb5c9d1892c7.mp4

---

## Changelog

- Added a `GlobalsUniform` at position 9 of the mesh view bind group

## Notes

The implementation is currently split between bevy_render and bevy_pbr because I was basing my implementation on the `ViewPlugin`. I'm not sure if that's the right way to structure it.

I named this `globals` instead of just time because we could potentially add more things to it.

## References in other engines

- Godot: <https://docs.godotengine.org/en/stable/tutorials/shaders/shader_reference/canvas_item_shader.html#global-built-ins>
    - Global time since startup, in seconds, by default resets to 0 after 3600 seconds
    - Doesn't seem to have anything else
- Unreal: <https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Materials/ExpressionReference/Constant/>
    - Generic time value that updates every frame. Can be paused or scaled.
    - Frame count node, doesn't seem to be an equivalent for shaders: <https://docs.unrealengine.com/4.26/en-US/BlueprintAPI/Utilities/GetFrameCount/>
- Unity: <https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html>
    - time since startup in seconds. No mention of time wrapping. Stored as a `vec4(t/20, t, t*2, t*3)` where `t` is the value in seconds
    - Also has delta time, sin time and cos time
- ShaderToy: <https://www.shadertoy.com/howto>
    - iTime is the time since startup in seconds.
    - iFrameRate
    - iTimeDelta
    - iFrame frame counter

Co-authored-by: Charles <IceSentry@users.noreply.github.com>
2022-09-28 04:20:27 +00:00
Martin Lysell
180c94cc13 Fix some outdated file reference comments in bevy_pbr (#6111)
# Objective

Simple docs/comments only PR that just fixes some outdated file references left over from the render rewrite.

## Solution

- Change the references to point to the correct files
2022-09-27 17:51:12 +00:00
Carter Anderson
01aedc8431 Spawn now takes a Bundle (#6054)
# Objective

Now that we can consolidate Bundles and Components under a single insert (thanks to #2975 and #6039), almost 100% of world spawns now look like `world.spawn().insert((Some, Tuple, Here))`. Spawning an entity without any components is an extremely uncommon pattern, so it makes sense to give spawn the "first class" ergonomic api. This consolidated api should be made consistent across all spawn apis (such as World and Commands).

## Solution

All `spawn` apis (`World::spawn`, `Commands:;spawn`, `ChildBuilder::spawn`, and `WorldChildBuilder::spawn`) now accept a bundle as input:

```rust
// before:
commands
  .spawn()
  .insert((A, B, C));
world
  .spawn()
  .insert((A, B, C);

// after
commands.spawn((A, B, C));
world.spawn((A, B, C));
```

All existing instances of `spawn_bundle` have been deprecated in favor of the new `spawn` api. A new `spawn_empty` has been added, replacing the old `spawn` api.  

By allowing `world.spawn(some_bundle)` to replace `world.spawn().insert(some_bundle)`, this opened the door to removing the initial entity allocation in the "empty" archetype / table done in `spawn()` (and subsequent move to the actual archetype in `.insert(some_bundle)`).

This improves spawn performance by over 10%:
![image](https://user-images.githubusercontent.com/2694663/191627587-4ab2f949-4ccd-4231-80eb-80dd4d9ad6b9.png)

To take this measurement, I added a new `world_spawn` benchmark.

Unfortunately, optimizing `Commands::spawn` is slightly less trivial, as Commands expose the Entity id of spawned entities prior to actually spawning. Doing the optimization would (naively) require assurances that the `spawn(some_bundle)` command is applied before all other commands involving the entity (which would not necessarily be true, if memory serves). Optimizing `Commands::spawn` this way does feel possible, but it will require careful thought (and maybe some additional checks), which deserves its own PR. For now, it has the same performance characteristics of the current `Commands::spawn_bundle` on main.

**Note that 99% of this PR is simple renames and refactors. The only code that needs careful scrutiny is the new `World::spawn()` impl, which is relatively straightforward, but it has some new unsafe code (which re-uses battle tested BundlerSpawner code path).** 

---

## Changelog

- All `spawn` apis (`World::spawn`, `Commands:;spawn`, `ChildBuilder::spawn`, and `WorldChildBuilder::spawn`) now accept a bundle as input
- All instances of `spawn_bundle` have been deprecated in favor of the new `spawn` api
- World and Commands now have `spawn_empty()`, which is equivalent to the old `spawn()` behavior.  

## Migration Guide

```rust
// Old (0.8):
commands
  .spawn()
  .insert_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));

// Old (0.8):
commands.spawn_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));

// Old (0.8):
let entity = commands.spawn().id();
// New (0.9)
let entity = commands.spawn_empty().id();

// Old (0.8)
let entity = world.spawn().id();
// New (0.9)
let entity = world.spawn_empty();
```
2022-09-23 19:55:54 +00:00
Carter Anderson
cd15f0f5be Accept Bundles for insert and remove. Deprecate insert/remove_bundle (#6039)
# Objective

Take advantage of the "impl Bundle for Component" changes in #2975 / add the follow up changes discussed there.

## Solution

- Change `insert` and `remove` to accept a Bundle instead of a Component (for both Commands and World)
- Deprecate `insert_bundle`, `remove_bundle`, and `remove_bundle_intersection`
- Add `remove_intersection`

---

## Changelog

- Change `insert` and `remove` now accept a Bundle instead of a Component (for both Commands and World)
- `insert_bundle` and `remove_bundle` are deprecated
 

## Migration Guide

Replace `insert_bundle` with `insert`:
```rust
// Old (0.8)
commands.spawn().insert_bundle(SomeBundle::default());
// New (0.9)
commands.spawn().insert(SomeBundle::default());
```

Replace `remove_bundle` with `remove`:
```rust
// Old (0.8)
commands.entity(some_entity).remove_bundle::<SomeBundle>();
// New (0.9)
commands.entity(some_entity).remove::<SomeBundle>();
```

Replace `remove_bundle_intersection` with `remove_intersection`:
```rust
// Old (0.8)
world.entity_mut(some_entity).remove_bundle_intersection::<SomeBundle>();
// New (0.9)
world.entity_mut(some_entity).remove_intersection::<SomeBundle>();
```

Consider consolidating as many operations as possible to improve ergonomics and cut down on archetype moves:
```rust
// Old (0.8)
commands.spawn()
  .insert_bundle(SomeBundle::default())
  .insert(SomeComponent);

// New (0.9) - Option 1
commands.spawn().insert((
  SomeBundle::default(),
  SomeComponent,
))

// New (0.9) - Option 2
commands.spawn_bundle((
  SomeBundle::default(),
  SomeComponent,
))
```

## Next Steps

Consider changing `spawn` to accept a bundle and deprecate `spawn_bundle`.
2022-09-21 21:47:53 +00:00
ira
2b80a3f279 Implement IntoIterator for &Extract<P> (#6025)
# Objective

Implement `IntoIterator` for `&Extract<P>` if the system parameter it wraps implements `IntoIterator`.

Enables the use of `IntoIterator` with an extracted query.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-09-20 00:29:10 +00:00
robtfm
503c2a9677 adjust cluster index for viewport origin (#5947)
# Objective

fixes #5946

## Solution

adjust cluster index calculation for viewport origin.

from reading point 2 of the rasterization algorithm description in https://gpuweb.github.io/gpuweb/#rasterization, it looks like framebuffer space (and so @bulitin(position)) is not meant to be adjusted for viewport origin, so we need to subtract that to get the right cluster index.

- add viewport origin to rust `ExtractedView` and wgsl `View` structs
- subtract from frag coord for cluster index calculation
2022-09-15 21:58:14 +00:00
ira
b42f426fc3 Add associated constant IDENTITY to Transform and friends. (#5340)
# Objective
Since `identity` is a const fn that takes no arguments it seems logical to make it an associated constant.
This is also more in line with types from glam (eg. `Quat::IDENTITY`).

## Migration Guide

The method `identity()` on `Transform`, `GlobalTransform` and `TransformBundle` has been deprecated.
Use the associated constant `IDENTITY` instead.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-08-30 22:10:24 +00:00
Lain-dono
24e5e10cd4 Use 3 bits of PipelineKey to store MSAA sample count (#5826)
Sample count always power of two. Thus, it is enough to store `log2(sample_count)`.
This can be implemented using [u32::trailing_zeros](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.trailing_zeros). Then we can restore sample count with the `1 << stored`.
You get 3 bits instead of 6 and up to 128x MSAA. This is more than is supported by any common hardware.

Full table of possible variations:

```
    original MSAA sample count      stored    loaded
* 00000000000000000000000000000000 -> 000 -> 00000001  1
  00000000000000000000000000000001 -> 000 -> 00000001  1
  00000000000000000000000000000010 -> 001 -> 00000010  2
  00000000000000000000000000000100 -> 010 -> 00000100  4
  00000000000000000000000000001000 -> 011 -> 00001000  8
  00000000000000000000000000010000 -> 100 -> 00010000  16
  00000000000000000000000000100000 -> 101 -> 00100000  32
  00000000000000000000000001000000 -> 110 -> 01000000  64
  00000000000000000000000010000000 -> 111 -> 10000000  128
* 00000000000000000000000100000000 -> 000 -> 00000001  256
* 00000000000000000000001000000000 -> 001 -> 00000010  512
* 00000000000000000000010000000000 -> 010 -> 00000100  1024
* 00000000000000000000100000000000 -> 011 -> 00001000  2048
* 00000000000000000001000000000000 -> 100 -> 00010000  4096
* 00000000000000000010000000000000 -> 101 -> 00100000  8192
* 00000000000000000100000000000000 -> 110 -> 01000000  16384
* 00000000000000001000000000000000 -> 111 -> 10000000  32768
* 00000000000000010000000000000000 -> 000 -> 00000001  65536
* 00000000000000100000000000000000 -> 001 -> 00000010  131072
* 00000000000001000000000000000000 -> 010 -> 00000100  262144
* 00000000000010000000000000000000 -> 011 -> 00001000  524288
* 00000000000100000000000000000000 -> 100 -> 00010000  1048576
* 00000000001000000000000000000000 -> 101 -> 00100000  2097152
* 00000000010000000000000000000000 -> 110 -> 01000000  4194304
* 00000000100000000000000000000000 -> 111 -> 10000000  8388608
* 00000001000000000000000000000000 -> 000 -> 00000001  16777216
* 00000010000000000000000000000000 -> 001 -> 00000010  33554432
* 00000100000000000000000000000000 -> 010 -> 00000100  67108864
* 00001000000000000000000000000000 -> 011 -> 00001000  134217728
* 00010000000000000000000000000000 -> 100 -> 00010000  268435456
* 00100000000000000000000000000000 -> 101 -> 00100000  536870912
* 01000000000000000000000000000000 -> 110 -> 01000000  1073741824
* 10000000000000000000000000000000 -> 111 -> 10000000  2147483648
```
2022-08-30 03:00:39 +00:00
Robert Swain
681c9c6dc8 bevy_pbr: Fix tangent and normal normalization (#5666)
# Objective

- Morten Mikkelsen clarified that the world normal and tangent must be normalized in the vertex stage and the interpolated values must not be normalized in the fragment stage. This is in order to match the mikktspace approach exactly.
- Fixes #5514 by ensuring the tangent basis matrix (TBN) is orthonormal

## Solution

- Normalize the world normal in the vertex stage and not the fragment stage
- Normalize the world tangent xyz in the vertex stage
- Take into account the sign of the determinant of the local to world matrix when calculating the bitangent

---

## Changelog

- Fixed - scaling a model that uses normal mapping now has correct lighting again
2022-08-18 21:54:40 +00:00
ira
992681b59b Make Resource trait opt-in, requiring #[derive(Resource)] V2 (#5577)
*This PR description is an edited copy of #5007, written by @alice-i-cecile.*
# Objective
Follow-up to https://github.com/bevyengine/bevy/pull/2254. The `Resource` trait currently has a blanket implementation for all types that meet its bounds.

While ergonomic, this results in several drawbacks:

* it is possible to make confusing, silent mistakes such as inserting a function pointer (Foo) rather than a value (Foo::Bar) as a resource
* it is challenging to discover if a type is intended to be used as a resource
* we cannot later add customization options (see the [RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/27-derive-component.md) for the equivalent choice for Component).
* dependencies can use the same Rust type as a resource in invisibly conflicting ways
* raw Rust types used as resources cannot preserve privacy appropriately, as anyone able to access that type can read and write to internal values
* we cannot capture a definitive list of possible resources to display to users in an editor
## Notes to reviewers
 * Review this commit-by-commit; there's effectively no back-tracking and there's a lot of churn in some of these commits.
   *ira: My commits are not as well organized :')*
 * I've relaxed the bound on Local to Send + Sync + 'static: I don't think these concerns apply there, so this can keep things simple. Storing e.g. a u32 in a Local is fine, because there's a variable name attached explaining what it does.
 * I think this is a bad place for the Resource trait to live, but I've left it in place to make reviewing easier. IMO that's best tackled with https://github.com/bevyengine/bevy/issues/4981.

## Changelog
`Resource` is no longer automatically implemented for all matching types. Instead, use the new `#[derive(Resource)]` macro.

## Migration Guide
Add `#[derive(Resource)]` to all types you are using as a resource.

If you are using a third party type as a resource, wrap it in a tuple struct to bypass orphan rules. Consider deriving `Deref` and `DerefMut` to improve ergonomics.

`ClearColor` no longer implements `Component`. Using `ClearColor` as a component in 0.8 did nothing.
Use the `ClearColorConfig` in the `Camera3d` and `Camera2d` components instead.


Co-authored-by: Alice <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: devil-ira <justthecooldude@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-08-08 21:36:35 +00:00
robtfm
6a1ba9c456 Spotlight shadow bugfix (#5451)
# Objective

fix an error in shadow map indexing that occurs when point lights without shadows are used in conjunction with spotlights with shadows

## Solution

calculate point_light_count correctly
2022-07-25 16:24:54 +00:00
Dusty DeWeese
9f8bdeeeb9 Use Affine3A for GlobalTransform to allow any affine transformation (#4379)
# Objective

- Add capability to use `Affine3A`s for some `GlobalTransform`s. This allows affine transformations that are not possible using a single `Transform` such as shear and non-uniform scaling along an arbitrary axis.
- Related to #1755 and #2026

## Solution

- `GlobalTransform` becomes an enum wrapping either a `Transform` or an `Affine3A`.
- The API of `GlobalTransform` is minimized to avoid inefficiency, and to make it clear that operations should be performed using the underlying data types.
- using `GlobalTransform::Affine3A` disables transform propagation, because the main use is for cases that `Transform`s cannot support.

---

## Changelog

- `GlobalTransform`s can optionally support any affine transformation using an `Affine3A`.


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-16 00:51:12 +00:00
Carter Anderson
40d4992401 Visibilty Inheritance, universal ComputedVisibility and RenderLayers support (#5310)
# Objective

Fixes #4907. Fixes #838. Fixes #5089.
Supersedes #5146. Supersedes #2087. Supersedes #865. Supersedes #5114

Visibility is currently entirely local. Set a parent entity to be invisible, and the children are still visible. This makes it hard for users to hide entire hierarchies of entities.

Additionally, the semantics of `Visibility` vs `ComputedVisibility` are inconsistent across entity types. 3D meshes use `ComputedVisibility` as the "definitive" visibility component, with `Visibility` being just one data source. Sprites just use `Visibility`, which means they can't feed off of `ComputedVisibility` data, such as culling information, RenderLayers, and (added in this pr) visibility inheritance information.

## Solution

Splits `ComputedVisibilty::is_visible` into `ComputedVisibilty::is_visible_in_view` and `ComputedVisibilty::is_visible_in_hierarchy`. For each visible entity, `is_visible_in_hierarchy` is computed by propagating visibility down the hierarchy. The `ComputedVisibility::is_visible()` function combines these two booleans for the canonical "is this entity visible" function.

Additionally, all entities that have `Visibility` now also have `ComputedVisibility`.  Sprites, Lights, and UI entities now use `ComputedVisibility` when appropriate.

This means that in addition to visibility inheritance, everything using Visibility now also supports RenderLayers. Notably, Sprites (and other 2d objects) now support `RenderLayers` and work properly across multiple views.

Also note that this does increase the amount of work done per sprite. Bevymark with 100,000 sprites on `main` runs in `0.017612` seconds and this runs in `0.01902`. That is certainly a gap, but I believe the api consistency and extra functionality this buys us is worth it. See [this thread](https://github.com/bevyengine/bevy/pull/5146#issuecomment-1182783452) for more info. Note that #5146 in combination with #5114 _are_ a viable alternative to this PR and _would_ perform better, but that comes at the cost of api inconsistencies and doing visibility calculations in the "wrong" place. The current visibility system does have potential for performance improvements. I would prefer to evolve that one system as a whole rather than doing custom hacks / different behaviors for each feature slice.

Here is a "split screen" example where the left camera uses RenderLayers to filter out the blue sprite.

![image](https://user-images.githubusercontent.com/2694663/178814868-2e9a2173-bf8c-4c79-8815-633899d492c3.png)


Note that this builds directly on #5146 and that @james7132 deserves the credit for the baseline visibility inheritance work. This pr moves the inherited visibility field into `ComputedVisibility`, then does the additional work of porting everything to `ComputedVisibility`. See my [comments here](https://github.com/bevyengine/bevy/pull/5146#issuecomment-1182783452) for rationale. 

## Follow up work

* Now that lights use ComputedVisibility, VisibleEntities now includes "visible lights" in the entity list. Functionally not a problem as we use queries to filter the list down in the desired context. But we should consider splitting this out into a separate`VisibleLights` collection for both clarity and performance reasons. And _maybe_ even consider scoping `VisibleEntities` down to `VisibleMeshes`?.
* Investigate alternative sprite rendering impls (in combination with visibility system tweaks) that avoid re-generating a per-view fixedbitset of visible entities every frame, then checking each ExtractedEntity. This is where most of the performance overhead lives. Ex: we could generate ExtractedEntities per-view using the VisibleEntities list, avoiding the need for the bitset.
* Should ComputedVisibility use bitflags under the hood? This would cut down on the size of the component, potentially speed up the `is_visible()` function, and allow us to cheaply expand ComputedVisibility with more data (ex: split out local visibility and parent visibility, add more culling classes, etc).
---

## Changelog

* ComputedVisibility now takes hierarchy visibility into account.
* 2D, UI and Light entities now use the ComputedVisibility component.

## Migration Guide

If you were previously reading `Visibility::is_visible` as the "actual visibility" for sprites or lights, use `ComputedVisibilty::is_visible()` instead:

```rust
// before (0.7)
fn system(query: Query<&Visibility>) {
  for visibility in query.iter() {
    if visibility.is_visible {
       log!("found visible entity");
    }
  }
}

// after (0.8)
fn system(query: Query<&ComputedVisibility>) {
  for visibility in query.iter() {
    if visibility.is_visible() {
       log!("found visible entity");
    }
  }
}
``` 


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-15 23:24:42 +00:00
François
814f8d1635 update wgpu to 0.13 (#5168)
# Objective

- Update wgpu to 0.13
- ~~Wait, is wgpu 0.13 released? No, but I had most of the changes already ready since playing with webgpu~~ well it has been released now
- Also update parking_lot to 0.12 and naga to 0.9

## Solution

- Update syntax for wgsl shaders https://github.com/gfx-rs/wgpu/blob/master/CHANGELOG.md#wgsl-syntax
- Add a few options, remove some references: https://github.com/gfx-rs/wgpu/blob/master/CHANGELOG.md#other-breaking-changes
- fragment inputs should now exactly match vertex outputs for locations, so I added exports for those to be able to reuse them https://github.com/gfx-rs/wgpu/pull/2704
2022-07-14 21:17:16 +00:00
CGMossa
93a131661d Very minor doc formatting changes (#5287)
# Objective

- Added a bunch of backticks to things that should have them, like equations, abstract variable names,
- Changed all small x, y, and z to capitals X, Y, Z.

This might be more annoying than helpful; Feel free to refuse this PR.
2022-07-12 13:06:16 +00:00
ira
4847f7e3ad Update codebase to use IntoIterator where possible. (#5269)
Remove unnecessary calls to `iter()`/`iter_mut()`.
Mainly updates the use of queries in our code, docs, and examples.

```rust
// From
for _ in list.iter() {
for _ in list.iter_mut() {

// To
for _ in &list {
for _ in &mut list {
```

We already enable the pedantic lint [clippy::explicit_iter_loop](https://rust-lang.github.io/rust-clippy/stable/) inside of Bevy. However, this only warns for a few known types from the standard library.

## Note for reviewers
As you can see the additions and deletions are exactly equal.
Maybe give it a quick skim to check I didn't sneak in a crypto miner, but you don't have to torture yourself by reading every line.
I already experienced enough pain making this PR :) 


Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-07-11 15:28:50 +00:00
Daniel McNab
7b2cf98896 Make RenderStage::Extract run on the render world (#4402)
# Objective

- Currently, the `Extract` `RenderStage` is executed on the main world, with the render world available as a resource.
- However, when needing access to resources in the render world (e.g. to mutate them), the only way to do so was to get exclusive access to the whole `RenderWorld` resource.
- This meant that effectively only one extract which wrote to resources could run at a time.
- We didn't previously make `Extract`ing writing to the world a non-happy path, even though we want to discourage that.

## Solution

- Move the extract stage to run on the render world.
- Add the main world as a `MainWorld` resource.
- Add an `Extract` `SystemParam` as a convenience to access a (read only) `SystemParam` in the main world during `Extract`.

## Future work

It should be possible to avoid needing to use `get_or_spawn` for the render commands, since now the `Commands`' `Entities` matches up with the world being executed on.
We need to determine how this interacts with https://github.com/bevyengine/bevy/pull/3519
It's theoretically possible to remove the need for the `value` method on `Extract`. However, that requires slightly changing the `SystemParam` interface, which would make it more complicated. That would probably mess up the `SystemState` api too.

## Todo
I still need to add doc comments to `Extract`.

---

## Changelog

### Changed
- The `Extract` `RenderStage` now runs on the render world (instead of the main world as before).
   You must use the `Extract` `SystemParam` to access the main world during the extract phase.
   Resources on the render world can now be accessed using `ResMut` during extract.

### Removed
- `Commands::spawn_and_forget`. Use `Commands::get_or_spawn(e).insert_bundle(bundle)` instead

## Migration Guide

The `Extract` `RenderStage` now runs on the render world (instead of the main world as before).
You must use the `Extract` `SystemParam` to access the main world during the extract phase. `Extract` takes a single type parameter, which is any system parameter (such as `Res`, `Query` etc.). It will extract this from the main world, and returns the result of this extraction when `value` is called on it.

For example, if previously your extract system looked like:
```rust
fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) {
    for cloud in clouds.iter() {
        commands.get_or_spawn(cloud).insert(Cloud);
    }
}
```
the new version would be:
```rust
fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) {
    for cloud in clouds.value().iter() {
        commands.get_or_spawn(cloud).insert(Cloud);
    }
}
```
The diff is:
```diff
--- a/src/clouds.rs
+++ b/src/clouds.rs
@@ -1,5 +1,5 @@
-fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) {
-    for cloud in clouds.iter() {
+fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) {
+    for cloud in clouds.value().iter() {
         commands.get_or_spawn(cloud).insert(Cloud);
     }
 }
```
You can now also access resources from the render world using the normal system parameters during `Extract`:
```rust
fn extract_assets(mut render_assets: ResMut<MyAssets>, source_assets: Extract<Res<MyAssets>>) {
     *render_assets = source_assets.clone();
}
```
Please note that all existing extract systems need to be updated to match this new style; even if they currently compile they will not run as expected. A warning will be emitted on a best-effort basis if this is not met.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-08 23:56:33 +00:00
Robin KAY
3c51ad2764 Allow rendering meshes without UV coordinate data. (#5222)
# Objective

Bevy requires meshes to include UV coordinates, even if the material does not use any textures, and will fail with an error `ERROR bevy_pbr::material: Mesh is missing requested attribute: Vertex_Uv (MeshVertexAttributeId(2), pipeline type: Some("bevy_pbr::material::MaterialPipeline<bevy_pbr::pbr_material::StandardMaterial>"))` otherwise. The objective of this PR is to permit this.

## Solution

This PR follows the design of #4528, which added support for per-vertex colours. It adds a shader define called VERTEX_UVS which indicates the presence of UV coordinates to the shader.
2022-07-08 20:55:08 +00:00
robtfm
132950cd55 Spotlights (#4715)
# Objective

add spotlight support

## Solution / Changelog

- add spotlight angles (inner, outer) to ``PointLight`` struct. emitted light is linearly attenuated from 100% to 0% as angle tends from inner to outer. Direction is taken from the existing transform rotation.
- add spotlight direction (vec3) and angles (f32,f32) to ``GpuPointLight`` struct (60 bytes -> 80 bytes) in ``pbr/render/lights.rs`` and ``mesh_view_bind_group.wgsl``
- reduce no-buffer-support max point light count to 204 due to above
- use spotlight data to attenuate light in ``pbr.wgsl``
- do additional cluster culling on spotlights to minimise cost in ``assign_lights_to_clusters``
- changed one of the lights in the lighting demo to a spotlight
- also added a ``spotlight`` demo - probably not justified but so reviewers can see it more easily

## notes

increasing the size of the GpuPointLight struct on my machine reduces the FPS of ``many_lights -- sphere`` from ~150fps to 140fps. 

i thought this was a reasonable tradeoff, and felt better than handling spotlights separately which is possible but would mean introducing a new bind group, refactoring light-assignment code and adding new spotlight-specific code in pbr.wgsl. the FPS impact for smaller numbers of lights should be very small.

the cluster culling strategy reintroduces the cluster aabb code which was recently removed... sorry. the aabb is used to get a cluster bounding sphere, which can then be tested fairly efficiently using the strategy described at the end of https://bartwronski.com/2017/04/13/cull-that-cone/. this works well with roughly cubic clusters (where the cluster z size is close to the same as x/y size), less well for other cases like single Z slice / tiled forward rendering. In the worst case we will end up just keeping the culling of the equivalent point light.

Co-authored-by: François <mockersf@gmail.com>
2022-07-08 19:57:43 +00:00
Elijah
5d3fa5e77b Add inverse_projection and inverse_view_proj fields to shader view uniform (#5119)
# Objective

Transform screen-space coordinates into world space in shaders. (My use case is for generating rays for ray tracing with the same perspective as the 3d camera).

## Solution

Add `inverse_projection` and `inverse_view_proj` fields to shader view uniform

---

## Changelog

### Added
`inverse_projection` and `inverse_view_proj` fields to shader view uniform

## Note

It'd probably be good to double-check that I did the matrix multiplication in the right order for `inverse_proj_view`. Thanks!
2022-07-04 21:04:16 +08:00
Nicola Papale
288765930f Rework extract_meshes (#4240)
* Cleanup redundant code
* Use a type alias to make sure the `caster_query` and
  `not_caster_query` really do the same thing and access the same things

**Objective**

Cleanup code that would otherwise be difficult to understand

**Solution**

* `extract_meshes` had two for loops which are functionally identical,
  just copy-pasted code. I extracted the common code between the two
  and put them into an anonymous function.
* I flattened the tuple literal for the bundle batch, it looks much
  less nested and the code is much more readable as a result.
* The parameters of `extract_meshes` were also very daunting, but they
  turned out to be the same query repeated twice. I extracted the query
  into a type alias.

EDIT: I reworked the PR to **not do anything breaking**, and keep the old allocation behavior. Removing the memorized length was clearly a performance loss, so I kept it.
2022-07-04 12:44:23 +00:00
CGMossa
33f9b3940d Updated glam to 0.21. (#5142)
Removed `const_vec2`/`const_vec3`
and replaced with equivalent `.from_array`.

# Objective

Fixes #5112 

## Solution

- `encase` needs to update to `glam` as well. See teoxoy/encase#4 on progress on that. 
- `hexasphere` also needs to be updated, see OptimisticPeach/hexasphere#12.
2022-07-03 19:55:33 +00:00
SarthakSingh31
cdbabb7053 Removed world cell from places where split multable access is not needed (#5167)
Fixes #5109.
2022-07-01 17:03:32 +00:00
DGriffin91
072f2e17d3 Move texture sample out of branch in prepare_normal (#5129)
# Objective

This fixes https://github.com/bevyengine/bevy/issues/5127

## Solution

- Moved texture sample out of branch in `prepare_normal()`.


Co-authored-by: DGriffin91 <github@dgdigital.net>
2022-06-29 02:48:46 +00:00
Robert Swain
84991d34f3 Array texture example (#5077)
# Objective

- Make the reusable PBR shading functionality a little more reusable
  - Add constructor functions for `StandardMaterial` and `PbrInput` structs to populate them with default values
  - Document unclear `PbrInput` members
- Demonstrate how to reuse the bevy PBR shading functionality
- The final important piece from #3969 as the initial shot at making the PBR shader code reusable in custom materials

## Solution

- Add back and rework the 'old' `array_texture` example from pre-0.6.
- Create a custom shader material
  - Use a single array texture binding and sampler for the material bind group
  - Use a shader that calls `pbr()` from the `bevy_pbr::pbr_functions` import
- Spawn a row of cubes using the custom material
- In the shader, select the array texture layer to sample by using the world position x coordinate modulo the number of array texture layers

<img width="1392" alt="Screenshot 2022-06-23 at 12 28 05" src="https://user-images.githubusercontent.com/302146/175278593-2296f519-f577-4ece-81c0-d842283784a1.png">

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-06-28 00:58:50 +00:00
研究社交
92eec47b99 Separate PBR and tone mapping into 2 functions (#5078)
# Objective

- Allow custom shaders to reuse the HDR results of PBR.

## Solution

- Separate `pbr()` and `tone_mapping()` into 2 functions in `pbr_functions.wgsl`.
2022-06-26 00:00:23 +00:00
Edward Vear
5a3e77716a Fix skinned mesh normal handling in mesh shader (#5095)
# Objective

Update pbr mesh shader to use correct normals for skinned meshes.

## Solution

Only use `mesh_normal_local_to_world` for normals if `SKINNED` is not defined.
2022-06-25 09:54:33 +00:00
James Liu
7e6dd3f03e Allow unbatched render phases to use unstable sorts (#5049)
# Objective

Partially addresses #4291.

Speed up the sort phase for unbatched render phases.

## Solution
Split out one of the optimizations in #4899 and allow implementors of `PhaseItem` to change what kind of sort is used when sorting the items in the phase. This currently includes Stable, Unstable, and Unsorted. Each of these corresponds to `Vec::sort_by_key`, `Vec::sort_unstable_by_key`, and no sorting at all. The default is `Unstable`. The last one can be used as a default if users introduce a preliminary depth prepass.

## Performance
This will not impact the performance of any batched phases, as it is still using a stable sort. 2D's only phase is unchanged. All 3D phases are unbatched currently, and will benefit from this change.

On `many_cubes`, where the primary phase is opaque, this change sees a speed up from 907.02us -> 477.62us, a 47.35% reduction.

![image](https://user-images.githubusercontent.com/3137680/174471253-22424874-30d5-4db5-b5b4-65fb2c612a9c.png)

## Future Work
There were prior discussions to add support for faster radix sorts in #4291, which in theory should be a `O(n)` instead of a `O(nlog(n))` time. [`voracious`](https://crates.io/crates/voracious_radix_sort) has been proposed, but it seems to be optimize for use cases with more than 30,000 items, which may be atypical for most systems.

Another optimization included in #4899 is to reduce the size of a few of the IDs commonly used in `PhaseItem` implementations to shrink the types to make swapping/sorting faster. Both `CachedPipelineId` and `DrawFunctionId` could be reduced to `u32` instead of `usize`.

Ideally, this should automatically change to use stable sorts when `BatchedPhaseItem` is implemented on the same phase item type, but this requires specialization, which may not land in stable Rust for a short while.

---

## Changelog
Added: `PhaseItem::sort`

## Migration Guide
RenderPhases now default to a unstable sort (via `slice::sort_unstable_by_key`). This can typically improve sort phase performance, but may produce incorrect batching results when implementing `BatchedPhaseItem`. To revert to the older stable sort, manually implement `PhaseItem::sort` to implement a stable sort (i.e. via `slice::sort_by_key`).

Co-authored-by: Federico Rinaldi <gisquerin@gmail.com>
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: colepoirier <colepoirier@gmail.com>
2022-06-23 10:52:49 +00:00
Robert Swain
114d169dce Callable PBR functions (#4939)
# Objective

- Builds on top of #4938 
- Make clustered-forward PBR lighting/shadows functionality callable
- See #3969 for details

## Solution

- Add `PbrInput` struct type containing a `StandardMaterial`, occlusion, world_position, world_normal, and frag_coord
- Split functionality to calculate the unit view vector, and normal-mapped normal into `bevy_pbr::pbr_functions`
- Split high-level shading flow into `pbr(in: PbrInput, N: vec3<f32>, V: vec3<f32>, is_orthographic: bool)` function in `bevy_pbr::pbr_functions`
- Rework `pbr.wgsl` fragment stage entry point to make use of the new functions
- This has been benchmarked on an M1 Max using `many_cubes -- sphere`. `main` had a median frame time of 15.88ms, this PR 15.99ms, which is a 0.69% frame time increase, which is within noise in my opinion.

---

## Changelog

- Added: PBR shading code is now callable. Import `bevy_pbr::pbr_functions` and its dependencies, create a `PbrInput`, calculate the unit view and normal-mapped normal vectors and whether the projection is orthographic, and call `pbr()`!
2022-06-21 20:50:06 +00:00
François
8b27124a80 WGSL: use correct syntax for matrix access (#5039)
# Objective

- `.x` is not the correct syntax to access a column in a matrix in WGSL: https://www.w3.org/TR/WGSL/#matrix-access-expr
- naga accepts it and translates it correctly, but it's not valid when shaders are kept as is and used directly in WGSL

## Solution

- Use the correct syntax
2022-06-18 07:41:54 +00:00
Robert Swain
c6222f1acc Separate out PBR lighting, shadows, clustered forward, and utils from pbr.wgsl (#4938)
# Objective

- Builds on top of #4901 
- Separate out PBR lighting, shadows, clustered forward, and utils from `pbr.wgsl` as part of making the PBR code more reusable and extensible.
- See #3969 for details.

## Solution

- Add `bevy_pbr::utils`, `bevy_pbr::clustered_forward`, `bevy_pbr::lighting`, `bevy_pbr::shadows` shader imports exposing many shader functions for external use
- Split `PI`, `saturate()`, `hsv2rgb()`, and `random1D()` into `bevy_pbr::utils`
- Split clustered-forward-specific functions into `bevy_pbr::clustered_forward`, including moving the debug visualization code into a `cluster_debug_visualization()` function in that import
- Split PBR lighting functions into `bevy_pbr::lighting`
- Split shadow functions into `bevy_pbr::shadows`

---

## Changelog

- Added: `bevy_pbr::utils`, `bevy_pbr::clustered_forward`, `bevy_pbr::lighting`, `bevy_pbr::shadows` shader imports exposing many shader functions for external use
  - Split `PI`, `saturate()`, `hsv2rgb()`, and `random1D()` into `bevy_pbr::utils`
  - Split clustered-forward-specific functions into `bevy_pbr::clustered_forward`, including moving the debug visualization code into a `cluster_debug_visualization()` function in that import
  - Split PBR lighting functions into `bevy_pbr::lighting`
  - Split shadow functions into `bevy_pbr::shadows`
2022-06-14 00:58:30 +00:00
Robert Swain
b333386271 Add reusable shader functions for transforming position/normal/tangent (#4901)
# Objective

- Add reusable shader functions for transforming positions / normals / tangents between local and world / clip space for 2D and 3D so that they are done in a simple and correct way
- The next step in #3969 so check there for more details.

## Solution

- Add `bevy_pbr::mesh_functions` and `bevy_sprite::mesh2d_functions` shader imports
  - These contain `mesh_` and `mesh2d_` versions of the following functions:
    - `mesh_position_local_to_world`
    - `mesh_position_world_to_clip`
    - `mesh_position_local_to_clip`
    - `mesh_normal_local_to_world`
    - `mesh_tangent_local_to_world`
- Use them everywhere where it is appropriate
  - Notably not in the sprite and UI shaders where `mesh2d_position_world_to_clip` could have been used, but including all the functions depends on the mesh binding so I chose to not use the function there
- NOTE: The `mesh_` and `mesh2d_` functions are currently identical. However, if I had defined only `bevy_pbr::mesh_functions` and used that in bevy_sprite, then bevy_sprite would have a runtime dependency on bevy_pbr, which seems undesirable. I also expect that when we have a proper 2D rendering API, these functions will diverge between 2D and 3D.

---

## Changelog

- Added: `bevy_pbr::mesh_functions` and `bevy_sprite::mesh2d_functions` shader imports containing `mesh_` and `mesh2d_` versions of the following functions:
  - `mesh_position_local_to_world`
  - `mesh_position_world_to_clip`
  - `mesh_position_local_to_clip`
  - `mesh_normal_local_to_world`
  - `mesh_tangent_local_to_world`

## Migration Guide

- The `skin_tangents` function from the `bevy_pbr::skinning` shader import has been replaced with the `mesh_tangent_local_to_world` function from the `bevy_pbr::mesh_functions` shader import
2022-06-14 00:32:33 +00:00
François
f969c62f7b Fix wasm examples (#4967)
# Objective

Fix #4958 

There was 4 issues:

- this is not true in WASM and on macOS: f28b921209/examples/3d/split_screen.rs (L90)
  - ~~I made sure the system was running at least once~~
  - I'm sending the event on window creation
- in webgl, setting a viewport has impacts on other render passes
  - only in webgl and when there is a custom viewport, I added a render pass without a custom viewport
- shaderdef NO_ARRAY_TEXTURES_SUPPORT was not used by the 2d pipeline
  - webgl feature was used but not declared in bevy_sprite, I added it to the Cargo.toml
- shaderdef NO_STORAGE_BUFFERS_SUPPORT was not used by the 2d pipeline
  - I added it based on the BufferBindingType

The last commit changes the two last fixes to add the shaderdefs in the shader cache directly instead of needing to do it in each pipeline

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-06-11 20:10:13 +00:00
Aevyrie
772d15238c Change default Image FilterMode to Linear (#4465)
# Objective

- Closes #4464 

## Solution

- Specify default mag and min filter types for `Image` instead of using `wgpu`'s defaults.

---

## Changelog

### Changed

- Default `Image` filtering changed from `Nearest` to `Linear`.


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-06-11 09:13:37 +00:00
François
193998b5d4 add NO_STORAGE_BUFFERS_SUPPORT shaderdef when needed (#4949)
# Objective

- fix #4946 
- fix running 3d in wasm

## Solution

- since #4867, the imports are splitter differently, and this shader def was not always set correctly depending on the shader used
- add it when needed
2022-06-06 20:00:30 +00:00
Carter Anderson
f487407e07 Camera Driven Rendering (#4745)
This adds "high level camera driven rendering" to Bevy. The goal is to give users more control over what gets rendered (and where) without needing to deal with render logic. This will make scenarios like "render to texture", "multiple windows", "split screen", "2d on 3d", "3d on 2d", "pass layering", and more significantly easier. 

Here is an [example of a 2d render sandwiched between two 3d renders (each from a different perspective)](https://gist.github.com/cart/4fe56874b2e53bc5594a182fc76f4915):
![image](https://user-images.githubusercontent.com/2694663/168411086-af13dec8-0093-4a84-bdd4-d4362d850ffa.png)

Users can now spawn a camera, point it at a RenderTarget (a texture or a window), and it will "just work". 

Rendering to a second window is as simple as spawning a second camera and assigning it to a specific window id:
```rust
// main camera (main window)
commands.spawn_bundle(Camera2dBundle::default());

// second camera (other window)
commands.spawn_bundle(Camera2dBundle {
    camera: Camera {
        target: RenderTarget::Window(window_id),
        ..default()
    },
    ..default()
});
```

Rendering to a texture is as simple as pointing the camera at a texture:

```rust
commands.spawn_bundle(Camera2dBundle {
    camera: Camera {
        target: RenderTarget::Texture(image_handle),
        ..default()
    },
    ..default()
});
```

Cameras now have a "render priority", which controls the order they are drawn in. If you want to use a camera's output texture as a texture in the main pass, just set the priority to a number lower than the main pass camera (which defaults to `0`).

```rust
// main pass camera with a default priority of 0
commands.spawn_bundle(Camera2dBundle::default());

commands.spawn_bundle(Camera2dBundle {
    camera: Camera {
        target: RenderTarget::Texture(image_handle.clone()),
        priority: -1,
        ..default()
    },
    ..default()
});

commands.spawn_bundle(SpriteBundle {
    texture: image_handle,
    ..default()
})
```

Priority can also be used to layer to cameras on top of each other for the same RenderTarget. This is what "2d on top of 3d" looks like in the new system:

```rust
commands.spawn_bundle(Camera3dBundle::default());

commands.spawn_bundle(Camera2dBundle {
    camera: Camera {
        // this will render 2d entities "on top" of the default 3d camera's render
        priority: 1,
        ..default()
    },
    ..default()
});
```

There is no longer the concept of a global "active camera". Resources like `ActiveCamera<Camera2d>` and `ActiveCamera<Camera3d>` have been replaced with the camera-specific `Camera::is_active` field. This does put the onus on users to manage which cameras should be active.

Cameras are now assigned a single render graph as an "entry point", which is configured on each camera entity using the new `CameraRenderGraph` component. The old `PerspectiveCameraBundle` and `OrthographicCameraBundle` (generic on camera marker components like Camera2d and Camera3d) have been replaced by `Camera3dBundle` and `Camera2dBundle`, which set 3d and 2d default values for the `CameraRenderGraph` and projections.

```rust
// old 3d perspective camera
commands.spawn_bundle(PerspectiveCameraBundle::default())

// new 3d perspective camera
commands.spawn_bundle(Camera3dBundle::default())
```

```rust
// old 2d orthographic camera
commands.spawn_bundle(OrthographicCameraBundle::new_2d())

// new 2d orthographic camera
commands.spawn_bundle(Camera2dBundle::default())
```

```rust
// old 3d orthographic camera
commands.spawn_bundle(OrthographicCameraBundle::new_3d())

// new 3d orthographic camera
commands.spawn_bundle(Camera3dBundle {
    projection: OrthographicProjection {
        scale: 3.0,
        scaling_mode: ScalingMode::FixedVertical,
        ..default()
    }.into(),
    ..default()
})
```

Note that `Camera3dBundle` now uses a new `Projection` enum instead of hard coding the projection into the type. There are a number of motivators for this change: the render graph is now a part of the bundle, the way "generic bundles" work in the rust type system prevents nice `..default()` syntax, and changing projections at runtime is much easier with an enum (ex for editor scenarios). I'm open to discussing this choice, but I'm relatively certain we will all come to the same conclusion here. Camera2dBundle and Camera3dBundle are much clearer than being generic on marker components / using non-default constructors.

If you want to run a custom render graph on a camera, just set the `CameraRenderGraph` component:

```rust
commands.spawn_bundle(Camera3dBundle {
    camera_render_graph: CameraRenderGraph::new(some_render_graph_name),
    ..default()
})
```

Just note that if the graph requires data from specific components to work (such as `Camera3d` config, which is provided in the `Camera3dBundle`), make sure the relevant components have been added.

Speaking of using components to configure graphs / passes, there are a number of new configuration options:

```rust
commands.spawn_bundle(Camera3dBundle {
    camera_3d: Camera3d {
        // overrides the default global clear color 
        clear_color: ClearColorConfig::Custom(Color::RED),
        ..default()
    },
    ..default()
})

commands.spawn_bundle(Camera3dBundle {
    camera_3d: Camera3d {
        // disables clearing
        clear_color: ClearColorConfig::None,
        ..default()
    },
    ..default()
})
```

Expect to see more of the "graph configuration Components on Cameras" pattern in the future.

By popular demand, UI no longer requires a dedicated camera. `UiCameraBundle` has been removed. `Camera2dBundle` and `Camera3dBundle` now both default to rendering UI as part of their own render graphs. To disable UI rendering for a camera, disable it using the CameraUi component:

```rust
commands
    .spawn_bundle(Camera3dBundle::default())
    .insert(CameraUi {
        is_enabled: false,
        ..default()
    })
```

## Other Changes

* The separate clear pass has been removed. We should revisit this for things like sky rendering, but I think this PR should "keep it simple" until we're ready to properly support that (for code complexity and performance reasons). We can come up with the right design for a modular clear pass in a followup pr.
* I reorganized bevy_core_pipeline into Core2dPlugin and Core3dPlugin (and core_2d / core_3d modules). Everything is pretty much the same as before, just logically separate. I've moved relevant types (like Camera2d, Camera3d, Camera3dBundle, Camera2dBundle) into their relevant modules, which is what motivated this reorganization.
* I adapted the `scene_viewer` example (which relied on the ActiveCameras behavior) to the new system. I also refactored bits and pieces to be a bit simpler. 
* All of the examples have been ported to the new camera approach. `render_to_texture` and `multiple_windows` are now _much_ simpler. I removed `two_passes` because it is less relevant with the new approach. If someone wants to add a new "layered custom pass with CameraRenderGraph" example, that might fill a similar niche. But I don't feel much pressure to add that in this pr.
* Cameras now have `target_logical_size` and `target_physical_size` fields, which makes finding the size of a camera's render target _much_ simpler. As a result, the `Assets<Image>` and `Windows` parameters were removed from `Camera::world_to_screen`, making that operation much more ergonomic.
* Render order ambiguities between cameras with the same target and the same priority now produce a warning. This accomplishes two goals:
    1. Now that there is no "global" active camera, by default spawning two cameras will result in two renders (one covering the other). This would be a silent performance killer that would be hard to detect after the fact. By detecting ambiguities, we can provide a helpful warning when this occurs.
    2. Render order ambiguities could result in unexpected / unpredictable render results. Resolving them makes sense.

## Follow Up Work

* Per-Camera viewports, which will make it possible to render to a smaller area inside of a RenderTarget (great for something like splitscreen)
* Camera-specific MSAA config (should use the same "overriding" pattern used for ClearColor)
* Graph Based Camera Ordering: priorities are simple, but they make complicated ordering constraints harder to express. We should consider adopting a "graph based" camera ordering model with "before" and "after" relationships to other cameras (or build it "on top" of the priority system).
* Consider allowing graphs to run subgraphs from any nest level (aka a global namespace for graphs). Right now the 2d and 3d graphs each need their own UI subgraph, which feels "fine" in the short term. But being able to share subgraphs between other subgraphs seems valuable.
* Consider splitting `bevy_core_pipeline` into `bevy_core_2d` and `bevy_core_3d` packages. Theres a shared "clear color" dependency here, which would need a new home.
2022-06-02 00:12:17 +00:00