Commit graph

407 commits

Author SHA1 Message Date
François
b28f6334da
only take up to the max number of joints (#9351)
# Objective

- Meshes with a higher number of joints than `MAX_JOINTS` are crashing
- Fixes partly #9021 (doesn't crash anymore, but the mesh is not
correctly displayed)

## Solution

- Only take up to `MAX_JOINTS` joints when extending the buffer
2023-08-28 16:58:45 +00:00
James O'Brien
4f1d9a6315
Reorder render sets, refactor bevy_sprite to take advantage (#9236)
This is a continuation of this PR: #8062 

# Objective

- Reorder render schedule sets to allow data preparation when phase item
order is known to support improved batching
- Part of the batching/instancing etc plan from here:
https://github.com/bevyengine/bevy/issues/89#issuecomment-1379249074
- The original idea came from @inodentry and proved to be a good one.
Thanks!
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the new
ordering

## Solution
- Move `Prepare` and `PrepareFlush` after `PhaseSortFlush` 
- Add a `PrepareAssets` set that runs in parallel with other systems and
sets in the render schedule.
  - Put prepare_assets systems in the `PrepareAssets` set
- If explicit dependencies are needed on Mesh or Material RenderAssets
then depend on the appropriate system.
- Add `ManageViews` and `ManageViewsFlush` sets between
`ExtractCommands` and Queue
- Move `queue_mesh*_bind_group` to the Prepare stage
  - Rename them to `prepare_`
- Put systems that prepare resources (buffers, textures, etc.) into a
`PrepareResources` set inside `Prepare`
- Put the `prepare_..._bind_group` systems into a `PrepareBindGroup` set
after `PrepareResources`
- Move `prepare_lights` to the `ManageViews` set
  - `prepare_lights` creates views and this must happen before `Queue`
  - This system needs refactoring to stop handling all responsibilities
- Gather lights, sort, and create shadow map views. Store sorted light
entities in a resource

- Remove `BatchedPhaseItem`
- Replace `batch_range` with `batch_size` representing how many items to
skip after rendering the item or to skip the item entirely if
`batch_size` is 0.
- `queue_sprites` has been split into `queue_sprites` for queueing phase
items and `prepare_sprites` for batching after the `PhaseSort`
  - `PhaseItem`s are still inserted in `queue_sprites`
- After sorting adjacent compatible sprite phase items are accumulated
into `SpriteBatch` components on the first entity of each batch,
containing a range of vertex indices. The associated `PhaseItem`'s
`batch_size` is updated appropriately.
- `SpriteBatch` items are then drawn skipping over the other items in
the batch based on the value in `batch_size`
- A very similar refactor was performed on `bevy_ui`
---

## Changelog

Changed:
- Reordered and reworked render app schedule sets. The main change is
that data is extracted, queued, sorted, and then prepared when the order
of data is known.
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the
reordering.

## Migration Guide
- Assets such as materials and meshes should now be created in
`PrepareAssets` e.g. `prepare_assets<Mesh>`
- Queueing entities to `RenderPhase`s continues to be done in `Queue`
e.g. `queue_sprites`
- Preparing resources (textures, buffers, etc.) should now be done in
`PrepareResources`, e.g. `prepare_prepass_textures`,
`prepare_mesh_uniforms`
- Prepare bind groups should now be done in `PrepareBindGroups` e.g.
`prepare_mesh_bind_group`
- Any batching or instancing can now be done in `Prepare` where the
order of the phase items is known e.g. `prepare_sprites`

 
## Next Steps
- Introduce some generic mechanism to ensure items that can be batched
are grouped in the phase item order, currently you could easily have
`[sprite at z 0, mesh at z 0, sprite at z 0]` preventing batching.
 - Investigate improved orderings for building the MeshUniform buffer
 - Implementing batching across the rest of bevy

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
2023-08-27 14:33:49 +00:00
Rob Parrett
a788e31ad5
Fix CI for Rust 1.72 (#9562)
# Objective

[Rust 1.72.0](https://blog.rust-lang.org/2023/08/24/Rust-1.72.0.html) is
now stable.

# Notes

- `let-else` formatting has arrived!
- I chose to allow `explicit_iter_loop` due to
https://github.com/rust-lang/rust-clippy/issues/11074.
  
We didn't hit any of the false positives that prevent compilation, but
fixing this did produce a lot of the "symbol soup" mentioned, e.g. `for
image in &mut *image_events {`.
  
  Happy to undo this if there's consensus the other way.

---------

Co-authored-by: François <mockersf@gmail.com>
2023-08-25 12:34:24 +00:00
François
bc50682360
fix wireframe after MeshUniform size reduction (#9505)
# Objective

- Wireframe currently don't display since #9416
- There is an error
```
2023-08-20T10:06:54.190347Z ERROR bevy_render::render_resource::pipeline_cache: failed to process shader:
error: no definition in scope for identifier: 'vertex_no_morph'
   ┌─ crates/bevy_pbr/src/render/wireframe.wgsl:26:94
   │
26 │     let model = bevy_pbr::mesh_functions::get_model_matrix(vertex_no_morph.instance_index);
   │                                                                                              ^^^^^^^^^^^^^^^ unknown identifier
   │
   = no definition in scope for identifier: 'vertex_no_morph'
```

## Solution

- Use the correct identifier
2023-08-21 07:53:50 +00:00
Robert Swain
0a11af9375
Reduce the size of MeshUniform to improve performance (#9416)
# Objective

- Significantly reduce the size of MeshUniform by only including
necessary data.

## Solution

Local to world, model transforms are affine. This means they only need a
4x3 matrix to represent them.

`MeshUniform` stores the current, and previous model transforms, and the
inverse transpose of the current model transform, all as 4x4 matrices.
Instead we can store the current, and previous model transforms as 4x3
matrices, and we only need the upper-left 3x3 part of the inverse
transpose of the current model transform. This change allows us to
reduce the serialized MeshUniform size from 208 bytes to 144 bytes,
which is over a 30% saving in data to serialize, and VRAM bandwidth and
space.

## Benchmarks

On an M1 Max, running `many_cubes -- sphere`, main is in yellow, this PR
is in red:
<img width="1484" alt="Screenshot 2023-08-11 at 02 36 43"
src="https://github.com/bevyengine/bevy/assets/302146/7d99c7b3-f2bb-4004-a8d0-4c00f755cb0d">
A reduction in frame time of ~14%.

---

## Changelog

- Changed: Redefined `MeshUniform` to improve performance by using 4x3
affine transforms and reconstructing 4x4 matrices in the shader. Helper
functions were added to `bevy_pbr::mesh_functions` to unpack the data.
`affine_to_square` converts the packed 4x3 in 3x4 matrix data to a 4x4
matrix. `mat2x4_f32_to_mat3x3` converts the 3x3 in mat2x4 + f32 matrix
data back into a 3x3.

## Migration Guide

Shader code before:
```
var model = mesh[instance_index].model;
```

Shader code after:
```
#import bevy_pbr::mesh_functions affine_to_square

var model = affine_to_square(mesh[instance_index].model);
```
2023-08-15 06:00:23 +00:00
Robert Swain
c1a5428f8e
Work around naga/wgpu WGSL instance_index -> GLSL gl_InstanceID bug on WebGL2 (#9383)
naga and wgpu should polyfill WGSL instance_index functionality where it
is not available in GLSL. Until that is done, we can work around it in
bevy using a push constant which is converted to a uniform by naga and
wgpu.

# Objective

- Fixes #9375 

## Solution

- Use a push constant to pass in the base instance to the shader on
WebGL2 so that base instance + gl_InstanceID is used to correctly
represent the instance index.

## TODO

- [ ] Benchmark vs per-object dynamic offset MeshUniform as this will
now push a uniform value per-draw as well as update the dynamic offset
per-batch.
- [x] Test on DX12 AMD/NVIDIA to check that this PR does not regress any
problems that were observed there. (@Elabajaba @robtfm were testing that
last time - help appreciated. <3 )

---

## Changelog

- Added: `bevy_render::instance_index` shader import which includes a
workaround for the lack of a WGSL `instance_index` polyfill for WebGL2
in naga and wgpu for the time being. It uses a push_constant which gets
converted to a plain uniform by naga and wgpu.

## Migration Guide

Shader code before:

```
struct Vertex {
    @builtin(instance_index) instance_index: u32,
...
}

@vertex
fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
...

    var model = mesh[vertex_no_morph.instance_index].model;
```

After:

```
#import bevy_render::instance_index

struct Vertex {
    @builtin(instance_index) instance_index: u32,
...
}

@vertex
fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
...

    var model = mesh[bevy_render::instance_index::get_instance_index(vertex_no_morph.instance_index)].model;
```
2023-08-09 18:38:45 +00:00
Robert Swain
3c6fad269b
Fix shader_material_glsl example after #9254 (#9311)
# Objective

- Fix shader_material_glsl example

## Solution

- Expose the `PER_OBJECT_BUFFER_BATCH_SIZE` shader def through the
default `MeshPipeline` specialization.
- Make use of it in the `custom_material.vert` shader to access the mesh
binding.

---

## Changelog

- Added: Exposed the `PER_OBJECT_BUFFER_BATCH_SIZE` shader def through
the default `MeshPipeline` specialization to use in custom shaders not
using bevy_pbr::mesh_bindings that still want to use the mesh binding in
some way.
2023-07-31 13:14:40 +00:00
Robert Swain
e6405bb7b4
Use GpuArrayBuffer for MeshUniform (#9254)
# Objective

- Reduce the number of rebindings to enable batching of draw commands

## Solution

- Use the new `GpuArrayBuffer` for `MeshUniform` data to store all
`MeshUniform` data in arrays within fewer bindings
- Sort opaque/alpha mask prepass, opaque/alpha mask main, and shadow
phases also by the batch per-object data binding dynamic offset to
improve performance on WebGL2.

---

## Changelog

- Changed: Per-object `MeshUniform` data is now managed by
`GpuArrayBuffer` as arrays in buffers that need to be indexed into.

## Migration Guide

Accessing the `model` member of an individual mesh object's shader
`Mesh` struct the old way where each `MeshUniform` was stored at its own
dynamic offset:
```rust
struct Vertex {
    @location(0) position: vec3<f32>,
};

fn vertex(vertex: Vertex) -> VertexOutput {
    var out: VertexOutput;
    out.clip_position = mesh_position_local_to_clip(
        mesh.model,
        vec4<f32>(vertex.position, 1.0)
    );
    return out;
}
```

The new way where one needs to index into the array of `Mesh`es for the
batch:
```rust
struct Vertex {
    @builtin(instance_index) instance_index: u32,
    @location(0) position: vec3<f32>,
};

fn vertex(vertex: Vertex) -> VertexOutput {
    var out: VertexOutput;
    out.clip_position = mesh_position_local_to_clip(
        mesh[vertex.instance_index].model,
        vec4<f32>(vertex.position, 1.0)
    );
    return out;
}
```
Note that using the instance_index is the default way to pass the
per-object index into the shader, but if you wish to do custom rendering
approaches you can pass it in however you like.

---------

Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
Co-authored-by: Elabajaba <Elabajaba@users.noreply.github.com>
2023-07-30 13:17:08 +00:00
Sludge
9b92de9e35
Register AlphaMode type (#9222)
# Objective

- `AlphaMode` derives `Reflect`, but wasn't registered with the app and
type registry

## Solution

- `app.register_type::<AlphaMode>()`
2023-07-20 21:26:03 +00:00
Carter Anderson
7c3131a761
Bump Version after Release (#9106)
CI-capable version of #9086

---------

Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: François <mockersf@gmail.com>
2023-07-10 21:19:27 +00:00
ClayenKitten
ffc572728f
Fix typos throughout the project (#9090)
# Objective

Fix typos throughout the project.

## Solution

[`typos`](https://github.com/crate-ci/typos) project was used for
scanning, but no automatic corrections were applied. I checked
everything by hand before fixing.

Most of the changes are documentation/comments corrections. Also, there
are few trivial changes to code (variable name, pub(crate) function name
and a few error/panic messages).

## Unsolved

`bevy_reflect_derive` has
[typo](1b51053f19/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs (L76))
in enum variant name that I didn't fix. Enum is `pub(crate)`, so there
shouldn't be any trouble if fixed. However, code is tightly coupled with
macro usage, so I decided to leave it for more experienced contributor
just in case.
2023-07-10 00:11:51 +00:00
Carter Anderson
8ba9571eed
Release 0.11.0 (#9080)
I created this manually as Github didn't want to run CI for the
workflow-generated PR. I'm guessing we didn't hit this in previous
releases because we used bors.

Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-09 08:43:47 +00:00
Edgar Geier
e03dd4d695
Run update_previous_view_projections in PreUpdate schedule (#9024)
# Objective

- Fixes #8630.

## Solution

Since a camera's view and projection matrices are modified during
`PostUpdate` in `camera_system` and `propagate_transforms`, it is fine
to move `update_previous_view_projections` from `Update` to `PreUpdate`.
Doing so adds consistence with `update_mesh_previous_global_transforms`
and allows systems in `Update` to use `PreviousViewProjection` correctly
without explicit ordering.
2023-07-05 15:51:19 +00:00
Nicola Papale
889a5fb130
Fix morph target prepass shader (#9013)
# Objective

Since 10f5c92, shadows were broken for models with morph target.

When #5703 was merged, the morph target code in `render/mesh.wgsl` was
correctly updated to use the new import syntax. However, similar code
exists in `prepass/prepass.wgsl`, but it was never update. (the reason
code is duplicated is that the `Vertex` struct is different for both
files).

## Solution

Update the code, so that shadows render correctly with morph targets.
2023-07-02 06:41:26 +00:00
Elabajaba
94291cf569
Fix black spots appearing due to NANs when SSAO is enabled (#8926)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/8925

## Solution

~~Clamp the bad values.~~

Normalize the prepass normals when we get them in the `prepass_normal()`
function.

## More Info

The issue is that NdotV is sometimes very slightly greater than 1 (maybe
FP rounding issues?), which caused `F_Schlick()` to return NANs in
`pow(1.0 - NdotV, 5.0)` (call stack looked like`pbr()` ->
`directional_light()` -> `Fd_Burley()` -> `F_Schlick()`)
2023-07-01 21:29:13 +00:00
Nicola Papale
982e33741d
Fix parallax mapping (#9003)
# Objective

Since 10f5c92, parallax mapping was broken.

When #5703 was merged, the change from `in.uv` to `uv` in the pbr shader
was reverted. So the shader would use the wrong coordinate to sample the
various textures.

## Solution

We revert to using the correct uv.
2023-07-01 13:37:49 +00:00
TotalKrill
d90c65d25f
Fix WebGL mode for Adreno GPUs (#8508)
# Objective

- This fixes a crash when loading shaders, when running an Adreno GPU
and using WebGL mode.
- Fixes #8506 
- Fixes #8047

## Solution

- The shader pbr_functions.wgsl, will fail in apply_fog function, trying
to access values that are null on Adreno chipsets using WebGL, these
devices are commonly found in android handheld devices.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
2023-06-29 04:32:04 +00:00
Gino Valente
aeeb20ec4c
bevy_reflect: FromReflect Ergonomics Implementation (#6056)
# Objective

**This implementation is based on
https://github.com/bevyengine/rfcs/pull/59.**

---

Resolves #4597

Full details and motivation can be found in the RFC, but here's a brief
summary.

`FromReflect` is a very powerful and important trait within the
reflection API. It allows Dynamic types (e.g., `DynamicList`, etc.) to
be formed into Real ones (e.g., `Vec<i32>`, etc.).

This mainly comes into play concerning deserialization, where the
reflection deserializers both return a `Box<dyn Reflect>` that almost
always contain one of these Dynamic representations of a Real type. To
convert this to our Real type, we need to use `FromReflect`.

It also sneaks up in other ways. For example, it's a required bound for
`T` in `Vec<T>` so that `Vec<T>` as a whole can be made `FromReflect`.
It's also required by all fields of an enum as it's used as part of the
`Reflect::apply` implementation.

So in other words, much like `GetTypeRegistration` and `Typed`, it is
very much a core reflection trait.

The problem is that it is not currently treated like a core trait and is
not automatically derived alongside `Reflect`. This makes using it a bit
cumbersome and easy to forget.

## Solution

Automatically derive `FromReflect` when deriving `Reflect`.

Users can then choose to opt-out if needed using the
`#[reflect(from_reflect = false)]` attribute.

```rust
#[derive(Reflect)]
struct Foo;

#[derive(Reflect)]
#[reflect(from_reflect = false)]
struct Bar;

fn test<T: FromReflect>(value: T) {}

test(Foo); // <-- OK
test(Bar); // <-- Panic! Bar does not implement trait `FromReflect`
```

#### `ReflectFromReflect`

This PR also automatically adds the `ReflectFromReflect` (introduced in
#6245) registration to the derived `GetTypeRegistration` impl— if the
type hasn't opted out of `FromReflect` of course.

<details>
<summary><h4>Improved Deserialization</h4></summary>

> **Warning**
> This section includes changes that have since been descoped from this
PR. They will likely be implemented again in a followup PR. I am mainly
leaving these details in for archival purposes, as well as for reference
when implementing this logic again.

And since we can do all the above, we might as well improve
deserialization. We can now choose to deserialize into a Dynamic type or
automatically convert it using `FromReflect` under the hood.

`[Un]TypedReflectDeserializer::new` will now perform the conversion and
return the `Box`'d Real type.

`[Un]TypedReflectDeserializer::new_dynamic` will work like what we have
now and simply return the `Box`'d Dynamic type.

```rust
// Returns the Real type
let reflect_deserializer = UntypedReflectDeserializer::new(&registry);
let mut deserializer = ron:🇩🇪:Deserializer::from_str(input)?;

let output: SomeStruct = reflect_deserializer.deserialize(&mut deserializer)?.take()?;

// Returns the Dynamic type
let reflect_deserializer = UntypedReflectDeserializer::new_dynamic(&registry);
let mut deserializer = ron:🇩🇪:Deserializer::from_str(input)?;

let output: DynamicStruct = reflect_deserializer.deserialize(&mut deserializer)?.take()?;
```

</details>

---

## Changelog

* `FromReflect` is now automatically derived within the `Reflect` derive
macro
* This includes auto-registering `ReflectFromReflect` in the derived
`GetTypeRegistration` impl
* ~~Renamed `TypedReflectDeserializer::new` and
`UntypedReflectDeserializer::new` to
`TypedReflectDeserializer::new_dynamic` and
`UntypedReflectDeserializer::new_dynamic`, respectively~~ **Descoped**
* ~~Changed `TypedReflectDeserializer::new` and
`UntypedReflectDeserializer::new` to automatically convert the
deserialized output using `FromReflect`~~ **Descoped**

## Migration Guide

* `FromReflect` is now automatically derived within the `Reflect` derive
macro. Items with both derives will need to remove the `FromReflect`
one.

  ```rust
  // OLD
  #[derive(Reflect, FromReflect)]
  struct Foo;
  
  // NEW
  #[derive(Reflect)]
  struct Foo;
  ```

If using a manual implementation of `FromReflect` and the `Reflect`
derive, users will need to opt-out of the automatic implementation.

  ```rust
  // OLD
  #[derive(Reflect)]
  struct Foo;
  
  impl FromReflect for Foo {/* ... */}
  
  // NEW
  #[derive(Reflect)]
  #[reflect(from_reflect = false)]
  struct Foo;
  
  impl FromReflect for Foo {/* ... */}
  ```

<details>
<summary><h4>Removed Migrations</h4></summary>

> **Warning**
> This section includes changes that have since been descoped from this
PR. They will likely be implemented again in a followup PR. I am mainly
leaving these details in for archival purposes, as well as for reference
when implementing this logic again.

* The reflect deserializers now perform a `FromReflect` conversion
internally. The expected output of `TypedReflectDeserializer::new` and
`UntypedReflectDeserializer::new` is no longer a Dynamic (e.g.,
`DynamicList`), but its Real counterpart (e.g., `Vec<i32>`).

  ```rust
let reflect_deserializer =
UntypedReflectDeserializer::new_dynamic(&registry);
  let mut deserializer = ron:🇩🇪:Deserializer::from_str(input)?;
  
  // OLD
let output: DynamicStruct = reflect_deserializer.deserialize(&mut
deserializer)?.take()?;
  
  // NEW
let output: SomeStruct = reflect_deserializer.deserialize(&mut
deserializer)?.take()?;
  ```

Alternatively, if this behavior isn't desired, use the
`TypedReflectDeserializer::new_dynamic` and
`UntypedReflectDeserializer::new_dynamic` methods instead:

  ```rust
  // OLD
  let reflect_deserializer = UntypedReflectDeserializer::new(&registry);
  
  // NEW
let reflect_deserializer =
UntypedReflectDeserializer::new_dynamic(&registry);
  ```

</details>

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-06-29 01:31:34 +00:00
robtfm
15445c990e
fix prepass normal_mapping (#8978)
# Objective

#5703 caused the normal prepass to fail as the prepass uses
`pbr_functions::apply_normal_mapping`, which uses
`mesh_view_bindings::view` to determine mip bias, which conflicts with
`prepass_bindings::view`.

## Solution

pass the mip bias to the `apply_normal_mapping` function explicitly.
2023-06-29 00:28:34 +00:00
robtfm
10f5c92068
improve shader import model (#5703)
# Objective

operate on naga IR directly to improve handling of shader modules.
- give codespan reporting into imported modules
- allow glsl to be used from wgsl and vice-versa

the ultimate objective is to make it possible to 
- provide user hooks for core shader functions (to modify light
behaviour within the standard pbr pipeline, for example)
- make automatic binding slot allocation possible

but ... since this is already big, adds some value and (i think) is at
feature parity with the existing code, i wanted to push this now.

## Solution

i made a crate called naga_oil (https://github.com/robtfm/naga_oil -
unpublished for now, could be part of bevy) which manages modules by
- building each module independantly to naga IR
- creating "header" files for each supported language, which are used to
build dependent modules/shaders
- make final shaders by combining the shader IR with the IR for imported
modules

then integrated this into bevy, replacing some of the existing shader
processing stuff. also reworked examples to reflect this.

## Migration Guide

shaders that don't use `#import` directives should work without changes.

the most notable user-facing difference is that imported
functions/variables/etc need to be qualified at point of use, and
there's no "leakage" of visible stuff into your shader scope from the
imports of your imports, so if you used things imported by your imports,
you now need to import them directly and qualify them.

the current strategy of including/'spreading' `mesh_vertex_output`
directly into a struct doesn't work any more, so these need to be
modified as per the examples (e.g. color_material.wgsl, or many others).
mesh data is assumed to be in bindgroup 2 by default, if mesh data is
bound into bindgroup 1 instead then the shader def `MESH_BINDGROUP_1`
needs to be added to the pipeline shader_defs.
2023-06-27 00:29:22 +00:00
JMS55
724e69bff4
Bias texture mipmaps (#7614)
# Objective

- Closes #7323 
- Reduce texture blurriness for TAA

## Solution

- Add a `MipBias` component and view uniform.
- Switch material `textureSample()` calls to `textureSampleBias()`.
- Add a `-1.0` bias to TAA.

---

## Changelog

- Added `MipBias` camera component, mostly for internal use.

---------

Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-06-22 20:55:05 +00:00
Nicola Papale
c6170d48f9
Add morph targets (#8158)
# Objective

- Add morph targets to `bevy_pbr` (closes #5756) & load them from glTF
- Supersedes #3722
- Fixes #6814

[Morph targets][1] (also known as shape interpolation, shape keys, or
blend shapes) allow animating individual vertices with fine grained
controls. This is typically used for facial expressions. By specifying
multiple poses as vertex offset, and providing a set of weight of each
pose, it is possible to define surprisingly realistic transitions
between poses. Blending between multiple poses also allow composition.
Morph targets are part of the [gltf standard][2] and are a feature of
Unity and Unreal, and babylone.js, it is only natural to implement them
in bevy.

## Solution

This implementation of morph targets uses a 3d texture where each pixel
is a component of an animated attribute. Each layer is a different
target. We use a 2d texture for each target, because the number of
attribute×components×animated vertices is expected to always exceed the
maximum pixel row size limit of webGL2. It copies fairly closely the way
skinning is implemented on the CPU side, while on the GPU side, the
shader morph target implementation is a relatively trivial detail.

We add an optional `morph_texture` to the `Mesh` struct. The
`morph_texture` is built through a method that accepts an iterator over
attribute buffers.

The `MorphWeights` component, user-accessible, controls the blend of
poses used by mesh instances (so that multiple copy of the same mesh may
have different weights), all the weights are uploaded to a uniform
buffer of 256 `f32`. We limit to 16 poses per mesh, and a total of 256
poses.

More literature:
* Old babylone.js implementation (vertex attribute-based):
https://www.eternalcoding.com/dev-log-1-morph-targets/
* Babylone.js implementation (similar to ours):
https://www.youtube.com/watch?v=LBPRmGgU0PE
* GPU gems 3:
https://developer.nvidia.com/gpugems/gpugems3/part-i-geometry/chapter-3-directx-10-blend-shapes-breaking-limits
* Development discord thread
https://discord.com/channels/691052431525675048/1083325980615114772


https://user-images.githubusercontent.com/26321040/231181046-3bca2ab2-d4d9-472e-8098-639f1871ce2e.mp4


https://github.com/bevyengine/bevy/assets/26321040/d2a0c544-0ef8-45cf-9f99-8c3792f5a258

## Acknowledgements

* Thanks to `storytold` for sponsoring the feature
* Thanks to `superdump` and `james7132` for guidance and help figuring
out stuff

## Future work

- Handling of less and more attributes (eg: animated uv, animated
arbitrary attributes)
- Dynamic pose allocation (so that zero-weighted poses aren't uploaded
to GPU for example, enables much more total poses)
- Better animation API, see #8357

----

## Changelog

- Add morph targets to bevy meshes
- Support up to 64 poses per mesh of individually up to 116508 vertices,
animation currently strictly limited to the position, normal and tangent
attributes.
	- Load a morph target using `Mesh::set_morph_targets` 
- Add `VisitMorphTargets` and `VisitMorphAttributes` traits to
`bevy_render`, this allows defining morph targets (a fairly complex and
nested data structure) through iterators (ie: single copy instead of
passing around buffers), see documentation of those traits for details
- Add `MorphWeights` component exported by `bevy_render`
- `MorphWeights` control mesh's morph target weights, blending between
various poses defined as morph targets.
- `MorphWeights` are directly inherited by direct children (single level
of hierarchy) of an entity. This allows controlling several mesh
primitives through a unique entity _as per GLTF spec_.
- Add `MorphTargetNames` component, naming each indices of loaded morph
targets.
- Load morph targets weights and buffers in `bevy_gltf` 
- handle morph targets animations in `bevy_animation` (previously, it
was a `warn!` log)
- Add the `MorphStressTest.gltf` asset for morph targets testing, taken
from the glTF samples repo, CC0.
- Add morph target manipulation to `scene_viewer`
- Separate the animation code in `scene_viewer` from the rest of the
code, reducing `#[cfg(feature)]` noise
- Add the `morph_targets.rs` example to show off how to manipulate morph
targets, loading `MorpStressTest.gltf`

## Migration Guide

- (very specialized, unlikely to be touched by 3rd parties)
- `MeshPipeline` now has a single `mesh_layouts` field rather than
separate `mesh_layout` and `skinned_mesh_layout` fields. You should
handle all possible mesh bind group layouts in your implementation
- You should also handle properly the new `MORPH_TARGETS` shader def and
mesh pipeline key. A new function is exposed to make this easier:
`setup_moprh_and_skinning_defs`
- The `MeshBindGroup` is now `MeshBindGroups`, cached bind groups are
now accessed through the `get` method.

[1]: https://en.wikipedia.org/wiki/Morph_target_animation
[2]:
https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#morph-targets

---------

Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-06-22 20:00:01 +00:00
Daniel Chia
0a881ab37f
Cascaded shadow maps: Fix prepass ortho depth clamping (#8877)
# Objective

- Fixes #8645

## Solution

Cascaded shadow maps use a technique commonly called shadow pancaking to
enhance shadow map resolution by restricting the orthographic projection
used in creating the shadow maps to the frustum slice for the cascade.
The implication of this restriction is that shadow casters can be closer
than the near plane of the projection volume.

Prior to this PR, we address clamp the depth of the prepass vertex
output to ensure that these shadow casters do not get clipped, resulting
in shadow loss. However, a flaw / bug of the prior approach is that the
depth that gets written to the shadow map isn't quite correct - the
depth was previously derived by interpolated the clamped clip position,
resulting in depths that are further than they should be. This creates
artifacts that are particularly noticeable when a very 'long' object
intersects the near plane close to perpendicularly.

The fix in this PR is to propagate the unclamped depth to the prepass
fragment shader and use that depth value directly.

A complementary solution would be to use
[DEPTH_CLIP_CONTROL](https://docs.rs/wgpu/latest/wgpu/struct.Features.html#associatedconstant.DEPTH_CLIP_CONTROL)
to request `unclipped_depth`. However due to the relatively low support
of the feature on Vulkan (I believe it's ~38%), I went with this
solution for now to get the broadest fix out first.

---

## Changelog

- Fixed: Shadows from directional lights were sometimes incorrectly
omitted when the shadow caster was partially out of view.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-06-21 22:00:19 +00:00
Edgar Geier
f18f28874a
Allow tuples and single plugins in add_plugins, deprecate add_plugin (#8097)
# Objective

- Better consistency with `add_systems`.
- Deprecating `add_plugin` in favor of a more powerful `add_plugins`.
- Allow passing `Plugin` to `add_plugins`.
- Allow passing tuples to `add_plugins`.

## Solution

- `App::add_plugins` now takes an `impl Plugins` parameter.
- `App::add_plugin` is deprecated.
- `Plugins` is a new sealed trait that is only implemented for `Plugin`,
`PluginGroup` and tuples over `Plugins`.
- All examples, benchmarks and tests are changed to use `add_plugins`,
using tuples where appropriate.

---

## Changelog

### Changed

- `App::add_plugins` now accepts all types that implement `Plugins`,
which is implemented for:
  - Types that implement `Plugin`.
  - Types that implement `PluginGroup`.
  - Tuples (up to 16 elements) over types that implement `Plugins`.
- Deprecated `App::add_plugin` in favor of `App::add_plugins`.

## Migration Guide

- Replace `app.add_plugin(plugin)` calls with `app.add_plugins(plugin)`.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-06-21 20:51:03 +00:00
IceSentry
72b4aacf86
fix normal prepass (#8890)
# Objective

- Fix broken normals when the NormalPrepass is enabled

## Solution

- Don't use the normal prepass for the world_normal
- Only loadthe normal prepass 
    - when msaa is disabled
- for opaque or alpha mask meshes and only for use it for N not
world_normal
2023-06-21 17:25:20 +00:00
Raffaele Ragni
7fc6db32ce
Add FromReflect where Reflect is used (#8776)
# Objective

Discovered that PointLight did not implement FromReflect. Adding
FromReflect where Reflect is used. I overreached and applied this rule
everywhere there was a Reflect without a FromReflect, except from where
the compiler wouldn't allow me.

Based from question: https://github.com/bevyengine/bevy/discussions/8774

## Solution

- Adding FromReflect where Reflect was already derived

## Notes

First PR I do in this ecosystem, so not sure if this is the usual
approach, that is, to touch many files at once.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-06-19 16:18:17 +00:00
JMS55
af9c945f40
Screen Space Ambient Occlusion (SSAO) MVP (#7402)
![image](https://github.com/bevyengine/bevy/assets/47158642/dbb62645-f639-4f2b-b84b-26fd915c186d)

# Objective

- Add Screen space ambient occlusion (SSAO). SSAO approximates
small-scale, local occlusion of _indirect_ diffuse light between
objects. SSAO does not apply to direct lighting, such as point or
directional lights.
- This darkens creases, e.g. on staircases, and gives nice contact
shadows where objects meet, giving entities a more "grounded" feel.
- Closes https://github.com/bevyengine/bevy/issues/3632.

## Solution

- Implement the GTAO algorithm.
-
https://www.activision.com/cdn/research/Practical_Real_Time_Strategies_for_Accurate_Indirect_Occlusion_NEW%20VERSION_COLOR.pdf
-
https://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf
- Source code heavily based on [Intel's
XeGTAO](0d177ce06b/Source/Rendering/Shaders/XeGTAO.hlsli).
- Add an SSAO bevy example.

## Algorithm Overview
* Run a depth and normal prepass
* Create downscaled mips of the depth texture (preprocess_depths pass)
* GTAO pass - for each pixel, take several random samples from the
depth+normal buffers, reconstruct world position, raytrace in screen
space to estimate occlusion. Rather then doing completely random samples
on a hemisphere, you choose random _slices_ of the hemisphere, and then
can analytically compute the full occlusion of that slice. Also compute
edges based on depth differences here.
* Spatial denoise pass - bilateral blur, using edge detection to not
blur over edges. This is the final SSAO result.
* Main pass - if SSAO exists, sample the SSAO texture, and set occlusion
to be the minimum of ssao/material occlusion. This then feeds into the
rest of the PBR shader as normal.

---

## Future Improvements
- Maybe remove the low quality preset for now (too noisy)
- WebGPU fallback (see below)
- Faster depth->world position (see reverted code)
- Bent normals 
- Try interleaved gradient noise or spatiotemporal blue noise
- Replace the spatial denoiser with a combined spatial+temporal denoiser
- Render at half resolution and use a bilateral upsample
- Better multibounce approximation
(https://drive.google.com/file/d/1SyagcEVplIm2KkRD3WQYSO9O0Iyi1hfy/view)

## Far-Future Performance Improvements
- F16 math (missing naga-wgsl support
https://github.com/gfx-rs/naga/issues/1884)
- Faster coordinate space conversion for normals
- Faster depth mipchain creation
(https://github.com/GPUOpen-Effects/FidelityFX-SPD) (wgpu/naga does not
currently support subgroup ops)
- Deinterleaved SSAO for better cache efficiency
(https://developer.nvidia.com/sites/default/files/akamai/gameworks/samples/DeinterleavedTexturing.pdf)

## Other Interesting Papers
- Visibility bitmask
(https://link.springer.com/article/10.1007/s00371-022-02703-y,
https://cdrinmatane.github.io/posts/cgspotlight-slides/)
- Screen space diffuse lighting
(https://github.com/Patapom/GodComplex/blob/master/Tests/TestHBIL/2018%20Mayaux%20-%20Horizon-Based%20Indirect%20Lighting%20(HBIL).pdf)

## Platform Support
* SSAO currently does not work on DirectX12 due to issues with wgpu and
naga:
  * https://github.com/gfx-rs/wgpu/pull/3798
  * https://github.com/gfx-rs/naga/pull/2353
* SSAO currently does not work on WebGPU because r16float is not a valid
storage texture format
https://gpuweb.github.io/gpuweb/wgsl/#storage-texel-formats. We can fix
this with a fallback to r32float.

---

## Changelog

- Added ScreenSpaceAmbientOcclusionSettings,
ScreenSpaceAmbientOcclusionQualityLevel, and
ScreenSpaceAmbientOcclusionBundle

---------

Co-authored-by: IceSentry <c.giguere42@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
Co-authored-by: Daniel Chia <danstryder@gmail.com>
Co-authored-by: Elabajaba <Elabajaba@users.noreply.github.com>
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
Co-authored-by: Brandon Dyer <brandondyer64@gmail.com>
Co-authored-by: Edgar Geier <geieredgar@gmail.com>
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-06-18 21:05:55 +00:00
lelo
278daab6ae
Rename Plane struct to HalfSpace (#8744)
# Objective

- Rename the `render::primitives::Plane` struct as to not confuse it
with `bevy_render::mesh::shape::Plane`
- Fixes https://github.com/bevyengine/bevy/issues/8730

## Solution

- Refactor the `render::primitives::Plane` struct to
`render::primitives::HalfSpace`
- Modify documentation to reflect this change

## Changelog

- Renamed `Plane` to `HalfSpace` to more accurately represent it's use
- Renamed `planes` member in `Frustum` to `half_spaces` to reflect
changes

## Migration Guide

- `Plane` has been renamed to `HalfSpace`
- `planes` member in `Frustum` has been renamed to `half_spaces`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
2023-06-12 19:27:41 +00:00
Chris Sixsmith
a78c4d78d5
Make setup of Opaque3dPrepass and AlphaMask3dPrepass phase items consistent with others (#8408)
# Objective

When browsing the bevy source code to try and learn about
`bevy_core_pipeline`, I noticed that the `DrawFunctions` resources,
`sort_phase_system`s and texture preparation for the `Opaque3d` and
`AlphaMask3d` phase items are all set up in `bevy_core_pipeline`, while
the `Opaque3dPrepass` and `AlphaMask3dPrepass` phase items are only
*declared* in `bevy_core_pipeline`, and actually registered properly
with the renderer in `bevy_pbr`.

This means that, if I am trying to make crate that replaces `bevy_pbr`,
I need to make sure I manually fix this unfinished setup the same way
that `bevy_pbr` does. Worse, it means that if I try to use the
`PrepassNode` `bevy_core_pipeline` adds *without* fixing this, the
engine will simply crash because the `DrawFunctions<T>` resources cannot
be accessed.

The only advantage I can think of for bevy doing it this way is an
ambiguous performance save due to the prepass render phases not being
present unless you are using prepass materials with PBR.

## Solution

I have moved the registration of `DrawFunctions<T>`,
`sort_phase_system::<T>`, camera `RenderPhase` extraction, and texture
preparation for prepass's phase items into `bevy_core_pipeline`
alongside the equivalent code that sets up the `Opaque3d`, `AlphaMask3d`
and `Transparent3d` phase items.

Am open to tweaking this to improve the performance impact of prepass
things being around if the app doesn't use them if needed.

I've tested that the `shader_prepass` example still works with this
change.
2023-06-12 19:15:28 +00:00
Nicola Papale
83de94f9f9
Register a few missed reflect components (#8807)
# Objective

-  Some reflect components weren't properly registered.

## Solution

- We register them
- I also sorted the register lines in `Plugin::build` in `bevy_ui`

### Note

How I did I find them:

- I picked up the list of `Component`s from the `Component` trait page
in rustdoc.
- Then I tried to register all of them. Removing the registration when
it doesn't implement `Reflect` to pass compilation.
- Then I added `app.register_type_data::<T, Foo>()`, for all Reflect
components. It panics if `T` is not registered.
- I repeated the last line N times until bevy stopped panicking at
startup

---

## Changelog

- Register the following components: `PrimaryWindow` `Fxaa`
`FogSettings` `NotShadowCaster` `NotShadowReceiver` `CalculatedClip`
`RelativeCursorPosition`
2023-06-10 23:19:39 +00:00
Nicola Papale
0ed8b20d8a
Remove Component derive for AlphaMode (#8804)
`AlphaMode` is not used as a component anywhere in the engine. It
shouldn't implement `Component`. It might mislead users into thinking it
has any effect as a component.

---

## Changelog

- Remove `Component` implementation for `AlphaMode`. It wasn't used by
anything.

## Migration Guide

`AlphaMode` is not a component anymore.

It wasn't used anywhere in the engine. If you were using it as a
component for your own purposes, you should use a newtype instead, as
follow:

```rust
#[derive(Component, Deref)]
struct MyAlphaMode(AlphaMode);
```

Then replace uses of `AlphaMode` with `MyAlphaMode`

```diff
- Query<&AlphaMode, …>,
+ Query<&MyAlphaMode, …>,
```
2023-06-10 22:38:07 +00:00
radiish
1efc762924
reflect: stable type path v2 (#7184)
# Objective

- Introduce a stable alternative to
[`std::any::type_name`](https://doc.rust-lang.org/std/any/fn.type_name.html).
- Rewrite of #5805 with heavy inspiration in design.
- On the path to #5830.
- Part of solving #3327.


## Solution

- Add a `TypePath` trait for static stable type path/name information.
- Add a `TypePath` derive macro.
- Add a `impl_type_path` macro for implementing internal and foreign
types in `bevy_reflect`.

---

## Changelog

- Added `TypePath` trait.
- Added `DynamicTypePath` trait and `get_type_path` method to `Reflect`.
- Added a `TypePath` derive macro.
- Added a `bevy_reflect::impl_type_path` for implementing `TypePath` on
internal and foreign types in `bevy_reflect`.
- Changed `bevy_reflect::utility::(Non)GenericTypeInfoCell` to
`(Non)GenericTypedCell<T>` which allows us to be generic over both
`TypeInfo` and `TypePath`.
- `TypePath` is now a supertrait of `Asset`, `Material` and
`Material2d`.
- `impl_reflect_struct` needs a `#[type_path = "..."]` attribute to be
specified.
- `impl_reflect_value` needs to either specify path starting with a
double colon (`::core::option::Option`) or an `in my_crate::foo`
declaration.
- Added `bevy_reflect_derive::ReflectTypePath`.
- Most uses of `Ident` in `bevy_reflect_derive` changed to use
`ReflectTypePath`.

## Migration Guide

- Implementors of `Asset`, `Material` and `Material2d` now also need to
derive `TypePath`.
- Manual implementors of `Reflect` will need to implement the new
`get_type_path` method.

## Open Questions
- [x] ~This PR currently does not migrate any usages of
`std::any::type_name` to use `bevy_reflect::TypePath` to ease the review
process. Should it?~ Migration will be left to a follow-up PR.
- [ ] This PR adds a lot of `#[derive(TypePath)]` and `T: TypePath` to
satisfy new bounds, mostly when deriving `TypeUuid`. Should we make
`TypePath` a supertrait of `TypeUuid`? [Should we remove `TypeUuid` in
favour of
`TypePath`?](2afbd85532 (r961067892))
2023-06-05 20:31:20 +00:00
Alice Cecile
cbd4abf0fc
Rename apply_system_buffers to apply_deferred (#8726)
# Objective

- `apply_system_buffers` is an unhelpful name: it introduces a new
internal-only concept
- this is particularly rough for beginners as reasoning about how
commands work is a critical stumbling block

## Solution

- rename `apply_system_buffers` to the more descriptive `apply_deferred`
- rename related fields, arguments and methods in the internals fo
bevy_ecs for consistency
- update the docs


## Changelog

`apply_system_buffers` has been renamed to `apply_deferred`, to more
clearly communicate its intent and relation to `Deferred` system
parameters like `Commands`.

## Migration Guide

- `apply_system_buffers` has been renamed to `apply_deferred`
- the `apply_system_buffers` method on the `System` trait has been
renamed to `apply_deferred`
- the `is_apply_system_buffers` function has been replaced by
`is_apply_deferred`
- `Executor::set_apply_final_buffers` is now
`Executor::set_apply_final_deferred`
- `Schedule::apply_system_buffers` is now `Schedule::apply_deferred`

---------

Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
2023-06-02 14:04:13 +00:00
François
bea7fd1c0b
update bitflags to 2.3 (#8728)
# Objective

- Update bitflags to 2.3
2023-06-01 08:41:42 +00:00
Marco Buono
292e069bb5
Apply codebase changes in preparation for StandardMaterial transmission (#8704)
# Objective

- Make #8015 easier to review;

## Solution

- This commit contains changes not directly related to transmission
required by #8015, in easier-to-review, one-change-per-commit form.

---

## Changelog

### Fixed

- Clear motion vector prepass using `0.0` instead of `1.0`, to avoid TAA
artifacts on transparent objects against the background;

### Added

- The `E` mathematical constant is now available for use in shaders,
exposed under `bevy_pbr::utils`;
- A new `TAA` shader def is now available, for conditionally enabling
shader logic via `#ifdef` when TAA is enabled; (e.g. for jittering
texture samples)
- A new `FallbackImageZero` resource is introduced, for when a fallback
image filled with zeroes is required;
- A new `RenderPhase<I>::render_range()` method is introduced, for
render phases that need to render their items in multiple parceled out
“steps”;

### Changed

- The `MainTargetTextures` struct now holds both `Texture` and
`TextureViews` for the main textures;
- The fog shader functions under `bevy_pbr::fog` now take the a `Fog`
structure as their first argument, instead of relying on the global
`fog` uniform;
- The main textures can now be used as copy sources;

## Migration Guide

- `ViewTarget::main_texture()` and `ViewTarget::main_texture_other()`
now return `&Texture` instead of `&TextureView`. If you were relying on
these methods, replace your usage with
`ViewTarget::main_texture_view()`and
`ViewTarget::main_texture_other_view()`, respectively;
- `ViewTarget::sampled_main_texture()` now returns `Option<&Texture>`
instead of a `Option<&TextureView>`. If you were relying on this method,
replace your usage with `ViewTarget::sampled_main_texture_view()`;
- The `apply_fog()`, `linear_fog()`, `exponential_fog()`,
`exponential_squared_fog()` and `atmospheric_fog()` functions now take a
configurable `Fog` struct. If you were relying on them, update your
usage by adding the global `fog` uniform as their first argument;
2023-05-30 14:21:53 +00:00
Marco Buono
4465f256eb
Add MAY_DISCARD shader def, enabling early depth tests for most cases (#6697)
# Objective

- Right now we can't really benefit from [early depth
testing](https://www.khronos.org/opengl/wiki/Early_Fragment_Test) in our
PBR shader because it includes codepaths with `discard`, even for
situations where they are not necessary.

## Solution

- This PR introduces a new `MeshPipelineKey` and shader def,
`MAY_DISCARD`;
- All possible material/mesh options that that may result in `discard`s
being needed must set `MAY_DISCARD` ahead of time:
- Right now, this is only `AlphaMode::Mask(f32)`, but in the future
might include other options/effects; (e.g. one effect I'm personally
interested in is bayer dither pseudo-transparency for LOD transitions of
opaque meshes)
- Shader codepaths that can `discard` are guarded by an `#ifdef
MAY_DISCARD` preprocessor directive:
  - Right now, this is just one branch in `alpha_discard()`;
- If `MAY_DISCARD` is _not_ set, the `@early_depth_test` attribute is
added to the PBR fragment shader. This is a not yet documented, possibly
non-standard WGSL extension I found browsing Naga's source code. [I
opened a PR to document it
there](https://github.com/gfx-rs/naga/pull/2132). My understanding is
that for backends where this attribute is supported, it will force an
explicit opt-in to early depth test. (e.g. via
`layout(early_fragment_tests) in;` in GLSL)

## Caveats

- I included `@early_depth_test` for the sake of us being explicit, and
avoiding the need for the driver to be “smart” about enabling this
feature. That way, if we make a mistake and include a `discard`
unguarded by `MAY_DISCARD`, it will either produce errors or noticeable
visual artifacts so that we'll catch early, instead of causing a
performance regression.
- I'm not sure explicit early depth test is supported on the naga Metal
backend, which is what I'm currently using, so I can't really test the
explicit early depth test enable, I would like others with Vulkan/GL
hardware to test it if possible;
- I would like some guidance on how to measure/verify the performance
benefits of this;
- If I understand it correctly, this, or _something like this_ is needed
to fully reap the performance gains enabled by #6284;
- This will _most definitely_ conflict with #6284 and #6644. I can fix
the conflicts as needed, depending on whether/the order they end up
being merging in.

---

## Changelog

### Changed

- Early depth tests are now enabled whenever possible for meshes using
`StandardMaterial`, reducing the number of fragments evaluated for
scenes with lots of occlusions.
2023-05-29 15:15:01 +00:00
François
71842c5ac9
Webgpu support (#8336)
# Objective

- Support WebGPU
- alternative to #5027 that doesn't need any async / await
- fixes #8315 
- Surprise fix #7318

## Solution

### For async renderer initialisation 

- Update the plugin lifecycle:
  - app builds the plugin
    - calls `plugin.build`
    - registers the plugin
  - app starts the event loop
- event loop waits for `ready` of all registered plugins in the same
order
    - returns `true` by default
- then call all `finish` then all `cleanup` in the same order as
registered
  - then execute the schedule

In the case of the renderer, to avoid anything async:
- building the renderer plugin creates a detached task that will send
back the initialised renderer through a mutex in a resource
- `ready` will wait for the renderer to be present in the resource
- `finish` will take that renderer and place it in the expected
resources by other plugins
- other plugins (that expect the renderer to be available) `finish` are
called and they are able to set up their pipelines
- `cleanup` is called, only custom one is still for pipeline rendering

### For WebGPU support

- update the `build-wasm-example` script to support passing `--api
webgpu` that will build the example with WebGPU support
- feature for webgl2 was always enabled when building for wasm. it's now
in the default feature list and enabled on all platforms, so check for
this feature must also check that the target_arch is `wasm32`

---

## Migration Guide

- `Plugin::setup` has been renamed `Plugin::cleanup`
- `Plugin::finish` has been added, and plugins adding pipelines should
do it in this function instead of `Plugin::build`
```rust
// Before
impl Plugin for MyPlugin {
    fn build(&self, app: &mut App) {
        app.insert_resource::<MyResource>
            .add_systems(Update, my_system);

        let render_app = match app.get_sub_app_mut(RenderApp) {
            Ok(render_app) => render_app,
            Err(_) => return,
        };

        render_app
            .init_resource::<RenderResourceNeedingDevice>()
            .init_resource::<OtherRenderResource>();
    }
}

// After
impl Plugin for MyPlugin {
    fn build(&self, app: &mut App) {
        app.insert_resource::<MyResource>
            .add_systems(Update, my_system);
    
        let render_app = match app.get_sub_app_mut(RenderApp) {
            Ok(render_app) => render_app,
            Err(_) => return,
        };
    
        render_app
            .init_resource::<OtherRenderResource>();
    }

    fn finish(&self, app: &mut App) {
        let render_app = match app.get_sub_app_mut(RenderApp) {
            Ok(render_app) => render_app,
            Err(_) => return,
        };
    
        render_app
            .init_resource::<RenderResourceNeedingDevice>();
    }
}
```
2023-05-04 22:07:57 +00:00
Airing
4d54ce14aa
Updated to wgpu 0.16.0, wgpu-hal 0.16.0 and naga 0.12.0 (#8446)
# Objective

- Updated to wgpu 0.16.0 and wgpu-hal 0.16.0

---

## Changelog

1. Upgrade wgpu to 0.16.0 and  wgpu-hal to 0.16.0
2. Fix the error in native when using a filterable
`TextureSampleType::Float` on a multisample `BindingType::Texture`.
([https://github.com/gfx-rs/wgpu/pull/3686](https://github.com/gfx-rs/wgpu/pull/3686))

---------

Co-authored-by: François <mockersf@gmail.com>
2023-04-26 15:34:23 +00:00
IceSentry
3f6367d584
Handle vertex_uvs if they are present in default prepass fragment shader (#8330)
# Objective

- Enabling AlphaMode::Opaque in the shader_prepass example crashes. The
issue seems to be that enabling opaque also generates vertex_uvs

Fixes https://github.com/bevyengine/bevy/issues/8273

## Solution

- Use the vertex_uvs in the shader if they are present
2023-04-23 08:07:15 +00:00
ira
6b774c0fda
Compute vertex_count for indexed meshes on GpuMesh (#8460)
# Objective

Compute the `vertex_count` for indexed meshes as well as non-indexed
meshes.

I will need this in a future PR based on #8427 that adds a gizmo
component that draws the normals of a mesh when attached to an entity
([branch](https://github.com/devil-ira/bevy/compare/instanced-line-rendering...devil-ira:bevy:instanced-line-rendering-normals)).

<details><summary>Example image</summary>
<p>


![image](https://user-images.githubusercontent.com/29694403/233789526-cb5feb47-0aa7-4e69-90a2-e31ec24aadff.png)

</p>
</details> 

## Solution

Move `vertex_count` field from `GpuBufferInfo::NonIndexed` to `GpuMesh`

## Migration Guide

`vertex_count` is now stored directly on `GpuMesh` instead of
`GpuBufferInfo::NonIndexed`.
2023-04-22 17:28:58 +00:00
Robert Swain
d8102a0a04
bevy_pbr: Do not cull meshes without Aabbs from cascades (#8444)
# Objective

- Mesh entities should cast shadows when not having Aabbs and having
NoFrustumCulling
- Fixes #8442 

## Solution

- Mesh entities with NoFrustumCulling get no automatic Aabbs added
- Point and spot lights do not cull mesh entities for their shadow
mapping if they do not have an Aabb, but directional lights do
- Make directional lights not cull mesh entities from cascades if the do
not have Aabbs. So no Aabb as a consequence of a NoFrustumCulling
component will mean that those mesh entities are not culled and so are
visible to the light.

---

## Changelog

- Fixed: Mesh entities with NoFrustumCulling will cast shadows for
directional light shadow maps
2023-04-20 01:43:24 +00:00
Nicola Papale
c488b7089c
Fix pbr shader breaking on missing UVs (#8412)
# Objective

Fix #8409

Since `in` doesn't have a `uv` field when `VERTEX_UVS` is not defined,
it shouldn't be accessed outside of related `#ifdef`s
2023-04-17 06:22:34 +00:00
Nicola Papale
8df014fbaf
Add parallax mapping to bevy PBR (#5928)
# Objective

Add a [parallax mapping] shader to bevy. Please note that
this is a 3d technique, NOT a 2d sidescroller feature.

## Solution

- Add related fields to `StandardMaterial`
- update the pbr shader
- Add an example taking advantage of parallax mapping

A pre-existing implementation exists at:
https://github.com/nicopap/bevy_mod_paramap/

The implementation is derived from:

https://web.archive.org/web/20150419215321/http://sunandblackcat.com/tipFullView.php?l=eng&topicid=28

Further discussion on literature is found in the `bevy_mod_paramap`
README.

### Limitations

- The mesh silhouette isn't affected by the depth map.
- The depth of the pixel does not reflect its visual position, resulting
  in artifacts for depth-dependent features such as fog or SSAO
- GLTF does not define a height map texture, so somehow the user will
  always need to work around this limitation, though [an extension is in
  the works][gltf]

### Future work

- It's possible to update the depth in the depth buffer to follow the
  parallaxed texture. This would enable interop with depth-based
  visual effects, it also allows `discard`ing pixels of materials when
  computed depth is higher than the one in depth buffer
- Cheap lower quality single-sample method using [offset limiting]
- Add distance fading, to disable parallaxing (relatively expensive)
  on distant objects
- GLTF extension to allow defining height maps. Or a workaround
  implemented through a blender plugin to the GLTF exporter that
  uses the `extras` field to add height map.
- [Quadratic surface vertex attributes][oliveira_3] to enable parallax
  mapping on bending surfaces and allow clean silhouetting.
- noise based sampling, to limit the pancake artifacts.
- Cone mapping ([GPU gems], [Simcity (2013)][simcity]). Requires
  preprocessing, increase depth map size, reduces sample count greatly.
- [Quadtree parallax mapping][qpm] (also requires preprocessing)
- Self-shadowing of parallax-mapped surfaces by modifying the shadow map
- Generate depth map from normal map [link to slides], [blender
question]


https://user-images.githubusercontent.com/26321040/223563792-dffcc6ab-70e8-4ff9-90d1-b36c338695ad.mp4

[blender question]:
https://blender.stackexchange.com/questions/89278/how-to-get-a-smooth-curvature-map-from-a-normal-map
[link to slides]:
https://developer.download.nvidia.com/assets/gamedev/docs/nmap2displacement.pdf
[oliveira_3]:
https://www.inf.ufrgs.br/~oliveira/pubs_files/Oliveira_Policarpo_RP-351_Jan_2005.pdf
[GPU gems]:
https://developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-18-relaxed-cone-stepping-relief-mapping
[simcity]:
https://community.simtropolis.com/omnibus/other-games/building-and-rendering-simcity-2013-r247/
[offset limiting]:
https://raw.githubusercontent.com/marcusstenbeck/tncg14-parallax-mapping/master/documents/Parallax%20Mapping%20with%20Offset%20Limiting%20-%20A%20Per-Pixel%20Approximation%20of%20Uneven%20Surfaces.pdf
[gltf]: https://github.com/KhronosGroup/glTF/pull/2196
[qpm]:
https://www.gamedevs.org/uploads/quadtree-displacement-mapping-with-height-blending.pdf

---

## Changelog

- Add a `depth_map` field to the `StandardMaterial`, it is a grayscale
  image where white represents bottom and black the top. If `depth_map`
  is set, bevy's pbr shader will use it to do [parallax mapping] to
  give an increased feel of depth to the material. This is similar to a
  displacement map, but with infinite precision at fairly low cost.
- The fields `parallax_mapping_method`, `parallax_depth_scale` and
  `max_parallax_layer_count` allow finer grained control over the
  behavior of the parallax shader.
- Add the `parallax_mapping` example to show off the effect.

[parallax mapping]: https://en.wikipedia.org/wiki/Parallax_mapping

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
2023-04-15 10:25:14 +00:00
Jannik Obermann
d47bb3e6e9
Sync pbr_types.wgsl StandardMaterial values (#8380)
# Objective

The default StandardMaterial values of `pbr_material.rs` and
`pbr_types.wgsl` are out of sync.
I think they are out of sync since
https://github.com/bevyengine/bevy/pull/7664.

## Solution

Adapt the values: `metallic = 0.0`, `perceptual_roughness = 0.5`.
2023-04-14 05:52:57 +00:00
Mikkel Rasmussen
e9312254d8
Non-breaking change* from UK spellings to US (#8291)
Fixes issue mentioned in PR #8285.

_Note: By mistake, this is currently dependent on #8285_
# Objective

Ensure consistency in the spelling of the documentation.

Exceptions:
`crates/bevy_mikktspace/src/generated.rs` - Has not been changed from
licence to license as it is part of a licensing agreement.

Maybe for further consistency,
https://github.com/bevyengine/bevy-website should also be given a look.

## Solution

### Changed the spelling of the current words (UK/CN/AU -> US) :
cancelled -> canceled (Breaking API changes in #8285)
behaviour -> behavior (Breaking API changes in #8285)
neighbour -> neighbor
grey -> gray
recognise -> recognize
centre -> center
metres -> meters
colour -> color

### ~~Update [`engine_style_guide.md`]~~ Moved to #8324 

---

## Changelog

Changed UK spellings in documentation to US

## Migration Guide

Non-breaking changes*

\* If merged after #8285
2023-04-08 16:22:46 +00:00
JoJoJet
3ead10a3e0
Suppress the clippy::type_complexity lint (#8313)
# Objective

The clippy lint `type_complexity` is known not to play well with bevy.
It frequently triggers when writing complex queries, and taking the
lint's advice of using a type alias almost always just obfuscates the
code with no benefit. Because of this, this lint is currently ignored in
CI, but unfortunately it still shows up when viewing bevy code in an
IDE.

As someone who's made a fair amount of pull requests to this repo, I
will say that this issue has been a consistent thorn in my side. Since
bevy code is filled with spurious, ignorable warnings, it can be very
difficult to spot the *real* warnings that must be fixed -- most of the
time I just ignore all warnings, only to later find out that one of them
was real after I'm done when CI runs.

## Solution

Suppress this lint in all bevy crates. This was previously attempted in
#7050, but the review process ended up making it more complicated than
it needs to be and landed on a subpar solution.

The discussion in https://github.com/rust-lang/rust-clippy/pull/10571
explores some better long-term solutions to this problem. Since there is
no timeline on when these solutions may land, we should resolve this
issue in the meantime by locally suppressing these lints.

### Unresolved issues

Currently, these lints are not suppressed in our examples, since that
would require suppressing the lint in every single source file. They are
still ignored in CI.
2023-04-06 21:27:36 +00:00
JMS55
f0f5d79917
Built-in skybox (#8275)
# Objective

- Closes https://github.com/bevyengine/bevy/issues/8008

## Solution

- Add a skybox plugin that renders a fullscreen triangle, and then
modifies the vertices in a vertex shader to enforce that it renders as a
skybox background.
- Skybox is run at the end of MainOpaquePass3dNode.
- In the future, it would be nice to get something like bevy_atmosphere
built-in, and have a default skybox+environment map light.

---

## Changelog

- Added `Skybox`.
- `EnvironmentMapLight` now renders in the correct orientation.

## Migration Guide
- Flip `EnvironmentMapLight` maps if needed to match how they previously
rendered (which was backwards).

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
2023-04-02 10:57:12 +00:00
IceSentry
0859f675c3
Use the prepass normal texture in main pass when possible (#8231)
# Objective

- We support enabling a normal prepass, but the main pass never actually
uses it and recomputes the normals in the main pass. This isn't ideal
since it's doing redundant work.

## Solution

- Use the normal texture from the prepass in the main pass

## Notes

~~I used `NORMAL_PREPASS_ENABLED` as a shader_def because
`NORMAL_PREPASS` is currently used to signify that it is running in the
prepass while this shader_def need to indicate the prepass is done and
the normal prepass was ran before. I'm not sure if there's a better way
to name this.~~
2023-03-29 18:04:40 +00:00
James O'Brien
ae31361949
Split opaque and transparent phases (#8090)
# Objective

Fixes #8089. 

## Solution

Splits the MainPass3dNode into 2 nodes, one for the opaque + alpha
passes and one for the transparent pass.

---

## Changelog
- Split MainPass3dNode into MainOpaquePass3dNode and
MainTransparentPass3dNode
- Combine opaque and alpha phases in MainOpaquePass3dNode into one pass
- Create `START_MAIN_PASS` and `END_MAIN_PASS` empty nodes as labels
- Main pass becomes `START_MAIN_PASS -> MAIN_OPAQUE_PASS ->
MAIN_TRANSPARENT_PASS -> END_MAIN_PASS`

## Migration Guide

Nodes that previously added edges involving `MAIN_PASS` should now add
edges to or from `START_MAIN_PASS` or `END_MAIN_PASS` respectively.
2023-03-28 06:35:16 +00:00
JMS55
53667dea56
Temporal Antialiasing (TAA) (#7291)
![image](https://user-images.githubusercontent.com/47158642/214374911-412f0986-3927-4f7a-9a6c-413bdee6b389.png)

# Objective

- Implement an alternative antialias technique
- TAA scales based off of view resolution, not geometry complexity
- TAA filters textures, firefly pixels, and other aliasing not covered
by MSAA
- TAA additionally will reduce noise / increase quality in future
stochastic rendering techniques
- Closes https://github.com/bevyengine/bevy/issues/3663

## Solution

- Add a temporal jitter component
- Add a motion vector prepass
- Add a TemporalAntialias component and plugin
- Combine existing MSAA and FXAA examples and add TAA

## Followup Work
- Prepass motion vector support for skinned meshes
- Move uniforms needed for motion vectors into a separate bind group,
instead of using different bind group layouts
- Reuse previous frame's GPU view buffer for motion vectors, instead of
recomputing
- Mip biasing for sharper textures, and or unjitter texture UVs
https://github.com/bevyengine/bevy/issues/7323
- Compute shader for better performance
- Investigate FSR techniques
  - Historical depth based disocclusion tests, for geometry disocclusion
  - Historical luminance/hue based tests, for shading disocclusion
- Pixel "locks" to reduce blending rate / revamp history confidence
mechanism
- Orthographic camera support for TemporalJitter
- Figure out COD's 1-tap bicubic filter

---

## Changelog

- Added MotionVectorPrepass and TemporalJitter
- Added TemporalAntialiasPlugin, TemporalAntialiasBundle, and
TemporalAntialiasSettings

---------

Co-authored-by: IceSentry <c.giguere42@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: Daniel Chia <danstryder@gmail.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
Co-authored-by: Brandon Dyer <brandondyer64@gmail.com>
Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-03-27 22:22:40 +00:00