Commit graph

521 commits

Author SHA1 Message Date
Elabajaba
45e920c2e1
Workaround for ICE in the DXC shader compiler in debug builds with an EnvironmentMapLight (#11487)
# Objective

DXC+DX12 debug builds with an environment map have been broken since
https://github.com/bevyengine/bevy/pull/11366 merged due to an internal
compiler error in DXC. I tracked it down to a single `break` statement
and reported it upstream
(https://github.com/microsoft/DirectXShaderCompiler/issues/6183)

## Solution

Workaround the ICE by setting the for loop index variable to the max
value of the loop to avoid the `break` that's causing the ICE.

This works because it's the last thing in the for loop.

The `reflection_probes` and `pbr` examples both appear to still work
correctly.
2024-01-27 13:37:08 +00:00
Miles Silberling-Cook
8f25805b66
Added documentation explaining the difference between lumens and luxes (#11551)
# Objective

- Fix https://github.com/bevyengine/bevy/issues/9809

## Solution

- Describe the difference between lumens and luxes, and why some
lightsources use one and some the other.
2024-01-27 00:32:14 +00:00
Elabajaba
35ac1b152e
Update to wgpu 0.19 and raw-window-handle 0.6 (#11280)
# Objective

Keep core dependencies up to date.

## Solution

Update the dependencies.

wgpu 0.19 only supports raw-window-handle (rwh) 0.6, so bumping that was
included in this.

The rwh 0.6 version bump is just the simplest way of doing it. There
might be a way we can take advantage of wgpu's new safe surface creation
api, but I'm not familiar enough with bevy's window management to
untangle it and my attempt ended up being a mess of lifetimes and rustc
complaining about missing trait impls (that were implemented). Thanks to
@MiniaczQ for the (much simpler) rwh 0.6 version bump code.

Unblocks https://github.com/bevyengine/bevy/pull/9172 and
https://github.com/bevyengine/bevy/pull/10812

~~This might be blocked on cpal and oboe updating their ndk versions to
0.8, as they both currently target ndk 0.7 which uses rwh 0.5.2~~ Tested
on android, and everything seems to work correctly (audio properly stops
when minimized, and plays when re-focusing the app).

---

## Changelog

- `wgpu` has been updated to 0.19! The long awaited arcanization has
been merged (for more info, see
https://gfx-rs.github.io/2023/11/24/arcanization.html), and Vulkan
should now be working again on Intel GPUs.
- Targeting WebGPU now requires that you add the new `webgpu` feature
(setting the `RUSTFLAGS` environment variable to
`--cfg=web_sys_unstable_apis` is still required). This feature currently
overrides the `webgl2` feature if you have both enabled (the `webgl2`
feature is enabled by default), so it is not recommended to add it as a
default feature to libraries without putting it behind a flag that
allows library users to opt out of it! In the future we plan on
supporting wasm binaries that can target both webgl2 and webgpu now that
wgpu added support for doing so (see
https://github.com/bevyengine/bevy/issues/11505).
- `raw-window-handle` has been updated to version 0.6.

## Migration Guide

- `bevy_render::instance_index::get_instance_index()` has been removed
as the webgl2 workaround is no longer required as it was fixed upstream
in wgpu. The `BASE_INSTANCE_WORKAROUND` shaderdef has also been removed.
- WebGPU now requires the new `webgpu` feature to be enabled. The
`webgpu` feature currently overrides the `webgl2` feature so you no
longer need to disable all default features and re-add them all when
targeting `webgpu`, but binaries built with both the `webgpu` and
`webgl2` features will only target the webgpu backend, and will only
work on browsers that support WebGPU.
- Places where you conditionally compiled things for webgl2 need to be
updated because of this change, eg:
- `#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]`
becomes `#[cfg(any(not(feature = "webgl") ,not(target_arch = "wasm32"),
feature = "webgpu"))]`
- `#[cfg(all(feature = "webgl", target_arch = "wasm32"))]` becomes
`#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature =
"webgpu")))]`
- `if cfg!(all(feature = "webgl", target_arch = "wasm32"))` becomes `if
cfg!(all(feature = "webgl", target_arch = "wasm32", not(feature =
"webgpu")))`
- `create_texture_with_data` now also takes a `TextureDataOrder`. You
can probably just set this to `TextureDataOrder::default()`
- `TextureFormat`'s `block_size` has been renamed to `block_copy_size`
- See the `wgpu` changelog for anything I might've missed:
https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md

---------

Co-authored-by: François <mockersf@gmail.com>
2024-01-26 18:14:21 +00:00
AxiomaticSemantics
2ebf5a303e
Remove TypeUuid (#11497)
# Objective
TypeUuid is deprecated, remove it.

## Migration Guide
Convert any uses of `#[derive(TypeUuid)]` with `#[derive(TypePath]` for
more complex uses see the relevant
[documentation](https://docs.rs/bevy/latest/bevy/prelude/trait.TypePath.html)
for more information.

---------

Co-authored-by: ebola <dev@axiomatic>
2024-01-25 16:16:58 +00:00
JMS55
a796d53a05
Meshlet prep (#11442)
# Objective

- Prep for https://github.com/bevyengine/bevy/pull/10164
- Make deferred_lighting_pass_id a ColorAttachment
- Correctly extract shadow view frusta so that the view uniforms get
populated
- Make some needed things public
- Misc formatting
2024-01-22 15:28:33 +00:00
Alice Cecile
eb07d16871
Revert rendering-related associated type name changes (#11027)
# Objective

> Can anyone explain to me the reasoning of renaming all the types named
Query to Data. I'm talking about this PR
https://github.com/bevyengine/bevy/pull/10779 It doesn't make sense to
me that a bunch of types that are used to run queries aren't named Query
anymore. Like ViewQuery on the ViewNode is the type of the Query. I
don't really understand the point of the rename, it just seems like it
hides the fact that a query will run based on those types.


[@IceSentry](https://discord.com/channels/691052431525675048/692572690833473578/1184946251431694387)

## Solution

Revert several renames in #10779.

## Changelog

- `ViewNode::ViewData` is now `ViewNode::ViewQuery` again.

## Migration Guide

- This PR amends the migration guide in
https://github.com/bevyengine/bevy/pull/10779

---------

Co-authored-by: atlas dostal <rodol@rivalrebels.com>
2024-01-22 15:01:55 +00:00
re0312
04aedf12fa
optimize batch_and_prepare_render_phase (#11323)
# Objective

- since #9685  ,bevy introduce automatic batching of draw commands, 
- `batch_and_prepare_render_phase` take the responsibility for batching
`phaseItem`,
- `GetBatchData` trait is used for indentify each phaseitem how to
batch. it defines a associated type `Data `used for Query to fetch data
from world.

- however,the impl of `GetBatchData ` in bevy always set ` type
Data=Entity` then we acually get following code
`let entity:Entity =query.get(item.entity())` that cause unnecessary
overhead .

## Solution

- remove associated type `Data ` and `Filter` from `GetBatchData `,
- change the type of the `query_item ` parameter in get_batch_data from`
Self::Data` to `Entity`.
- `batch_and_prepare_render_phase ` no longer takes a query using
`F::Data, F::Filter`
- `get_batch_data `now returns `Option<(Self::BufferData,
Option<Self::CompareData>)>`

---

## Performance
based in main merged with #11290 
Window 11 ,Intel 13400kf, NV 4070Ti

![image](https://github.com/bevyengine/bevy/assets/45868716/f63b9d98-6aee-4057-a2c7-a2162b2db765)
frame time from 3.34ms to 3 ms,  ~ 10%


![image](https://github.com/bevyengine/bevy/assets/45868716/a06eea9c-f79e-4324-8392-8d321560c5ba)
`batch_and_prepare_render_phase` from 800us ~ 400 us  

## Migration Guide
trait `GetBatchData` no longer hold associated type  `Data `and `Filter`
`get_batch_data` `query_item `type from `Self::Data` to `Entity` and
return `Option<(Self::BufferData, Option<Self::CompareData>)>`
`batch_and_prepare_render_phase`  should not have a query
2024-01-20 09:30:44 +00:00
Patrick Walton
83d6600267
Implement minimal reflection probes (fixed macOS, iOS, and Android). (#11366)
This pull request re-submits #10057, which was backed out for breaking
macOS, iOS, and Android. I've tested this version on macOS and Android
and on the iOS simulator.

# Objective

This pull request implements *reflection probes*, which generalize
environment maps to allow for multiple environment maps in the same
scene, each of which has an axis-aligned bounding box. This is a
standard feature of physically-based renderers and was inspired by [the
corresponding feature in Blender's Eevee renderer].

## Solution

This is a minimal implementation of reflection probes that allows
artists to define cuboid bounding regions associated with environment
maps. For every view, on every frame, a system builds up a list of the
nearest 4 reflection probes that are within the view's frustum and
supplies that list to the shader. The PBR fragment shader searches
through the list, finds the first containing reflection probe, and uses
it for indirect lighting, falling back to the view's environment map if
none is found. Both forward and deferred renderers are fully supported.

A reflection probe is an entity with a pair of components, *LightProbe*
and *EnvironmentMapLight* (as well as the standard *SpatialBundle*, to
position it in the world). The *LightProbe* component (along with the
*Transform*) defines the bounding region, while the
*EnvironmentMapLight* component specifies the associated diffuse and
specular cubemaps.

A frequent question is "why two components instead of just one?" The
advantages of this setup are:

1. It's readily extensible to other types of light probes, in particular
*irradiance volumes* (also known as ambient cubes or voxel global
illumination), which use the same approach of bounding cuboids. With a
single component that applies to both reflection probes and irradiance
volumes, we can share the logic that implements falloff and blending
between multiple light probes between both of those features.

2. It reduces duplication between the existing *EnvironmentMapLight* and
these new reflection probes. Systems can treat environment maps attached
to cameras the same way they treat environment maps applied to
reflection probes if they wish.

Internally, we gather up all environment maps in the scene and place
them in a cubemap array. At present, this means that all environment
maps must have the same size, mipmap count, and texture format. A
warning is emitted if this restriction is violated. We could potentially
relax this in the future as part of the automatic mipmap generation
work, which could easily do texture format conversion as part of its
preprocessing.

An easy way to generate reflection probe cubemaps is to bake them in
Blender and use the `export-blender-gi` tool that's part of the
[`bevy-baked-gi`] project. This tool takes a `.blend` file containing
baked cubemaps as input and exports cubemap images, pre-filtered with an
embedded fork of the [glTF IBL Sampler], alongside a corresponding
`.scn.ron` file that the scene spawner can use to recreate the
reflection probes.

Note that this is intentionally a minimal implementation, to aid
reviewability. Known issues are:

* Reflection probes are basically unsupported on WebGL 2, because WebGL
2 has no cubemap arrays. (Strictly speaking, you can have precisely one
reflection probe in the scene if you have no other cubemaps anywhere,
but this isn't very useful.)

* Reflection probes have no falloff, so reflections will abruptly change
when objects move from one bounding region to another.

* As mentioned before, all cubemaps in the world of a given type
(diffuse or specular) must have the same size, format, and mipmap count.

Future work includes:

* Blending between multiple reflection probes.

* A falloff/fade-out region so that reflected objects disappear
gradually instead of vanishing all at once.

* Irradiance volumes for voxel-based global illumination. This should
reuse much of the reflection probe logic, as they're both GI techniques
based on cuboid bounding regions.

* Support for WebGL 2, by breaking batches when reflection probes are
used.

These issues notwithstanding, I think it's best to land this with
roughly the current set of functionality, because this patch is useful
as is and adding everything above would make the pull request
significantly larger and harder to review.

---

## Changelog

### Added

* A new *LightProbe* component is available that specifies a bounding
region that an *EnvironmentMapLight* applies to. The combination of a
*LightProbe* and an *EnvironmentMapLight* offers *reflection probe*
functionality similar to that available in other engines.

[the corresponding feature in Blender's Eevee renderer]:
https://docs.blender.org/manual/en/latest/render/eevee/light_probes/reflection_cubemaps.html

[`bevy-baked-gi`]: https://github.com/pcwalton/bevy-baked-gi

[glTF IBL Sampler]: https://github.com/KhronosGroup/glTF-IBL-Sampler
2024-01-19 07:33:52 +00:00
JMS55
fcd7c0fc3d
Exposure settings (adopted) (#11347)
Rebased and finished version of
https://github.com/bevyengine/bevy/pull/8407. Huge thanks to @GitGhillie
for adjusting all the examples, and the many other people who helped
write this PR (@superdump , @coreh , among others) :)

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

---

## Changelog
- Added a `brightness` control to `Skybox`.
- Added an `intensity` control to `EnvironmentMapLight`.
- Added `ExposureSettings` and `PhysicalCameraParameters` for
controlling exposure of 3D cameras.
- Removed the baked-in `DirectionalLight` exposure Bevy previously
hardcoded internally.

## Migration Guide
- If using a `Skybox` or `EnvironmentMapLight`, use the new `brightness`
and `intensity` controls to adjust their strength.
- All 3D scene will now have different apparent brightnesses due to Bevy
implementing proper exposure controls. You will have to adjust the
intensity of your lights and/or your camera exposure via the new
`ExposureSettings` component to compensate.

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: GitGhillie <jillisnoordhoek@gmail.com>
Co-authored-by: Marco Buono <thecoreh@gmail.com>
Co-authored-by: vero <email@atlasdostal.com>
Co-authored-by: atlas dostal <rodol@rivalrebels.com>
2024-01-16 14:53:21 +00:00
Aevyrie
839d2f8353
Approximate indirect specular occlusion (#11152)
# Objective

- The current PBR renderer over-brightens indirect specular reflections,
which tends to cause objects to appear to glow, because specular
occlusion is not accounted for.

## Solution

- Attenuate indirect specular term with an approximation for specular
occlusion, using [[Lagarde et al., 2014] (pg.
76)](https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf).

| Before | After | Animation |
| --- | --- | --- |
| <img width="1840" alt="before bike"
src="https://github.com/bevyengine/bevy/assets/2632925/b6e10d15-a998-4a94-875a-1c2b1e98348a">
| <img width="1840" alt="after bike"
src="https://github.com/bevyengine/bevy/assets/2632925/53b1479c-b1e4-427f-b140-53df26ca7193">
|
![ezgif-1-fbcbaf272b](https://github.com/bevyengine/bevy/assets/2632925/c2dece1c-eb3d-4e05-92a2-46cf83052c7c)
|
| <img width="1840" alt="classroom before"
src="https://github.com/bevyengine/bevy/assets/2632925/b16c0e74-741e-4f40-a7df-8863eaa62596">
| <img width="1840" alt="classroom after"
src="https://github.com/bevyengine/bevy/assets/2632925/26f9e971-0c63-4ee9-9544-964e5703d65e">
|
![ezgif-1-0f390edd06](https://github.com/bevyengine/bevy/assets/2632925/d8894e52-380f-4528-aa0d-1ca249108178)
|

---

## Changelog

- Ambient occlusion now applies to indirect specular reflections to
approximate how objects occlude specular light.

## Migration Guide

- Renamed `PbrInput::occlusion` to `diffuse_occlusion`, and added
`specular_occlusion`.
2024-01-15 16:10:55 +00:00
vero
4695b82f6b
Use EntityHashMap whenever possible (#11353)
# Objective

Fixes #11352

## Solution

- Use `EntityHashMap<Entity, T>` instead of `HashMap<Entity, T>`

---

## Changelog

Changed
- Use `EntityHashMap<Entity, T>` instead of `HashMap<Entity, T>`
whenever possible

## Migration Guide

TODO
2024-01-15 15:51:17 +00:00
Ixentus
e2fd63104d
Simplify conditions (#11316)
# Objective

- Conditions don't have to be closures unless they have state or mutate.

## Solution

- Simplify conditions when possible.

---

## Changelog

The following run conditions are now regular systems:
- resource_exists<T>
- resource_added<T>
- resource_changed<T>
- resource_exists_and_changed<T>
- state_exists<S: States>
- state_changed<S: States>
- any_with_component<T: Component>

## Migration Guide

- resource_exists<T>() -> resource_exists<T>
- resource_added<T>() -> resource_added<T>
- resource_changed<T>() -> resource_changed<T>
- resource_exists_and_changed<T>() -> resource_exists_and_changed<T>
- state_exists<S: States>() -> state_exists<S: States>
- state_changed<S: States>() -> state_changed<S: States>
- any_with_component<T: Component>() -> any_with_component<T: Component>
2024-01-13 13:22:17 +00:00
François
3d996639a0
Revert "Implement minimal reflection probes. (#10057)" (#11307)
# Objective

- Fix working on macOS, iOS, Android on main 
- Fixes #11281 
- Fixes #11282 
- Fixes #11283 
- Fixes #11299

## Solution

- Revert #10057
2024-01-12 20:41:51 +00:00
Elabajaba
64a15f1b10
Fix ssao only sampling mip 0 (#11292)
# Objective

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

## Solution

SSAO's sample_mip_level was always giving negative values because it was
in UV space (0..1) when it needed to be in pixel units (0..resolution).

Fixing it so it properly samples lower mip levels when appropriate is a
pretty large speedup (~3.2ms -> ~1ms at 4k, ~507us-> 256us at 1080p on a
6800xt), and I didn't notice any obvious visual quality differences.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-01-12 05:33:26 +00:00
Jakob Hellermann
a657478675
resolve all internal ambiguities (#10411)
- ignore all ambiguities that are not a problem
- remove `.before(Assets::<Image>::track_assets),` that points into a
different schedule (-> should this be caught?)
- add some explicit orderings:
- run `poll_receivers` and `update_accessibility_nodes` after
`window_closed` in `bevy_winit::accessibility`
  - run `bevy_ui::accessibility::calc_bounds` after `CameraUpdateSystem`
- run ` bevy_text::update_text2d_layout` and `bevy_ui::text_system`
after `font_atlas_set::remove_dropped_font_atlas_sets`
- add `app.ignore_ambiguity(a, b)` function for cases where you want to
ignore an ambiguity between two independent plugins `A` and `B`
- add `IgnoreAmbiguitiesPlugin` in `DefaultPlugins` that allows
cross-crate ambiguities like `bevy_animation`/`bevy_ui`
- Fixes https://github.com/bevyengine/bevy/issues/9511

## Before
**Render**
![render_schedule_Render
dot](https://github.com/bevyengine/bevy/assets/22177966/1c677968-7873-40cc-848c-91fca4c8e383)

**PostUpdate**
![schedule_PostUpdate
dot](https://github.com/bevyengine/bevy/assets/22177966/8fc61304-08d4-4533-8110-c04113a7367a)

## After
**Render**
![render_schedule_Render
dot](https://github.com/bevyengine/bevy/assets/22177966/462f3b28-cef7-4833-8619-1f5175983485)
**PostUpdate**
![schedule_PostUpdate
dot](https://github.com/bevyengine/bevy/assets/22177966/8cfb3d83-7842-4a84-9082-46177e1a6c70)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
2024-01-09 19:08:15 +00:00
Patrick Walton
54a943d232
Implement minimal reflection probes. (#10057)
# Objective

This pull request implements *reflection probes*, which generalize
environment maps to allow for multiple environment maps in the same
scene, each of which has an axis-aligned bounding box. This is a
standard feature of physically-based renderers and was inspired by [the
corresponding feature in Blender's Eevee renderer].

## Solution

This is a minimal implementation of reflection probes that allows
artists to define cuboid bounding regions associated with environment
maps. For every view, on every frame, a system builds up a list of the
nearest 4 reflection probes that are within the view's frustum and
supplies that list to the shader. The PBR fragment shader searches
through the list, finds the first containing reflection probe, and uses
it for indirect lighting, falling back to the view's environment map if
none is found. Both forward and deferred renderers are fully supported.

A reflection probe is an entity with a pair of components, *LightProbe*
and *EnvironmentMapLight* (as well as the standard *SpatialBundle*, to
position it in the world). The *LightProbe* component (along with the
*Transform*) defines the bounding region, while the
*EnvironmentMapLight* component specifies the associated diffuse and
specular cubemaps.

A frequent question is "why two components instead of just one?" The
advantages of this setup are:

1. It's readily extensible to other types of light probes, in particular
*irradiance volumes* (also known as ambient cubes or voxel global
illumination), which use the same approach of bounding cuboids. With a
single component that applies to both reflection probes and irradiance
volumes, we can share the logic that implements falloff and blending
between multiple light probes between both of those features.

2. It reduces duplication between the existing *EnvironmentMapLight* and
these new reflection probes. Systems can treat environment maps attached
to cameras the same way they treat environment maps applied to
reflection probes if they wish.

Internally, we gather up all environment maps in the scene and place
them in a cubemap array. At present, this means that all environment
maps must have the same size, mipmap count, and texture format. A
warning is emitted if this restriction is violated. We could potentially
relax this in the future as part of the automatic mipmap generation
work, which could easily do texture format conversion as part of its
preprocessing.

An easy way to generate reflection probe cubemaps is to bake them in
Blender and use the `export-blender-gi` tool that's part of the
[`bevy-baked-gi`] project. This tool takes a `.blend` file containing
baked cubemaps as input and exports cubemap images, pre-filtered with an
embedded fork of the [glTF IBL Sampler], alongside a corresponding
`.scn.ron` file that the scene spawner can use to recreate the
reflection probes.

Note that this is intentionally a minimal implementation, to aid
reviewability. Known issues are:

* Reflection probes are basically unsupported on WebGL 2, because WebGL
2 has no cubemap arrays. (Strictly speaking, you can have precisely one
reflection probe in the scene if you have no other cubemaps anywhere,
but this isn't very useful.)

* Reflection probes have no falloff, so reflections will abruptly change
when objects move from one bounding region to another.

* As mentioned before, all cubemaps in the world of a given type
(diffuse or specular) must have the same size, format, and mipmap count.

Future work includes:

* Blending between multiple reflection probes.

* A falloff/fade-out region so that reflected objects disappear
gradually instead of vanishing all at once.

* Irradiance volumes for voxel-based global illumination. This should
reuse much of the reflection probe logic, as they're both GI techniques
based on cuboid bounding regions.

* Support for WebGL 2, by breaking batches when reflection probes are
used.

These issues notwithstanding, I think it's best to land this with
roughly the current set of functionality, because this patch is useful
as is and adding everything above would make the pull request
significantly larger and harder to review.

---

## Changelog

### Added

* A new *LightProbe* component is available that specifies a bounding
region that an *EnvironmentMapLight* applies to. The combination of a
*LightProbe* and an *EnvironmentMapLight* offers *reflection probe*
functionality similar to that available in other engines.

[the corresponding feature in Blender's Eevee renderer]:
https://docs.blender.org/manual/en/latest/render/eevee/light_probes/reflection_cubemaps.html

[`bevy-baked-gi`]: https://github.com/pcwalton/bevy-baked-gi

[glTF IBL Sampler]: https://github.com/KhronosGroup/glTF-IBL-Sampler
2024-01-08 22:09:17 +00:00
re0312
101037d0c2
update Outdated comment (#11243)
# Objective

- since #9236 queue_mesh_bind_group has been renamed to
prepare_mesh_bind_group,but the comment referring to it has not been
updated. .
2024-01-07 15:02:43 +00:00
Patrick Walton
5697fee3ad
Bump the vertex attribute index for prepass joints. (#11191)
This was missed in #10231.

Fixes #11190.
2024-01-03 10:35:39 +00:00
JMS55
44424391fe
Unload render assets from RAM (#10520)
# Objective
- No point in keeping Meshes/Images in RAM once they're going to be sent
to the GPU, and kept in VRAM. This saves a _significant_ amount of
memory (several GBs) on scenes like bistro.
- References
  - https://github.com/bevyengine/bevy/pull/1782
  - https://github.com/bevyengine/bevy/pull/8624 

## Solution
- Augment RenderAsset with the capability to unload the underlying asset
after extracting to the render world.
- Mesh/Image now have a cpu_persistent_access field. If this field is
RenderAssetPersistencePolicy::Unload, the asset will be unloaded from
Assets<T>.
- A new AssetEvent is sent upon dropping the last strong handle for the
asset, which signals to the RenderAsset to remove the GPU version of the
asset.

---

## Changelog
- Added `AssetEvent::NoLongerUsed` and
`AssetEvent::is_no_longer_used()`. This event is sent when the last
strong handle of an asset is dropped.
- Rewrote the API for `RenderAsset` to allow for unloading the asset
data from the CPU.
- Added `RenderAssetPersistencePolicy`.
- Added `Mesh::cpu_persistent_access` for memory savings when the asset
is not needed except for on the GPU.
- Added `Image::cpu_persistent_access` for memory savings when the asset
is not needed except for on the GPU.
- Added `ImageLoaderSettings::cpu_persistent_access`.
- Added `ExrTextureLoaderSettings`.
- Added `HdrTextureLoaderSettings`.

## Migration Guide
- Asset loaders (GLTF, etc) now load meshes and textures without
`cpu_persistent_access`. These assets will be removed from
`Assets<Mesh>` and `Assets<Image>` once `RenderAssets<Mesh>` and
`RenderAssets<Image>` contain the GPU versions of these assets, in order
to reduce memory usage. If you require access to the asset data from the
CPU in future frames after the GLTF asset has been loaded, modify all
dependent `Mesh` and `Image` assets and set `cpu_persistent_access` to
`RenderAssetPersistencePolicy::Keep`.
- `Mesh` now requires a new `cpu_persistent_access` field. Set it to
`RenderAssetPersistencePolicy::Keep` to mimic the previous behavior.
- `Image` now requires a new `cpu_persistent_access` field. Set it to
`RenderAssetPersistencePolicy::Keep` to mimic the previous behavior.
- `MorphTargetImage::new()` now requires a new `cpu_persistent_access`
parameter. Set it to `RenderAssetPersistencePolicy::Keep` to mimic the
previous behavior.
- `DynamicTextureAtlasBuilder::add_texture()` now requires that the
`TextureAtlas` you pass has an `Image` with `cpu_persistent_access:
RenderAssetPersistencePolicy::Keep`. Ensure you construct the image
properly for the texture atlas.
- The `RenderAsset` trait has significantly changed, and requires
adapting your existing implementations.
  - The trait now requires `Clone`.
- The `ExtractedAsset` associated type has been removed (the type itself
is now extracted).
  - The signature of `prepare_asset()` is slightly different
- A new `persistence_policy()` method is now required (return
RenderAssetPersistencePolicy::Unload to match the previous behavior).
- Match on the new `NoLongerUsed` variant for exhaustive matches of
`AssetEvent`.
2024-01-03 03:31:04 +00:00
Patrick Walton
dd14f3a477
Implement lightmaps. (#10231)
![Screenshot](https://i.imgur.com/A4KzWFq.png)

# Objective

Lightmaps, textures that store baked global illumination, have been a
mainstay of real-time graphics for decades. Bevy currently has no
support for them, so this pull request implements them.

## Solution

The new `Lightmap` component can be attached to any entity that contains
a `Handle<Mesh>` and a `StandardMaterial`. When present, it will be
applied in the PBR shader. Because multiple lightmaps are frequently
packed into atlases, each lightmap may have its own UV boundaries within
its texture. An `exposure` field is also provided, to control the
brightness of the lightmap.

Note that this PR doesn't provide any way to bake the lightmaps. That
can be done with [The Lightmapper] or another solution, such as Unity's
Bakery.

---

## Changelog

### Added
* A new component, `Lightmap`, is available, for baked global
illumination. If your mesh has a second UV channel (UV1), and you attach
this component to the entity with that mesh, Bevy will apply the texture
referenced in the lightmap.

[The Lightmapper]: https://github.com/Naxela/The_Lightmapper

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-01-02 20:38:47 +00:00
Brian Reavis
846a871cb2
Export tonemapping_pipeline_key (2d), alpha_mode_pipeline_key (#11166)
This expands upon https://github.com/bevyengine/bevy/pull/11134.

I found myself needing `tonemapping_pipeline_key` for some custom 2d
draw functions. #11134 exported the 3d version of
`tonemapping_pipeline_key` and this PR exports the 2d version. I also
made `alpha_mode_pipeline_key` public for good measure.
2024-01-01 23:57:12 +00:00
Marco Buono
c2ab3a0402
Do not load prepass normals for transmissive materials (#11140)
Turns out whenever a normal prepass was active (which includes whenever
you use SSAO) we were attempting to read the normals from the prepass
for the specular transmissive material. Since transmissive materials
don't participate in the prepass (unlike opaque materials) we were
reading the normals from “behind” the mesh, producing really weird
visual results.

# Objective

- Fixes #11112.

## Solution

- We introduce a new `READS_VIEW_TRANSMISSION_TEXTURE` mesh pipeline
key;
- We set it whenever the material properties has the
`reads_view_transmission_texture` flag set; (i.e. the material is
transmissive)
- If this key is set we prevent the reading of normals from the prepass,
by not setting the `LOAD_PREPASS_NORMALS` shader def.

---

## Changelog

### Fixed

- Specular transmissive materials no longer attempt to erroneously load
prepass normals, and now work correctly even with the normal prepass
active (e.g. when using SSAO)
2024-01-01 17:04:20 +00:00
JMS55
70b0eacc3b
Keep track of when a texture is first cleared (#10325)
# Objective
- Custom render passes, or future passes in the engine (such as
https://github.com/bevyengine/bevy/pull/10164) need a better way to know
and indicate to the core passes whether the view color/depth/prepass
attachments have been cleared or not yet this frame, to know if they
should clear it themselves or load it.

## Solution

- For all render targets (depth textures, shadow textures, prepass
textures, main textures) use an atomic bool to track whether or not each
texture has been cleared this frame. Abstracted away in the new
ColorAttachment and DepthAttachment wrappers.

---

## Changelog
- Changed `ViewTarget::get_color_attachment()`, removed arguments.
- Changed `ViewTarget::get_unsampled_color_attachment()`, removed
arguments.
- Removed `Camera3d::clear_color`.
- Removed `Camera2d::clear_color`.
- Added `Camera::clear_color`.
- Added `ExtractedCamera::clear_color`.
- Added `ColorAttachment` and `DepthAttachment` wrappers.
- Moved `ClearColor` and `ClearColorConfig` from
`bevy::core_pipeline::clear_color` to `bevy::render::camera`.
- Core render passes now track when a texture is first bound as an
attachment in order to decide whether to clear or load it.

## Migration Guide
- Remove arguments to `ViewTarget::get_color_attachment()` and
`ViewTarget::get_unsampled_color_attachment()`.
- Configure clear color on `Camera` instead of on `Camera3d` and
`Camera2d`.
- Moved `ClearColor` and `ClearColorConfig` from
`bevy::core_pipeline::clear_color` to `bevy::render::camera`.
- `ViewDepthTexture` must now be created via the `new()` method

---------

Co-authored-by: vero <email@atlasdostal.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-12-31 00:37:37 +00:00
JMS55
3d3a065820
Misc cleanup (#11134)
Re-exports a few types/functions I need that have no reason to be
private, and some minor code quality changes.
2023-12-30 23:27:48 +00:00
Tygyh
1568d4a415
Reorder impl to be the same as the trait (#11076)
# Objective

- Make the implementation order consistent between all sources to fit
the order in the trait.

## Solution

- Change the implementation order.
2023-12-24 17:43:55 +00:00
Tygyh
7b8305e5b4
Remove unnecessary parens (#11075)
# Objective

- Increase readability.

## Solution

- Remove unnecessary parens.
2023-12-24 17:43:01 +00:00
David Cosby
42b737878f
Re-export smallvec crate from bevy_utils (#11006)
Matches versioning & features from other Cargo.toml files in the
project.

# Objective
Resolves #10932 

## Solution
Added smallvec to the bevy_utils cargo.toml and added a line to
re-export the crate. Target version and features set to match what's
used in the other bevy crates.
2023-12-24 15:35:09 +00:00
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