Commit graph

494 commits

Author SHA1 Message Date
Olle Lukowski
6b9cd57956
Introduce AspectRatio struct (#10368)
# Objective

- Fix an inconsistency in the calculation of aspect ratio's. 
- Fixes #10288 

## Solution

- Created an intermediate `AspectRatio` struct, as suggested in the
issue. This is currently just used in any places where aspect ratio
calculations happen, to prevent doing it wrong. In my and @mamekoro 's
opinion, it would be better if this was used instead of a normal `f32`
in various places, but I didn't want to make too many changes to begin
with.

## Migration Guide
- Anywhere where you are currently expecting a f32 when getting aspect
ratios, you will now receive a `AspectRatio` struct. this still holds
the same value.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-12-17 02:01:26 +00:00
Torstein Grindvik
16c5a4b7cd
Fix BindingType import warning (#10818)
# Objective

Fix this warning

```
warning: unused import: `BindingType`
  --> ...bevy/crates/bevy_pbr/src/render/mesh_view_bindings.rs:23:88
   |
23 |         BindGroup, BindGroupLayout, BindGroupLayoutEntry, BindGroupLayoutEntryBuilder, BindingType,
   |                                                                                        ^^^^^^^^^^^
   |
   = note: `#[warn(unused_imports)]` on by default
```

## Solution

- Import via globstar

Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
2023-12-14 18:48:20 +00:00
Mike
6b84ba97a3
Auto insert sync points (#9822)
# Objective

- Users are often confused when their command effects are not visible in
the next system. This PR auto inserts sync points if there are deferred
buffers on a system and there are dependents on that system (systems
with after relationships).
- Manual sync points can lead to users adding more than needed and it's
hard for the user to have a global understanding of their system graph
to know which sync points can be merged. However we can easily calculate
which sync points can be merged automatically.

## Solution

1. Add new edge types to allow opting out of new behavior
2. Insert an sync point for each edge whose initial node has deferred
system params.
3. Reuse nodes if they're at the number of sync points away.

* add opt outs for specific edges with `after_ignore_deferred`,
`before_ignore_deferred` and `chain_ignore_deferred`. The
`auto_insert_apply_deferred` boolean on `ScheduleBuildSettings` can be
set to false to opt out for the whole schedule.

## Perf
This has a small negative effect on schedule build times.
```text
group                                           auto-sync                              main-for-auto-sync
-----                                           -----------                            ------------------
build_schedule/1000_schedule                    1.06       2.8±0.15s        ? ?/sec    1.00       2.7±0.06s        ? ?/sec
build_schedule/1000_schedule_noconstraints      1.01     26.2±0.88ms        ? ?/sec    1.00     25.8±0.36ms        ? ?/sec
build_schedule/100_schedule                     1.02     13.1±0.33ms        ? ?/sec    1.00     12.9±0.28ms        ? ?/sec
build_schedule/100_schedule_noconstraints       1.08   505.3±29.30µs        ? ?/sec    1.00   469.4±12.48µs        ? ?/sec
build_schedule/500_schedule                     1.00    485.5±6.29ms        ? ?/sec    1.00    485.5±9.80ms        ? ?/sec
build_schedule/500_schedule_noconstraints       1.00      6.8±0.10ms        ? ?/sec    1.02      6.9±0.16ms        ? ?/sec
```
---

## Changelog

- Auto insert sync points and added `after_ignore_deferred`,
`before_ignore_deferred`, `chain_no_deferred` and
`auto_insert_apply_deferred` APIs to opt out of this behavior

## Migration Guide

- `apply_deferred` points are added automatically when there is ordering
relationship with a system that has deferred parameters like `Commands`.
If you want to opt out of this you can switch from `after`, `before`,
and `chain` to the corresponding `ignore_deferred` API,
`after_ignore_deferred`, `before_ignore_deferred` or
`chain_ignore_deferred` for your system/set ordering.
- You can also set `ScheduleBuildSettings::auto_insert_sync_points` to
`false` if you want to do it for the whole schedule. Note that in this
mode you can still add `apply_deferred` points manually.
- For most manual insertions of `apply_deferred` you should remove them
as they cannot be merged with the automatically inserted points and
might reduce parallelizability of the system graph.

## TODO
- [x] remove any apply_deferred used in the engine
- [x] ~~decide if we should deprecate manually using apply_deferred.~~
We'll still allow inserting manual sync points for now for whatever edge
cases users might have.
- [x] Update migration guide
- [x] rerun schedule build benchmarks

---------

Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
2023-12-14 16:34:01 +00:00
Elabajaba
70a592f31a
Update to wgpu 0.18 (#10266)
# Objective

Keep up to date with wgpu.

## Solution

Update the wgpu version.

Currently blocked on naga_oil updating to naga 0.14 and releasing a new
version.

3d scenes (or maybe any scene with lighting?) currently don't render
anything due to
```
error: naga_oil bug, please file a report: composer failed to build a valid header: Type [2] '' is invalid
 = Capability Capabilities(CUBE_ARRAY_TEXTURES) is required
 ```

I'm not sure what should be passed in for `wgpu::InstanceFlags`, or if we want to make the gles3minorversion configurable (might be useful for debugging?)

Currently blocked on https://github.com/bevyengine/naga_oil/pull/63, and https://github.com/gfx-rs/wgpu/issues/4569 to be fixed upstream in wgpu first.

## Known issues

Amd+windows+vulkan has issues with texture_binding_arrays (see the image [here](https://github.com/bevyengine/bevy/pull/10266#issuecomment-1819946278)), but that'll be fixed in the next wgpu/naga version, and you can just use dx12 as a workaround for now (Amd+linux mesa+vulkan texture_binding_arrays are fixed though).

---

## Changelog

Updated wgpu to 0.18, naga to 0.14.2, and naga_oil to 0.11.
- Windows desktop GL should now be less painful as it no longer requires Angle.
- You can now toggle shader validation and debug information for debug and release builds using `WgpuSettings.instance_flags` and [InstanceFlags](https://docs.rs/wgpu/0.18.0/wgpu/struct.InstanceFlags.html)

## Migration Guide

- `RenderPassDescriptor` `color_attachments`  (as well as `RenderPassColorAttachment`, and `RenderPassDepthStencilAttachment`) now use `StoreOp::Store` or `StoreOp::Discard` instead of a `boolean` to declare whether or not they should be stored.
- `RenderPassDescriptor` now have `timestamp_writes` and `occlusion_query_set` fields. These can safely be set to `None`.
- `ComputePassDescriptor` now have a `timestamp_writes` field. This can be set to `None` for now.
- See the [wgpu changelog](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v0180-2023-10-25) for additional details
2023-12-14 02:45:47 +00:00
Mantas
5af2f022d8
Rename WorldQueryData & WorldQueryFilter to QueryData & QueryFilter (#10779)
# Rename `WorldQueryData` & `WorldQueryFilter` to `QueryData` &
`QueryFilter`

Fixes #10776 

## Solution

Traits `WorldQueryData` & `WorldQueryFilter` were renamed to `QueryData`
and `QueryFilter`, respectively. Related Trait types were also renamed.

---

## Changelog

- Trait `WorldQueryData` has been renamed to `QueryData`. Derive macro's
`QueryData` attribute `world_query_data` has been renamed to
`query_data`.
- Trait `WorldQueryFilter` has been renamed to `QueryFilter`. Derive
macro's `QueryFilter` attribute `world_query_filter` has been renamed to
`query_filter`.
- Trait's `ExtractComponent` type `Query` has been renamed to `Data`.
- Trait's `GetBatchData` types `Query` & `QueryFilter` has been renamed
to `Data` & `Filter`, respectively.
- Trait's `ExtractInstance` type `Query` has been renamed to `Data`.
- Trait's `ViewNode` type `ViewQuery` has been renamed to `ViewData`.
- Trait's `RenderCommand` types `ViewWorldQuery` & `ItemWorldQuery` has
been renamed to `ViewData` & `ItemData`, respectively.

## Migration Guide

Note: if merged before 0.13 is released, this should instead modify the
migration guide of #10776 with the updated names.

- Rename `WorldQueryData` & `WorldQueryFilter` trait usages to
`QueryData` & `QueryFilter` and their respective derive macro attributes
`world_query_data` & `world_query_filter` to `query_data` &
`query_filter`.
- Rename the following trait type usages:
  - Trait's `ExtractComponent` type `Query` to `Data`.
  - Trait's `GetBatchData` type `Query` to `Data`.
  - Trait's `ExtractInstance` type `Query` to `Data`.
  - Trait's `ViewNode` type `ViewQuery` to `ViewData`'
- Trait's `RenderCommand` types `ViewWolrdQuery` & `ItemWorldQuery` to
`ViewData` & `ItemData`, respectively.

```rust
// Before
#[derive(WorldQueryData)]
#[world_query_data(derive(Debug))]
struct EmptyQuery {
    empty: (),
}

// After
#[derive(QueryData)]
#[query_data(derive(Debug))]
struct EmptyQuery {
    empty: (),
}

// Before
#[derive(WorldQueryFilter)]
struct CustomQueryFilter<T: Component, P: Component> {
    _c: With<ComponentC>,
    _d: With<ComponentD>,
    _or: Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
    _generic_tuple: (With<T>, With<P>),
}

// After
#[derive(QueryFilter)]
struct CustomQueryFilter<T: Component, P: Component> {
    _c: With<ComponentC>,
    _d: With<ComponentD>,
    _or: Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
    _generic_tuple: (With<T>, With<P>),
}

// Before
impl ExtractComponent for ContrastAdaptiveSharpeningSettings {
    type Query = &'static Self;
    type Filter = With<Camera>;
    type Out = (DenoiseCAS, CASUniform);

    fn extract_component(item: QueryItem<Self::Query>) -> Option<Self::Out> {
        //...
    }
}

// After
impl ExtractComponent for ContrastAdaptiveSharpeningSettings {
    type Data = &'static Self;
    type Filter = With<Camera>;
    type Out = (DenoiseCAS, CASUniform);

    fn extract_component(item: QueryItem<Self::Data>) -> Option<Self::Out> {
        //...
    }
}

// Before
impl GetBatchData for MeshPipeline {
    type Param = SRes<RenderMeshInstances>;
    type Query = Entity;
    type QueryFilter = With<Mesh3d>;
    type CompareData = (MaterialBindGroupId, AssetId<Mesh>);
    type BufferData = MeshUniform;

    fn get_batch_data(
        mesh_instances: &SystemParamItem<Self::Param>,
        entity: &QueryItem<Self::Query>,
    ) -> (Self::BufferData, Option<Self::CompareData>) {
        // ....
    }
}

// After
impl GetBatchData for MeshPipeline {
    type Param = SRes<RenderMeshInstances>;
    type Data = Entity;
    type Filter = With<Mesh3d>;
    type CompareData = (MaterialBindGroupId, AssetId<Mesh>);
    type BufferData = MeshUniform;

    fn get_batch_data(
        mesh_instances: &SystemParamItem<Self::Param>,
        entity: &QueryItem<Self::Data>,
    ) -> (Self::BufferData, Option<Self::CompareData>) {
        // ....
    }
}

// Before
impl<A> ExtractInstance for AssetId<A>
where
    A: Asset,
{
    type Query = Read<Handle<A>>;
    type Filter = ();

    fn extract(item: QueryItem<'_, Self::Query>) -> Option<Self> {
        Some(item.id())
    }
}

// After
impl<A> ExtractInstance for AssetId<A>
where
    A: Asset,
{
    type Data = Read<Handle<A>>;
    type Filter = ();

    fn extract(item: QueryItem<'_, Self::Data>) -> Option<Self> {
        Some(item.id())
    }
}

// Before
impl ViewNode for PostProcessNode {
    type ViewQuery = (
        &'static ViewTarget,
        &'static PostProcessSettings,
    );

    fn run(
        &self,
        _graph: &mut RenderGraphContext,
        render_context: &mut RenderContext,
        (view_target, _post_process_settings): QueryItem<Self::ViewQuery>,
        world: &World,
    ) -> Result<(), NodeRunError> {
        // ...
    }
}

// After
impl ViewNode for PostProcessNode {
    type ViewData = (
        &'static ViewTarget,
        &'static PostProcessSettings,
    );

    fn run(
        &self,
        _graph: &mut RenderGraphContext,
        render_context: &mut RenderContext,
        (view_target, _post_process_settings): QueryItem<Self::ViewData>,
        world: &World,
    ) -> Result<(), NodeRunError> {
        // ...
    }
}

// Before
impl<P: CachedRenderPipelinePhaseItem> RenderCommand<P> for SetItemPipeline {
    type Param = SRes<PipelineCache>;
    type ViewWorldQuery = ();
    type ItemWorldQuery = ();
    #[inline]
    fn render<'w>(
        item: &P,
        _view: (),
        _entity: (),
        pipeline_cache: SystemParamItem<'w, '_, Self::Param>,
        pass: &mut TrackedRenderPass<'w>,
    ) -> RenderCommandResult {
        // ...
    }
}

// After
impl<P: CachedRenderPipelinePhaseItem> RenderCommand<P> for SetItemPipeline {
    type Param = SRes<PipelineCache>;
    type ViewData = ();
    type ItemData = ();
    #[inline]
    fn render<'w>(
        item: &P,
        _view: (),
        _entity: (),
        pipeline_cache: SystemParamItem<'w, '_, Self::Param>,
        pass: &mut TrackedRenderPass<'w>,
    ) -> RenderCommandResult {
        // ...
    }
}
```
2023-12-12 19:45:50 +00:00
robtfm
67d92e9b85
light renderlayers (#10742)
# Objective

add `RenderLayers` awareness to lights. lights default to
`RenderLayers::layer(0)`, and must intersect the camera entity's
`RenderLayers` in order to affect the camera's output.

note that lights already use renderlayers to filter meshes for shadow
casting. this adds filtering lights per view based on intersection of
camera layers and light layers.

fixes #3462 

## Solution

PointLights and SpotLights are assigned to individual views in
`assign_lights_to_clusters`, so we simply cull the lights which don't
match the view layers in that function.

DirectionalLights are global, so we 
- add the light layers to the `DirectionalLight` struct
- add the view layers to the `ViewUniform` struct
- check for intersection before processing the light in
`apply_pbr_lighting`

potential issue: when mesh/light layers are smaller than the view layers
weird results can occur. e.g:
camera = layers 1+2
light = layers 1
mesh = layers 2

the mesh does not cast shadows wrt the light as (1 & 2) == 0.
the light affects the view as (1+2 & 1) != 0. 
the view renders the mesh as (1+2 & 2) != 0.

so the mesh is rendered and lit, but does not cast a shadow. 

this could be fixed (so that the light would not affect the mesh in that
view) by adding the light layers to the point and spot light structs,
but i think the setup is pretty unusual, and space is at a premium in
those structs (adding 4 bytes more would reduce the webgl point+spot
light max count to 240 from 256).

I think typical usage is for cameras to have a single layer, and
meshes/lights to maybe have multiple layers to render to e.g. minimaps
as well as primary views.

if there is a good use case for the above setup and we should support
it, please let me know.

---

## Migration Guide

Lights no longer affect all `RenderLayers` by default, now like cameras
and meshes they default to `RenderLayers::layer(0)`. To recover the
previous behaviour and have all lights affect all views, add a
`RenderLayers::all()` component to the light entity.
2023-12-12 19:45:37 +00:00
Joona Aalto
4b1865f8bd
Normalize only nonzero normals for mikktspace normal maps (#10905)
# Objective

Fixes #5891.

For mikktspace normal maps, normals must be renormalized in vertex
shaders to match the way mikktspace bakes vertex tangents and normal
maps so that the exact inverse process is applied when shading.

However, for invalid normals like `vec3<f32>(0.0, 0.0, 0.0)`, this
normalization causes NaN values, and because it's in the vertex shader,
it affects the entire triangle and causes it to be shaded as black:

![incorrectly shaded
cone](https://github.com/bevyengine/bevy/assets/57632562/3334b3a9-f72a-4a08-853e-8077a346f5c9)

*A cone with a tip that has a vertex normal of [0, 0, 0], causing the
mesh to be shaded as black.*

In some cases, normals of zero are actually *useful*. For example, a
smoothly shaded cone without creases requires the apex vertex normal to
be zero, because there is no singular normal that works correctly, so
the apex shouldn't contribute to the overall shading. Duplicate vertices
for the apex fix some shading issues, but it causes visible creases and
is more expensive. See #5891 and #10298 for more details.

For correctly shaded cones and other similar low-density shapes with
sharp tips, vertex normals of zero can not be normalized in the vertex
shader.

## Solution

Only normalize the vertex normals and tangents in the vertex shader if
the normal isn't [0, 0, 0]. This way, mikktspace normal maps should
still work for everything except the zero normals, and the zero normals
will only be normalized in the fragment shader.

This allows us to render cones correctly:

![smooth cone with some
banding](https://github.com/bevyengine/bevy/assets/57632562/6b36e264-22c6-453b-a6de-c404b314ca1a)

Notice how there is still a weird shadow banding effect in one area. I
noticed that it can be fixed by normalizing
[here](d2614f2d80/crates/bevy_pbr/src/render/pbr_functions.wgsl (L51)),
which produces a perfectly smooth cone without duplicate vertices:

![smooth
cone](https://github.com/bevyengine/bevy/assets/57632562/64f9ad5d-b249-4eae-880b-a1e61e07ae73)

I didn't add this change yet, because it seems a bit arbitrary. I can
add it here if that'd be useful or make another PR though.
2023-12-10 11:42:47 +00:00
Elabajaba
0f5d8128c9
Fix prepass binding issues causing crashes when not all prepass bindings are used (#10788)
# Objective

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

## Solution

The bind_group_layout entries for the prepass were wrong when not all 4
prepass textures were used, as it just zipped [17, 18, 19, 20] with the
smallvec of prepass `bind_group_layout` entries that potentially didn't
contain 4 entries. (eg. if you had a depth and motion vector prepass but
no normal prepass, then depth would be correct but the entry for the
motion vector prepass would be 18 (normal prepass' spot) instead of 19).

Change the prepass `get_bind_group_layout_entries` function to return an
array of `[Option<BindGroupLayoutEntryBuilder>; 4]` and only add the
layout entry if it exists.
2023-11-29 23:11:12 +00:00
tygyh
fd308571c4
Remove unnecessary path prefixes (#10749)
# Objective

- Shorten paths by removing unnecessary prefixes

## Solution

- Remove the prefixes from many paths which do not need them. Finding
the paths was done automatically using built-in refactoring tools in
Jetbrains RustRover.
2023-11-28 23:43:40 +00:00
JMS55
4bf20e7d27
Swap material and mesh bind groups (#10485)
# Objective
- Materials should be a more frequent rebind then meshes (due to being
able to use a single vertex buffer, such as in #10164) and therefore
should be in a higher bind group.

---

## Changelog
- For 2d and 3d mesh/material setups (but not UI materials, or other
rendering setups such as gizmos, sprites, or text), mesh data is now in
bind group 1, and material data is now in bind group 2, which is swapped
from how they were before.

## Migration Guide
- Custom 2d and 3d mesh/material shaders should now use bind group 2
`@group(2) @binding(x)` for their bound resources, instead of bind group
1.
- Many internal pieces of rendering code have changed so that mesh data
is now in bind group 1, and material data is now in bind group 2.
Semi-custom rendering setups (that don't use the Material or Material2d
APIs) should adapt to these changes.
2023-11-28 22:26:22 +00:00
robtfm
d95d20f4b1
prepass vertex shader always outputs world position (#10657)
# Objective

the pbr prepass vertex shader currently only sets
`VertexOutput::world_position` when deferred or motion prepasses are
enabled.
the field is always in the vertex output so is otherwise undetermined,
and the calculation is very cheap.

## Solution

always set the world position in the pbr prepass vert shader.
2023-11-28 12:13:28 +00:00
Kanabenki
0e9f6e92ea
Add clippy::manual_let_else at warn level to lints (#10684)
# Objective

Related to #10612.

Enable the
[`clippy::manual_let_else`](https://rust-lang.github.io/rust-clippy/master/#manual_let_else)
lint as a warning. The `let else` form seems more idiomatic to me than a
`match`/`if else` that either match a pattern or diverge, and from the
clippy doc, the lint doesn't seem to have any possible false positive.

## Solution

Add the lint as warning in `Cargo.toml`, refactor places where the lint
triggers.
2023-11-28 04:15:27 +00:00
IceSentry
6d0c11a28f
Bind group layout entries (#10224)
# Objective

- Follow up to #9694

## Solution

- Same api as #9694 but adapted for `BindGroupLayoutEntry`
- Use the same `ShaderStages` visibilty for all entries by default
- Add `BindingType` helper function that mirror the wgsl equivalent and
that make writing layouts much simpler.

Before:
```rust
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
    label: Some("post_process_bind_group_layout"),
    entries: &[
        BindGroupLayoutEntry {
            binding: 0,
            visibility: ShaderStages::FRAGMENT,
            ty: BindingType::Texture {
                sample_type: TextureSampleType::Float { filterable: true },
                view_dimension: TextureViewDimension::D2,
                multisampled: false,
            },
            count: None,
        },
        BindGroupLayoutEntry {
            binding: 1,
            visibility: ShaderStages::FRAGMENT,
            ty: BindingType::Sampler(SamplerBindingType::Filtering),
            count: None,
        },
        BindGroupLayoutEntry {
            binding: 2,
            visibility: ShaderStages::FRAGMENT,
            ty: BindingType::Buffer {
                ty: bevy::render::render_resource::BufferBindingType::Uniform,
                has_dynamic_offset: false,
                min_binding_size: Some(PostProcessSettings::min_size()),
            },
            count: None,
        },
    ],
});
```
After:
```rust
let layout = render_device.create_bind_group_layout(
    "post_process_bind_group_layout"),
    &BindGroupLayoutEntries::sequential(
        ShaderStages::FRAGMENT,
        (
            texture_2d_f32(),
            sampler(SamplerBindingType::Filtering),
            uniform_buffer(false, Some(PostProcessSettings::min_size())),
        ),
    ),
);
```

Here's a more extreme example in bevy_solari:
86dab7f5da

---

## Changelog

- Added `BindGroupLayoutEntries` and all `BindingType` helper functions.

## Migration Guide

`RenderDevice::create_bind_group_layout()` doesn't take a
`BindGroupLayoutDescriptor` anymore. You need to provide the parameters
separately

```rust
// 0.12
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
    label: Some("post_process_bind_group_layout"),
    entries: &[
        BindGroupLayoutEntry {
			// ...
        },
    ],
});

// 0.13
let layout = render_device.create_bind_group_layout(
	"post_process_bind_group_layout",
    &[
        BindGroupLayoutEntry {
			// ...
        },
    ],
);
```

## TODO

- [x] implement a `Dynamic` variant
- [x] update the `RenderDevice::create_bind_group_layout()` api to match
the one from `RenderDevice::creat_bind_group()`
- [x] docs
2023-11-28 04:00:49 +00:00
Carter Anderson
90958104cb
Ensure instance_index push constant is always used in prepass.wgsl (#10706)
# Objective

 Kind of helps #10509 

## Solution

Add a line to `prepass.wgsl` that ensure the `instance_index` push
constant is always used on WebGL 2. This is not a full fix, as the
_second_ a custom shader is used that doesn't use the push constant, the
breakage will resurface. We have satisfying medium term and long term
solutions. This is just a short term hack for 0.12.1 that will make more
cases work. See #10509 for more details.
2023-11-28 01:13:25 +00:00
Torstein Grindvik
4788315fd0
Use as_image_copy where possible (#10733)
# Objective

`wgpu` has a helper method `texture.as_image_copy()` for a common
pattern when making a default-like `ImageCopyTexture` from a texture.

This is used in various places in Bevy for texture copy operations, but
it was not used where `write_texture` is called.

## Solution

- Replace struct `ImageCopyTexture` initialization with
`texture.as_image_copy()` where appropriate

Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
2023-11-26 19:24:32 +00:00
Stepan Koltsov
790fafdbb0
Explain how AmbientLight is inserted and configured (#10712) 2023-11-24 00:07:58 +00:00
robtfm
ea01c3e387
Non uniform transmission samples (#10674)
# Objective

fix webgpu+chrome(119) textureSample in non-uniform control flow error

## Solution

modify view transmission texture sampling to use textureSampleLevel.
there are no mips for the view transmission texture, so this doesn't
change the result, but it removes the need for the samples to be in
uniform control flow.

note: in future we may add a mipchain to the transmission texture to
improve the blur effect. if uniformity analysis hasn't improved, this
would require switching to manual derivative calculations (which is
something we plan to do anyway).
2023-11-22 18:54:45 +00:00
Ame
8c0ce5280b
Standardize toml format with taplo (#10594)
# Objective

- Standardize fmt for toml files

## Solution

- Add [taplo](https://taplo.tamasfe.dev/) to CI (check for fmt and diff
for toml files), for context taplo is used by the most popular extension
in VScode [Even Better
TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml
- Add contribution section to explain toml fmt with taplo.
 
Now to pass CI you need to run `taplo fmt --option indent_string=" "` or
if you use vscode have the `Even Better TOML` extension with 4 spaces
for indent

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-11-21 01:04:14 +00:00
Ame
951c9bb1a2
Add [lints] table, fix adding #![allow(clippy::type_complexity)] everywhere (#10011)
# Objective

- Fix adding `#![allow(clippy::type_complexity)]` everywhere. like #9796

## Solution

- Use the new [lints] table that will land in 1.74
(https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#lints)
- inherit lint to the workspace, crates and examples.
```
[lints]
workspace = true
```

## Changelog

- Bump rust version to 1.74
- Enable lints table for the workspace
```toml
[workspace.lints.clippy]
type_complexity = "allow"
```
- Allow type complexity for all crates and examples
```toml
[lints]
workspace = true
```

---------

Co-authored-by: Martín Maita <47983254+mnmaita@users.noreply.github.com>
2023-11-18 20:58:48 +00:00
BrayMatter
bad55c1ad8
Ensure ExtendedMaterial works with reflection (to enable bevy_egui_inspector integration) (#10548)
# Objective

- Ensure ExtendedMaterial can be referenced in bevy_egui_inspector
correctly

## Solution

Add a more manual `TypePath` implementation to work around bugs in the
derive macro.
2023-11-15 12:48:36 +00:00
Torstein Grindvik
719b30a719
More inactive camera checks (#10555)
# Objective

- Reduce work from inactive cameras

Tracing was done on the `3d_shapes` example on PR
https://github.com/bevyengine/bevy/pull/10543 .
Doing tracing on a "real" application showed more instances of
unnecessary work.

## Solution

- Skip work on inactive cameras

Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
2023-11-14 13:44:42 +00:00
Sludge
39c8998257
Register WireframeColor (#10486)
This makes it usable via reflection by adding its data to the
`TypeRegistry`.
2023-11-12 17:07:15 +00:00
kayh
c98481aa56
Fix bevy_pbr shader function name (#10423)
# Objective

Fix a shader error that happens when using pbr morph targets.

## Solution

Fix the function name in the `prepass.wgsl` shader, which is incorrectly
prefixed with `morph::` (added in
61bad4eb57 (diff-97e4500f0a36bc6206d7b1490c8dd1a69459ee39dc6822eb9b2f7b160865f49fR42)).

This section of the shader is only enabled when using morph targets, so
it seems like there are no tests / examples using it?
2023-11-07 20:04:25 +00:00
github-actions[bot]
bf30a25efc
Release 0.12 (#10362)
Preparing next release
This PR has been auto-generated

---------

Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: François <mockersf@gmail.com>
2023-11-04 17:24:23 +00:00
robtfm
cd594221cf
gate depth reads on !WEBGL2 (#10365)
# Objective

fix #10364 

## Solution

gate depth prepass reads in pbr_transmission.wgsl by `#ifndef WEBGL2`
2023-11-04 02:02:49 +00:00
Sélène Amanita
c376954b87
Make DirectionalLight Cascades computation generic over CameraProjection (#9226)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/9077 (see this issue for
motivations)

## Solution

Implement 1 and 2 of the "How to fix it" section of
https://github.com/bevyengine/bevy/issues/9077

`update_directional_light_cascades` is split into
`clear_directional_light_cascades` and a generic
`build_directional_light_cascades`, to clear once and potentially insert
many times.

---

## Changelog

`DirectionalLight`'s computation is now generic over `CameraProjection`
and can work with custom camera projections.

## Migration Guide

If you have a component `MyCustomProjection` that implements
`CameraProjection`:
- You need to implement a new required associated method,
`get_frustum_corners`, returning an array of the corners of a subset of
the frustum with given `z_near` and `z_far`, in local camera space.
- You can now add the
`build_directional_light_cascades::<MyCustomProjection>` system in
`SimulationLightSystems::UpdateDirectionalLightCascades` after
`clear_directional_light_cascades` for your projection to work with
directional lights.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-11-03 06:07:59 +00:00
Carter Anderson
3ec52c2bdb
Increase default normal bias to avoid common artifacts (#10346)
# Objective

Bevy's default bias values for directional and spot lights currently
cause significant artifacts. We should fix that so shadows look good by
default!

This is a less controversial/invasive alternative to #10188, which might
enable us to keep the default bias value low, but also has its own sets
of concerns and caveats that make it a risky choice for Bevy 0.12.

## Solution

Bump the default normal bias from `0.6` to `1.8`. There is precedent for
values in this general area as Godot has a default normal bias of `2.0`.

### Before


![image](https://github.com/superdump/bevy/assets/2694663/a5828011-33fc-4427-90ed-f093d7389053)

### After


![image](https://github.com/bevyengine/bevy/assets/2694663/0f2b16b0-c116-41ab-9886-1ace9e00efd6)

## Migration Guide

The default `shadow_normal_bias` value for `DirectionalLight` and
`SpotLight` has changed to accommodate artifacts introduced with the new
shadow PCF changes. It is unlikely (especially given the new PCF shadow
behaviors with these values), but you might need to manually tweak this
value if your scene requires a lower bias and it relied on the previous
default value.
2023-11-03 05:44:57 +00:00
robtfm
5cc3352f5b
allow DeferredPrepass to work without other prepass markers (#10223)
# Objective

fix crash / misbehaviour when `DeferredPrepass` is used without
`DepthPrepass`.

- Deferred lighting requires the depth prepass texture to be present, so
that the depth texture is available for binding. without it the deferred
lighting pass will use 0 for depth of all meshes.
- When `DeferredPrepass` is used without other prepass markers, and with
any materials that use `OpaqueRenderMode::Forward`, those entities will
try to queue to the `Opaque3dPrepass` render phase, which doesn't exist,
causing a crash.

## Solution

- check if the prepass phases exist before queueing
- generate prepass textures if `Opaque3dDeferred` is present
- add a note to the DeferredPrepass marker to note that DepthPrepass is
also required by the default deferred lighting pass
- also changed some `With<T>.is_some()`s to `Has<T>`s
2023-11-03 01:09:14 +00:00
Christopher Biscardi
74b5073f75
Make VERTEX_COLORS usable in prepass shader, if available (#10341)
# Objective

I was working with forward rendering prepass fragment shaders and ran
into an issue of not being able to access vertex colors in the prepass.
I was able to access vertex colors in regular fragment shaders as well
as in deferred shaders.

## Solution

It seems like this `if` was nested unintentionally as moving it outside
of the `deferred` block works.

---

## Changelog

Enable vertex colors in forward rendering prepass fragment shaders
2023-11-03 00:54:13 +00:00
François
6f8848a6c2
double sided normals: fix apply_normal_mapping calls (#10330)
# Objective

- After #10326, examples `array_texture`, `ssao` and `shader_prepass`
don't render correctly
```
error: failed to build a valid final module: Entry point fragment at Fragment is invalid
   ┌─ crates/bevy_pbr/src/render/pbr_prepass.wgsl:26:22
   │
26 │           let normal =  evy_pbr::pbr_functions::31mapply_normal_mapping(
   │ ╭──────────────────────^
27 │ │             bevy_pbr::pbr_bindings::material.flags,
28 │ │             world_normal,
29 │ │
   · │
36 │ │
37 │ │             bevy_pbr::mesh_view_bindings::view.mip_bias,
   │ ╰───────────────────────────────────────────────────────────────────────────────────────^ invalid function call
   │
   = Call to [9] is invalid
   = Requires 6 arguments, but 4 are provided

```

## Solution

- fix `apply_normal_mapping` calls
2023-11-01 16:40:25 +00:00
Marco Buono
44928e0df4
StandardMaterial Light Transmission (#8015)
# Objective

<img width="1920" alt="Screenshot 2023-04-26 at 01 07 34"
src="https://user-images.githubusercontent.com/418473/234467578-0f34187b-5863-4ea1-88e9-7a6bb8ce8da3.png">

This PR adds both diffuse and specular light transmission capabilities
to the `StandardMaterial`, with support for screen space refractions.
This enables realistically representing a wide range of real-world
materials, such as:

  - Glass; (Including frosted glass)
  - Transparent and translucent plastics;
  - Various liquids and gels;
  - Gemstones;
  - Marble;
  - Wax;
  - Paper;
  - Leaves;
  - Porcelain.

Unlike existing support for transparency, light transmission does not
rely on fixed function alpha blending, and therefore works with both
`AlphaMode::Opaque` and `AlphaMode::Mask` materials.

## Solution

- Introduces a number of transmission related fields in the
`StandardMaterial`;
- For specular transmission:
- Adds logic to take a view main texture snapshot after the opaque
phase; (in order to perform screen space refractions)
- Introduces a new `Transmissive3d` phase to the renderer, to which all
meshes with `transmission > 0.0` materials are sent.
- Calculates a light exit point (of the approximate mesh volume) using
`ior` and `thickness` properties
- Samples the snapshot texture with an adaptive number of taps across a
`roughness`-controlled radius enabling “blurry” refractions
- For diffuse transmission:
- Approximates transmitted diffuse light by using a second, flipped +
displaced, diffuse-only Lambertian lobe for each light source.

## To Do

- [x] Figure out where `fresnel_mix()` is taking place, if at all, and
where `dielectric_specular` is being calculated, if at all, and update
them to use the `ior` value (Not a blocker, just a nice-to-have for more
correct BSDF)
- To the _best of my knowledge, this is now taking place, after
964340cdd. The fresnel mix is actually "split" into two parts in our
implementation, one `(1 - fresnel(...))` in the transmission, and
`fresnel()` in the light implementations. A surface with more
reflectance now will produce slightly dimmer transmission towards the
grazing angle, as more of the light gets reflected.
- [x] Add `transmission_texture`
- [x] Add `diffuse_transmission_texture`
- [x] Add `thickness_texture`
- [x] Add `attenuation_distance` and `attenuation_color`
- [x] Connect values to glTF loader
  - [x] `transmission` and `transmission_texture`
  - [x] `thickness` and `thickness_texture`
  - [x] `ior`
- [ ] `diffuse_transmission` and `diffuse_transmission_texture` (needs
upstream support in `gltf` crate, not a blocker)
- [x] Add support for multiple screen space refraction “steps”
- [x] Conditionally create no transmission snapshot texture at all if
`steps == 0`
- [x] Conditionally enable/disable screen space refraction transmission
snapshots
- [x] Read from depth pre-pass to prevent refracting pixels in front of
the light exit point
- [x] Use `interleaved_gradient_noise()` function for sampling blur in a
way that benefits from TAA
- [x] Drill down a TAA `#define`, tweak some aspects of the effect
conditionally based on it
- [x] Remove const array that's crashing under HLSL (unless a new `naga`
release with https://github.com/gfx-rs/naga/pull/2496 comes out before
we merge this)
- [ ] Look into alternatives to the `switch` hack for dynamically
indexing the const array (might not be needed, compilers seem to be
decent at expanding it)
- [ ] Add pipeline keys for gating transmission (do we really want/need
this?)
- [x] Tweak some material field/function names?

## A Note on Texture Packing

_This was originally added as a comment to the
`specular_transmission_texture`, `thickness_texture` and
`diffuse_transmission_texture` documentation, I removed it since it was
more confusing than helpful, and will likely be made redundant/will need
to be updated once we have a better infrastructure for preprocessing
assets_

Due to how channels are mapped, you can more efficiently use a single
shared texture image
for configuring the following:

- R - `specular_transmission_texture`
- G - `thickness_texture`
- B - _unused_
- A - `diffuse_transmission_texture`

The `KHR_materials_diffuse_transmission` glTF extension also defines a
`diffuseTransmissionColorTexture`,
that _we don't currently support_. One might choose to pack the
intensity and color textures together,
using RGB for the color and A for the intensity, in which case this
packing advice doesn't really apply.

---

## Changelog

- Added a new `Transmissive3d` render phase for rendering specular
transmissive materials with screen space refractions
- Added rendering support for transmitted environment map light on the
`StandardMaterial` as a fallback for screen space refractions
- Added `diffuse_transmission`, `specular_transmission`, `thickness`,
`ior`, `attenuation_distance` and `attenuation_color` to the
`StandardMaterial`
- Added `diffuse_transmission_texture`, `specular_transmission_texture`,
`thickness_texture` to the `StandardMaterial`, gated behind a new
`pbr_transmission_textures` cargo feature (off by default, for maximum
hardware compatibility)
- Added `Camera3d::screen_space_specular_transmission_steps` for
controlling the number of “layers of transparency” rendered for
transmissive objects
- Added a `TransmittedShadowReceiver` component for enabling shadows in
(diffusely) transmitted light. (disabled by default, as it requires
carefully setting up the `thickness` to avoid self-shadow artifacts)
- Added support for the `KHR_materials_transmission`,
`KHR_materials_ior` and `KHR_materials_volume` glTF extensions
- Renamed items related to temporal jitter for greater consistency

## Migration Guide

- `SsaoPipelineKey::temporal_noise` has been renamed to
`SsaoPipelineKey::temporal_jitter`
- The `TAA` shader def (controlled by the presence of the
`TemporalAntiAliasSettings` component in the camera) has been replaced
with the `TEMPORAL_JITTER` shader def (controlled by the presence of the
`TemporalJitter` component in the camera)
- `MeshPipelineKey::TAA` has been replaced by
`MeshPipelineKey::TEMPORAL_JITTER`
- The `TEMPORAL_NOISE` shader def has been consolidated with
`TEMPORAL_JITTER`
2023-10-31 20:59:02 +00:00
Marco Buono
dc1f76d9a2
Fix handling of double_sided for normal maps (#10326)
# Objective

Right now, we flip the `world_normal` in response to `double_sided &&
!is_front`, however when calculating `N` from tangents and the normal
map, we don't flip the normal read from the normal map, which produces
extremely weird results.

## Solution

- Pass `double_sided` and `is_front` flags to the
`apply_normal_mapping()` function and use them to conditionally flip
`Nt`

## Comparison

Note: These are from a custom scene running with the `transmission`
branch, (#8015) I noticed lighting got pretty weird for the back side of
translucent `double_sided` materials whenever I added a normal map.

### Before

<img width="1392" alt="Screenshot 2023-10-31 at 01 26 06"
src="https://github.com/bevyengine/bevy/assets/418473/d5f8c9c3-aca1-4c2f-854d-f0d0fd2fb19a">

### After

<img width="1392" alt="Screenshot 2023-10-31 at 01 25 42"
src="https://github.com/bevyengine/bevy/assets/418473/fa0e1aa2-19ad-4c27-bb08-37299d97971c">


---

## Changelog

- Fixed a bug where `StandardMaterial::double_sided` would interact
incorrectly with normal maps, producing broken results.
2023-10-31 09:44:40 +00:00
JMS55
b208388af9
Smaller TAA fixes (#10200)
Extracted the easy stuff from #8974 .

# Problem
1. Commands from `update_previous_view_projections` would crash when
matching entities were despawned.
2. `TaaPipelineId` and `draw_3d_graph` module were not public.
3. When the motion vectors pointed to pixels that are now off screen, a
smearing artifact could occur.

# Solution
1. Use `try_insert` command instead.
2. Make them public, renaming to `TemporalAntiAliasPipelineId`.
3. Check for this case, and ignore history for pixels that are
off-screen.
2023-10-27 23:13:14 +00:00
Robert Swain
0f54a82e3b
Fix sampling of diffuse env map texture with non-uniform control flow (#10276)
# Objective

- `deferred_rendering` and `load_gltf` fail in WebGPU builds due to
textureSample() being called on the diffuse environment map texture
after non-uniform control flow

## Solution

- The diffuse environment map texture only has one mip, so use
`textureSampleLevel(..., 0.0)` to sample that mip and not require UV
gradient calculation.
2023-10-27 01:35:19 +00:00
Carter Anderson
134750d18e
Image Sampler Improvements (#10254)
# Objective

- Build on the changes in https://github.com/bevyengine/bevy/pull/9982
- Use `ImageSamplerDescriptor` as the "public image sampler descriptor"
interface in all places (for consistency)
- Make it possible to configure textures to use the "default" sampler
(as configured in the `DefaultImageSampler` resource)
- Fix a bug introduced in #9982 that prevents configured samplers from
being used in Basis, KTX2, and DDS textures

---

## Migration Guide

- When using the `Image` API, use `ImageSamplerDescriptor` instead of
`wgpu::SamplerDescriptor`
- If writing custom wgpu renderer features that work with `Image`, call
`&image_sampler.as_wgpu()` to convert to a wgpu descriptor.
2023-10-26 23:30:09 +00:00
Nicola Papale
66f72dd25b
Use wildcard imports in bevy_pbr (#9847)
# Objective

- the style of import used by bevy guarantees merge conflicts when any
file change
- This is especially true when import lists are large, such as in
`bevy_pbr`
- Merge conflicts are tricky to resolve. This bogs down rendering PRs
and makes contributing to bevy's rendering system more difficult than it
needs to

## Solution

- Use wildcard imports to replace multiline import list in `bevy_pbr`

I suspect this is controversial, but I'd like to hear alternatives.
Because this is one of many papercuts that makes developing render
features near impossible.
2023-10-25 08:40:55 +00:00
François
af37ab51ec
WebGL2: fix import path for unpack_unorm3x4_plus_unorm_20_ (#10251)
# Objective

- Fixes #10250 

```
[Log] ERROR crates/bevy_render/src/render_resource/pipeline_cache.rs:823 failed to process shader: (wasm_example.js, line 376)
error: no definition in scope for identifier: 'bevy_pbr::pbr_deferred_functions::unpack_unorm3x4_plus_unorm_20_'
   ┌─ crates/bevy_pbr/src/deferred/deferred_lighting.wgsl:44:20
   │
44 │     frag_coord.z = bevy_pbr::pbr_deferred_functions::unpack_unorm3x4_plus_unorm_20_(deferred_data.b).w;
   │                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown identifier
   │
   = no definition in scope for identifier: 'bevy_pbr::pbr_deferred_functions::unpack_unorm3x4_plus_unorm_20_'
```

## Solution

- Fix the import path

The "gray" issue is since #9258 on macOS 

... at least they're not white anymore
<img width="1294" alt="Screenshot 2023-10-25 at 00 14 11"
src="https://github.com/bevyengine/bevy/assets/8672791/df1a1138-c26c-4417-9b49-a00fbb8561d7">
2023-10-25 00:18:45 +00:00
Griffin
1bd7e5a8e6
View Transformations (#9726)
# Objective

- Add functions for common view transformations.

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
2023-10-24 21:26:19 +00:00
st0rmbtw
afe8b5f20d
Replace all usages of texture_descritor.size.* with the helper methods (#10227)
# Objective

A follow-up PR for https://github.com/bevyengine/bevy/pull/10221

## Changelog

Replaced usages of texture_descriptor.size with the helper methods of
`Image` through the entire engine codebase
2023-10-23 20:49:02 +00:00
Rafał Harabień
51c70bc98c
Fix fog color being inaccurate (#10226)
# Objective

Fog color was passed to shaders without conversion from sRGB to linear
color space. Because shaders expect colors in linear space this resulted
in wrong color being used. This is most noticeable in open scenes with
dark fog color and clear color set to the same color. In such case
background/clear color (which is properly processed) is going to be
darker than very far objects.

Example:

![image](https://github.com/bevyengine/bevy/assets/160391/89b70d97-b2d0-4bc5-80f4-c9e8b8801c4c)

[bevy-fog-color-bug.zip](https://github.com/bevyengine/bevy/files/13063718/bevy-fog-color-bug.zip)

## Solution

Add missing conversion of fog color to linear color space.

---

## Changelog

* Fixed conversion of fog color

## Migration Guide

- Colors in `FogSettings` struct (`color` and `directional_light_color`)
are now sent to the GPU in linear space. If you were using
`Color::rgb()`/`Color::rgba()` and would like to retain the previous
colors, you can quickly fix it by switching to
`Color::rgb_linear()`/`Color::rgba_linear()`.
2023-10-23 12:45:18 +00:00
Marco Buono
e59085a67f
Use “specular occlusion” term to consistently extinguish fresnel on Ambient and Environment Map lights (#10182)
# Objective

Even at `reflectance == 0.0`, our ambient and environment map light
implementations still produce fresnel/specular highlights.

Such a low `reflectance` value lies outside of the physically possible
range and is already used by our directional, point and spot light
implementations (via the `fresnel()` function) to enable artistic
control, effectively disabling the fresnel "look" for non-physically
realistic materials. Since ambient and environment lights use a
different formulation, they were not honoring this same principle.

This PR aims to bring consistency to all light types, offering the same
fresnel extinguishing control to ambient and environment lights.

Thanks to `@nathanf` for [pointing
out](https://discord.com/channels/691052431525675048/743663924229963868/1164083373514440744)
the [Filament docs section about
this](https://google.github.io/filament/Filament.md.html#lighting/occlusion/specularocclusion).

## Solution

- We use [the same
formulation](ffc572728f/crates/bevy_pbr/src/render/pbr_lighting.wgsl (L99))
already used by the `fresnel()` function in `bevy_pbr::lighting` to
modulate the F90, to modulate the specular component of Ambient and
Environment Map lights.

## Comparison

⚠️ **Modified version of the PBR example for demo purposes, that shows
reflectance (_NOT_ part of this PR)** ⚠️

Also, keep in mind this is a very subtle difference (look for the
fresnel highlights on the lower left spheres, you might need to zoom in.

### Before
<img width="1392" alt="Screenshot 2023-10-18 at 23 02 25"
src="https://github.com/bevyengine/bevy/assets/418473/ec0efb58-9a98-4377-87bc-726a1b0a3ff3">

### After
<img width="1392" alt="Screenshot 2023-10-18 at 23 01 43"
src="https://github.com/bevyengine/bevy/assets/418473/a2809325-5728-405e-af02-9b5779767843">

---

## Changelog

- Ambient and Environment Map lights will now honor values of
`reflectance` that are below the physically possible range (⪅ 0.35) by
extinguishing their fresnel highlights. (Just like point, directional
and spot lights already did.) This allows for more consistent artistic
control and for non-physically realistic looks with all light types.

## Migration Guide

- If Fresnel highlights from Ambient and Environment Map lights are no
longer visible in your materials, make sure you're using a higher,
physically plausible value of `reflectance` (⪆ 0.35).
2023-10-23 03:26:20 +00:00
robtfm
6f2a5cb862
Bind group entries (#9694)
# Objective

Simplify bind group creation code. alternative to (and based on) #9476

## Solution

- Add a `BindGroupEntries` struct that can transparently be used where
`&[BindGroupEntry<'b>]` is required in BindGroupDescriptors.

Allows constructing the descriptor's entries as:
```rust
render_device.create_bind_group(
    "my_bind_group",
    &my_layout,
    &BindGroupEntries::with_indexes((
        (2, &my_sampler),
        (3, my_uniform),
    )),
);
```

instead of

```rust
render_device.create_bind_group(
    "my_bind_group",
    &my_layout,
    &[
        BindGroupEntry {
            binding: 2,
            resource: BindingResource::Sampler(&my_sampler),
        },
        BindGroupEntry {
            binding: 3,
            resource: my_uniform,
        },
    ],
);
```

or

```rust
render_device.create_bind_group(
    "my_bind_group",
    &my_layout,
    &BindGroupEntries::sequential((&my_sampler, my_uniform)),
);
```

instead of

```rust
render_device.create_bind_group(
    "my_bind_group",
    &my_layout,
    &[
        BindGroupEntry {
            binding: 0,
            resource: BindingResource::Sampler(&my_sampler),
        },
        BindGroupEntry {
            binding: 1,
            resource: my_uniform,
        },
    ],
);
```

the structs has no user facing macros, is tuple-type-based so stack
allocated, and has no noticeable impact on compile time.

- Also adds a `DynamicBindGroupEntries` struct with a similar api that
uses a `Vec` under the hood and allows extending the entries.
- Modifies `RenderDevice::create_bind_group` to take separate arguments
`label`, `layout` and `entries` instead of a `BindGroupDescriptor`
struct. The struct can't be stored due to the internal references, and
with only 3 members arguably does not add enough context to justify
itself.
- Modify the codebase to use the new api and the `BindGroupEntries` /
`DynamicBindGroupEntries` structs where appropriate (whenever the
entries slice contains more than 1 member).

## Migration Guide

- Calls to `RenderDevice::create_bind_group({BindGroupDescriptor {
label, layout, entries })` must be amended to
`RenderDevice::create_bind_group(label, layout, entries)`.
- If `label`s have been specified as `"bind_group_name".into()`, they
need to change to just `"bind_group_name"`. `Some("bind_group_name")`
and `None` will still work, but `Some("bind_group_name")` can optionally
be simplified to just `"bind_group_name"`.

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2023-10-21 15:39:22 +00:00
robtfm
61bad4eb57
update shader imports (#10180)
# Objective

- bump naga_oil to 0.10
- update shader imports to use rusty syntax

## Migration Guide

naga_oil 0.10 reworks the import mechanism to support more syntax to
make it more rusty, and test for item use before importing to determine
which imports are modules and which are items, which allows:

- use rust-style imports
```
#import bevy_pbr::{
    pbr_functions::{alpha_discard as discard, apply_pbr_lighting}, 
    mesh_bindings,
}
```

- import partial paths:
```
#import part::of::path
...
path::remainder::function();
```
which will call to `part::of::path::remainder::function`

- use fully qualified paths without importing:
```
// #import bevy_pbr::pbr_functions
bevy_pbr::pbr_functions::pbr()
```
- use imported items without qualifying
```
#import bevy_pbr::pbr_functions::pbr
// for backwards compatibility the old style is still supported:
// #import bevy_pbr::pbr_functions pbr
...
pbr()
```

- allows most imported items to end with `_` and numbers (naga_oil#30).
still doesn't allow struct members to end with `_` or numbers but it's
progress.

- the vast majority of existing shader code will work without changes,
but will emit "deprecated" warnings for old-style imports. these can be
suppressed with the `allow-deprecated` feature.

- partly breaks overrides (as far as i'm aware nobody uses these yet) -
now overrides will only be applied if the overriding module is added as
an additional import in the arguments to `Composer::make_naga_module` or
`Composer::add_composable_module`. this is necessary to support
determining whether imports are modules or items.
2023-10-21 11:51:58 +00:00
Marco Buono
9b80205acb
Variable MeshPipeline View Bind Group Layout (#10156)
# Objective

This PR aims to make it so that we don't accidentally go over
`MAX_TEXTURE_IMAGE_UNITS` (in WebGL) or
`maxSampledTexturesPerShaderStage` (in WebGPU), giving us some extra
leeway to add more view bind group textures.

(This PR is extracted from—and unblocks—#8015)

## Solution

- We replace the existing `view_layout` and `view_layout_multisampled`
pair with an array of 32 bind group layouts, generated ahead of time;
- For now, these layouts cover all the possible combinations of:
`multisampled`, `depth_prepass`, `normal_prepass`,
`motion_vector_prepass` and `deferred_prepass`:
- In the future, as @JMS55 pointed out, we can likely take out
`motion_vector_prepass` and `deferred_prepass`, as these are not really
needed for the mesh pipeline and can use separate pipelines. This would
bring the possible combinations down to 8;
- We can also add more "optional" textures as they become needed,
allowing the engine to scale to a wider variety of use cases in lower
end/web environments (e.g. some apps might just want normal and depth
prepasses, others might only want light probes), while still keeping a
high ceiling for high end native environments where more textures are
supported.
- While preallocating bind group layouts is relatively cheap, the number
of combinations grows exponentially, so we should likely limit ourselves
to something like at most 256–1024 total layouts until we find a better
solution (like generating them lazily)
- To make this mechanism a little bit more explicit/discoverable, so
that compatibility with WebGPU/WebGL is not broken by accident, we add a
`MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES` const and warn whenever
the number of textures in the layout crosses it.
- The warning is gated by `#[cfg(debug_assertions)]` and not issued in
release builds;
- We're counting the actual textures in the bind group layout instead of
using some roundabout metric so it should be accurate;
- Right now `MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES` is set to 10
in order to leave 6 textures free for other groups;
- Currently there's no combination that would cause us to go over the
limit, but that will change once #8015 lands.

---

## Changelog

- `MeshPipeline` view bind group layouts now vary based on the current
multisampling and prepass states, saving a couple of texture binding
entries when prepasses are not in use.

## Migration Guide

- `MeshPipeline::view_layout` and
`MeshPipeline::view_layout_multisampled` have been replaced with a
private array to accomodate for variable view bind group layouts. To
obtain a view bind group layout for the current pipeline state, use the
new `MeshPipeline::get_view_layout()` or
`MeshPipeline::get_view_layout_from_key()` methods.
2023-10-21 11:19:44 +00:00
Jan Češpivo
dcc35120f9
chore: use ExtractComponent derive macro for EnvironmentMapLight and FogSettings (#10191)
I've done tiny cleanup when playing with code.

## Solution

[derive
macro](https://github.com/bevyengine/bevy/blob/main/crates/bevy_render/macros/src/extract_component.rs)
with `extract_component_filter` attribute generate the same code I
removed.

## Migration Guide

No migration needed
2023-10-19 20:18:33 +00:00
robtfm
c99351f7c2
allow extensions to StandardMaterial (#7820)
# Objective

allow extending `Material`s (including the built in `StandardMaterial`)
with custom vertex/fragment shaders and additional data, to easily get
pbr lighting with custom modifications, or otherwise extend a base
material.

# Solution

- added `ExtendedMaterial<B: Material, E: MaterialExtension>` which
contains a base material and a user-defined extension.
- added example `extended_material` showing how to use it
- modified AsBindGroup to have "unprepared" functions that return raw
resources / layout entries so that the extended material can combine
them

note: doesn't currently work with array resources, as i can't figure out
how to make the OwnedBindingResource::get_binding() work, as wgpu
requires a `&'a[&'a TextureView]` and i have a `Vec<TextureView>`.

# Migration Guide

manual implementations of `AsBindGroup` will need to be adjusted, the
changes are pretty straightforward and can be seen in the diff for e.g.
the `texture_binding_array` example.

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
2023-10-17 21:28:08 +00:00
robtfm
de8a6007b7
check for any prepass phase (#10160)
# Objective

deferred doesn't currently run unless one of `DepthPrepass`,
`ForwardPrepass` or `MotionVectorPrepass` is also present on the camera.

## Solution

modify the `queue_prepass_material_meshes` view query to check for any
relevant phase, instead of requiring `Opaque3dPrepass` and
`AlphaMask3dPrepass` to be present
2023-10-17 19:28:52 +00:00
Marco Buono
5733d2403e
*_PREPASS Shader Def Cleanup (#10136)
# Objective

- This PR aims to make the various `*_PREPASS` shader defs we have
(`NORMAL_PREPASS`, `DEPTH_PREPASS`, `MOTION_VECTORS_PREPASS` AND
`DEFERRED_PREPASS`) easier to use and understand:
- So that their meaning is now consistent across all contexts; (“prepass
X is enabled for the current view”)
  - So that they're also consistently set across all contexts.
- It also aims to enable us to (with a follow up PR) to conditionally
gate the `BindGroupEntry` and `BindGroupLayoutEntry` items associated
with these prepasses, saving us up to 4 texture slots in WebGL
(currently globally limited to 16 per shader, regardless of bind groups)

## Solution

- We now consistently set these from `PrepassPipeline`, the
`MeshPipeline` and the `DeferredLightingPipeline`, we also set their
`MeshPipelineKey`s;
- We introduce `PREPASS_PIPELINE`, `MESH_PIPELINE` and
`DEFERRED_LIGHTING_PIPELINE` that can be used to detect where the code
is running, without overloading the meanings of the prepass shader defs;
- We also gate the WGSL functions in `bevy_pbr::prepass_utils` with
`#ifdef`s for their respective shader defs, so that shader code can
provide a fallback whenever they're not available.
- This allows us to conditionally include the bindings for these prepass
textures (My next PR, which will hopefully unblock #8015)
- @robtfm mentioned [these were being used to prevent accessing the same
binding as read/write in the
prepass](https://discord.com/channels/691052431525675048/743663924229963868/1163270458393759814),
however even after reversing the `#ifndef`s I had no issues running the
code, so perhaps the compiler is already smart enough even without tree
shaking to know they're not being used, thanks to `#ifdef
PREPASS_PIPELINE`?

## Comparison

### Before

| Shader Def | `PrepassPipeline` | `MeshPipeline` |
`DeferredLightingPipeline` |
| ------------------------ | ----------------- | -------------- |
-------------------------- |
| `NORMAL_PREPASS` | Yes | No | No |
| `DEPTH_PREPASS` | Yes | No | No |
| `MOTION_VECTORS_PREPASS` | Yes | No | No |
| `DEFERRED_PREPASS` | Yes | No | No |

| View Key | `PrepassPipeline` | `MeshPipeline` |
`DeferredLightingPipeline` |
| ------------------------ | ----------------- | -------------- |
-------------------------- |
| `NORMAL_PREPASS` | Yes | Yes | No |
| `DEPTH_PREPASS` | Yes | No | No |
| `MOTION_VECTORS_PREPASS` | Yes | No | No |
| `DEFERRED_PREPASS` | Yes | Yes\* | No |

\* Accidentally was being set twice, once with only
`deferred_prepass.is_some()` as a condition,
and once with `deferred_p repass.is_some() && !forward` as a condition.

### After

| Shader Def | `PrepassPipeline` | `MeshPipeline` |
`DeferredLightingPipeline` |
| ---------------------------- | ----------------- | --------------- |
-------------------------- |
| `NORMAL_PREPASS` | Yes | Yes | Yes |
| `DEPTH_PREPASS` | Yes | Yes | Yes |
| `MOTION_VECTORS_PREPASS` | Yes | Yes | Yes |
| `DEFERRED_PREPASS` | Yes | Yes | Unconditionally |
| `PREPASS_PIPELINE` | Unconditionally | No | No |
| `MESH_PIPELINE` | No | Unconditionally | No |
| `DEFERRED_LIGHTING_PIPELINE` | No | No | Unconditionally |

| View Key | `PrepassPipeline` | `MeshPipeline` |
`DeferredLightingPipeline` |
| ------------------------ | ----------------- | -------------- |
-------------------------- |
| `NORMAL_PREPASS` | Yes | Yes | Yes |
| `DEPTH_PREPASS` | Yes | Yes | Yes |
| `MOTION_VECTORS_PREPASS` | Yes | Yes | Yes |
| `DEFERRED_PREPASS` | Yes | Yes | Unconditionally |

---

## Changelog

- Cleaned up WGSL `*_PREPASS` shader defs so they're now consistently
used everywhere;
- Introduced `PREPASS_PIPELINE`, `MESH_PIPELINE` and
`DEFERRED_LIGHTING_PIPELINE` WGSL shader defs for conditionally
compiling logic based the current pipeline;
- WGSL functions from `bevy_pbr::prepass_utils` are now guarded with
`#ifdef` based on the currently enabled prepasses;

## Migration Guide

- When using functions from `bevy_pbr::prepass_utils`
(`prepass_depth()`, `prepass_normal()`, `prepass_motion_vector()`) in
contexts where these prepasses might be disabled, you should now wrap
your calls with the appropriate `#ifdef` guards, (`#ifdef
DEPTH_PREPASS`, `#ifdef NORMAL_PREPASS`, `#ifdef MOTION_VECTOR_PREPASS`)
providing fallback logic where applicable.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2023-10-17 00:16:21 +00:00
Griffin
490699c311
Fix unlit missing parameters (#10144)
# Objective

- The refactoring in https://github.com/bevyengine/bevy/pull/10105
missed including the frag_coord and normal in pbr_input.

## Solution

- Add them back
2023-10-16 22:11:51 +00:00
Edgar Geier
e23d7cf501
Explain usage of prepass shaders in docs for Material trait (#9025)
# Objective

- Fixes #8696.

## Solution

- Added a paragraph describing the usage of the `prepass_vertex_shader`
and `prepass_fragment_shader`.
2023-10-16 13:39:17 +00:00