Updates the wireframe rendering initialliy implemented in https://github.com/bevyengine/bevy/pull/562 to the new renderer.
It lives in `bevy_pbr2` instead of `bevy_render2` because that way it can reuse the `MeshPipeline`.
# Objective
Make it easier to build and use an asset path with `format!()`. This can be useful for accessing assets in a loop.
Enabled by this PR:
```rust
let monkey_handle = asset_server.get_handle(&format!("models/monkey/Monkey.gltf#Mesh0/Primitive0"));
let monkey_handle = asset_server.get_handle(format!("models/monkey/Monkey.gltf#Mesh0/Primitive0"));
```
Before this PR:
```rust
let monkey_handle = asset_server.get_handle(format!("models/monkey/Monkey.gltf#Mesh0/Primitive0").as_str());
```
It's just a tiny improvement in ergonomics, but i ran into it and was wondering why the function does not accept a `String` and Bevy is all about simplicity/ergonomics, right? 😄😉
## Solution
Implement `Into<HandleId>` for `String` and `&String`.
# Objective
- Rendering before MainPass should be possible, so clearing needs to happen in an earlier pass.
- Fixes#3190.
## Solution
- I added a "Clear" SubGraph, a "ClearPassNode" Node, that clears the color and depth attachments of all views and a "ClearNodeDriver" Node, that schedules the "ClearPassNode" before MainPass.
- Make sure that the 2d and 3d draw passes do not clear their attachments anymore.
### Notes
- It works in the way, that with the current pipeline examples nothing should have changed in their behaviour
- I would like to add an example that adds a pass inbetween ClearPass and MainPass, but I do not understand enough about the new render architecture to do that yet
- Clears all attachment for all views: I do not know enough about rendering in general to say, whether there is a use case for not clearing
- Does not solve #3043 as we still need Cameras/ViewTargets to clear.
# Objective
The new renderer does not support any options yet for wgpu. These are needed for example for rendering wireframes (see #3193).
## Solution
I've ported WgpuOptions to bevy_render2.
The defaults match the defaults that were used before this PR (meaning, some specific options when target_arch = wasm32).
Additionally, I removed `Auto` from WgpuBackends and added `Primary`. The default will use primary or GL based on the target_arch.
# Objective
- there are a few new versions for `ron`, `winit`, `ndk`, `raw-window-handle`
- `cargo-deny` is failing due to new security issues / duplicated dependencies
## Solution
- Update our dependencies
- Note all new security issues, with which of Bevy direct dependency it comes from
- Update duplicate crate list, with which of Bevy direct dependency it comes from
`notify` is not updated here as it's in #2993
# Objective
Implement clustered-forward rendering.
## Solution
~~FIXME - in the interest of keeping the merge train moving, I'm submitting this PR now before the description is ready. I want to add in some comments into the code with references for the various bits and pieces and I want to describe some of the key decisions I made here. I'll do that as soon as I can.~~ Anyone reviewing is welcome to add review comments where you want to know more about how something or other works.
* The summary of the technique is that the view frustum is divided into a grid of sub-volumes called clusters, point lights are tested against each of the clusters to see if they would affect that volume within the scene and if so, added to a list of lights affecting that cluster. Then when shading a fragment which is a point on the surface of a mesh within the scene, the point is mapped to a cluster and only the lights affecting that clusters are used in lighting calculations. This brings huge performance and scalability benefits as most of the time lights are placed so that there are not that many that overlap each other in terms of their sphere of influence, but there may be many distinct point lights visible in the scene. Doing all the lighting calculations for all visible lights in the scene for every pixel on the screen quickly becomes a performance limitation. Clustered forward rendering allows us to make an approximate list of lights that affect each pixel, indeed each surface in the scene (as it works along the view z axis too, unlike tiled/forward+).
* WebGL2 is a platform we want to support and it does not support storage buffers. Uniform buffer bindings are limited to a maximum of 16384 bytes per binding. I used bit shifting and masking to pack the cluster light lists and various indices into a uniform buffer and the 16kB limit is very likely the first bottleneck in scaling the number of lights in a scene at the moment if the lights can affect many clusters due to their range or proximity to the camera (there are a lot of clusters close to the camera, which is an area for improvement). We could store the information in textures instead of uniform buffers to remove this bottleneck though I don’t know if there are performance implications to reading from textures instead if uniform buffers.
* Because of the uniform buffer binding size limitations we can support a maximum of 256 lights with the current size of the PointLight struct
* The z-slicing method (i.e. the mapping from view space z to a depth slice which defines the near and far planes of a cluster) is using the Doom 2016 method. I need to add comments with references to this. It’s an exponential function that simplifies well for the purposes of optimising the fragment shader. xy grid divisions are regular in screen space.
* Some optimisation work was done on the allocation of lights to clusters, which involves intersection tests, and for this number of clusters and lights the system has insignificant cost using a fairly naïve algorithm. I think for more lights / finer-grained clusters we could use a BVH, but at some point it would be just much better to use compute shaders and storage buffers.
* Something else to note is that it is absolutely infeasible to use plain cube map point light shadow mapping for many lights. It does not scale in terms of performance nor memory usage. There are some interesting methods I saw discussed in reference material that I will add a link to which render and update shadow maps piece-wise, but they also need compute shaders to work well. Basically for now you need to sacrifice point light shadows for all but a handful of point lights if you don’t want to kill performance. I set the limit to 10 but that’s just what we had from before where 10 was the maximum number of point lights before this PR.
* I added a couple of debug visualisations behind a shader def that were useful for seeing performance impact of light distribution - I should make the debug mode configurable without modifying the shader code. One mode shows the number of lights affecting each cluster by tinting toward red for few lights or green for many lights (maxes out at 16, but not sure that’s a reasonable max). The other shows which cluster the surface at a fragment belongs to by tinting it with a randomish colour. This can help to understand deeper performance issues due to screen space tiles spanning multiple clusters in depth with divergent shader execution times.
Also, there are more things that could be done as improvements, and I will document those somewhere (I'm not sure where will be the best place... in a todo alongside the code, a GitHub issue, somewhere else?) but I think it works well enough and brings significant performance and scalability benefits that it's worth integrating already now and then iterating on.
* Calculate the light’s effective range based on its intensity and physical falloff and either just use this, or take the minimum of the user-supplied range and this. This would avoid unnecessary lighting calculations for clusters that cannot be affected. This would need to take into account HDR tone mapping as in my not-fully-understanding-the-details understanding, the threshold is relative to how bright the scene is.
* Improve the z-slicing to use a larger first slice.
* More gracefully handle the cluster light list uniform buffer binding size limitations by prioritising which lights are included (some heuristic for most significant like closest to the camera, brightest, affecting the most pixels, …)
* Switch to using a texture instead of uniform buffer
* Figure out the / a better story for shadows
I will also probably add an example that demonstrates some of the issues:
* What situations exhaust the space available in the uniform buffers
* Light range too large making lights affect many clusters and so exhausting the space for the lists of lights that affect clusters
* Light range set to be too small producing visible artifacts where clusters the light would physically affect are not affected by the light
* Perhaps some performance issues
* How many lights can be closely packed or affect large portions of the view before performance drops?
Fills in some gaps we had in our Bevy ECS tracing spans:
* Exclusive systems
* System Commands (for `apply_buffers = true` cases)
* System archetype updates
* Parallel system execution prep
Applogies, had to recreate this pr because of branching issue.
Old PR: https://github.com/bevyengine/bevy/pull/3033
# Objective
Fixes#3032
Allowing a user to create a transparent window
## Solution
I've allowed the transparent bool to be passed to the winit window builder
# Objective
Fixes#3181
## Solution
Refactored `contributors.rs` example:
- Renamed unclear variables
- Split setup system into two separate systems
Co-authored-by: CrazyRoka <rokarostuk@gmail.com>
# Objective
- Checks for NaN in computed NDC space coordinates, fixing unexpected NaN in a fallible (`Option<T>`) function.
## Solution
- Adds a NaN check, in addition to the existing NDC bounds checks.
- This is a helper function, and should have no performance impact to the engine itself.
- This will help prevent hard-to-trace NaN propagation in user code, by returning `None` instead of `Some(NaN)`.
Depends on https://github.com/bevyengine/bevy/pull/3269 for CI error fix.
# Objective
I'm exposing these command encoders so bevy user's can create their own command encoders. This is useful when you want to copy a texture to a texture or create a compute pass manually for example.
Note: I formatted this file which might of changed the order of some exports.
## Solution
Just re-export `CommandEncoder` and `CommandEncoderDescriptor`.
# Objective
- Fix#3188
- Allow creating a `PipelinedSpriteBundle` without an image, just a plain color
```rust
PipelinedSpriteBundle {
sprite: Sprite {
color: Color::rgba(0.8, 0.0, 0.0, 0.3),
custom_size: Some(Vec2::new(500.0, 500.0)),
..Default::default()
},
..Default::default()
}
```
## Solution
- The default impl for `Image` was creating a one pixel image with all values at `1`. I changed it to `255` as picking `1` for it doesn't really make sense, it should be either `0` or `255`
- I created a static handle and added the default image to the assets with this handle
- I changed the default impl for `PipelinedSpriteBundle` to use this handle
# Objective
Fixes recent pipeline errors:
```
error: use of deprecated associated function `std::array::IntoIter::<T, N>::new`: use `IntoIterator::into_iter` instead
--> crates/bevy_render/src/mesh/mesh.rs:467:54
|
467 | .flat_map(|normal| std::array::IntoIter::new([normal, normal, normal]))
| ^^^
|
= note: `-D deprecated` implied by `-D warnings`
Compiling bevy_render2 v0.5.0 (/home/runner/work/bevy/bevy/pipelined/bevy_render2)
error: use of deprecated associated function `std::array::IntoIter::<T, N>::new`: use `IntoIterator::into_iter` instead
--> pipelined/bevy_render2/src/mesh/mesh/mod.rs:287:54
|
287 | .flat_map(|normal| std::array::IntoIter::new([normal, normal, normal]))
| ^^^
|
= note: `-D deprecated` implied by `-D warnings`
error: could not compile `bevy_render` due to previous error
```
## Solution
- Replaced `IntoIter::new` with `IntoIterator::into_iter`
## Suggestions
For me it looks like two equivalent `Mesh` structs with the same methods. Should we refactor it? Or, they will be different in the near future?
Co-authored-by: CrazyRoka <rokarostuk@gmail.com>
# Objective
- New clippy lints with rust 1.57 are failing
## Solution
- Fixed clippy lints following suggestions
- I ignored clippy in old renderer because there was many and it will be removed soon
# Objective
- iOS CI has linker issues https://github.com/bevyengine/bevy/runs/4388921574?check_suite_focus=true
## Solution
- Building for iOS actually requires ~~both iOS SDK for target and~~ macOS SDK for build scripts. ~~I added them both when needed~~ I replaced the iOS SDK with the maOS. This was not an issue on m1 as they are compatible enough to make the build pass.
- This completely confused `shader-sys` which fails to build in this configuration. Luckily as the example now uses the new renderer, I was able to remove the old renderer and depend no more on this lib.
This is confirmed to work:
- on intel mac with simulator
- on m1 mac with simulator
- on m1 mac with real iphone
# Objective
- Add support for `#else` for shader defs
## Solution
- When entering a scope with `#ifdef` or `#ifndef`, if the parent scope is truthy, and the shader definition is also truthy, then the a new scope is pushed onto the scope stack that is also truthy, else falsy. When encountering a subsequent else clause within a scope, if the parent is truthy and the current scope is truthy, then it should become falsy. If the parent scope is truthy and the current scope is falsy then it should become truthy. If the parent scope is falsy, then the current scope should remain falsy as the parent scope takes precedent.
- I added a simple test for an else case.
A sample implementation of how to have `iter()` work on mutable queries without breaking aliasing rules.
# Objective
- Fixes#753
## Solution
- Added a ReadOnlyFetch to WorldQuery that is the `&T` version of `&mut T` that is used to specify the return type for read only operations like `iter()`.
- ~~As the comment suggests specifying the bound doesn't work due to restrictions on defining recursive implementations (like `Or`). However bounds on the functions are fine~~ Never mind I misread how `Or` was constructed, bounds now exist.
- Note that the only mutable one has a new `Fetch` for readonly as the `State` has to be the same for any of this to work
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Changing the underlying image would not update a sprite
## Solution
- 'Detect' if the underlying image changes to update the sprite
Currently, we don't support change detection on `RenderAssets`, so we have to manually check it.
This method at least maintains the bind groups when the image isn't changing. They were cached, so I assume that's important.
This gives us correct behaviour here.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- With #3109 I broke iOS CI: https://github.com/bevyengine/bevy/runs/4374891646?check_suite_focus=true
## Solution
- Fix indentation in makefile
- Adds scheme that is now needed
With this, `make install` works on my m1 Mac but still fails on my intel Mac unless I run something like `make install; cargo build --target x86_64-apple-ios; make install; cargo build --target x86_64-apple-ios; make install`. It seems something is off when executing cargo through `xcodebuild` on my setup but not sure what. So this PR will probably not fix iOS CI 😞
This pull request aims to solve the issue of a lack of documentation in the enum WindowMode
# Objective
- Fixes#3136
## Solution
- Added a few lines of documentation that should document what the enum does better
# Objective
- Remove `cargo-lipo` as [it's deprecated](https://github.com/TimNN/cargo-lipo#maintenance-status) and doesn't work on new Apple processors
- Fix CI that will fail as soon as GitHub update the worker used by Bevy to macOS 11
## Solution
- Replace `cargo-lipo` with building with the correct target
- Setup the correct path to libraries by using `xcrun --show-sdk-path`
- Also try and fix path to cmake in case it's not found but available through homebrew
# Problem
Let's say I am writting a simple bevy plugin, and I want to depend on `bevy_ecs` crate instead of depending on the full `bevy`.
So I write the following:
*Cargo.toml*:
```toml
[dependencies]
bevy_ecs = { git = "https://github.com/bevyengine/bevy.git", rev = "94db0176fecfac7e7e9763f2dc7458a54c105886" }
```
*lib.rs*:
```rust
use bevy_ecs::prelude::*;
#[derive(Debug, Default, Component)
pub struct MyFancyComponent;
```
So far, so good. Everything works. But let's say I want to write some examples for using my plugin. And for theses I'd like to use the `bevy` crate, so that I can write complete examples (rendering stuff, etc.) that are simple and look like what the consumer of my plugin will do (`use bevy::prelude::*` and `DefaultPlugins`)
So I amend my *Cargo.toml*:
```toml
[dependencies]
bevy_ecs = { git = "https://github.com/bevyengine/bevy.git", rev = "94db0176fecfac7e7e9763f2dc7458a54c105886" }
[dev-dependencies]
bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "94db0176fecfac7e7e9763f2dc7458a54c105886", default-features = false }
```
And that leads to a complilation error
```
error[E0433]: failed to resolve: use of undeclared crate or module `bevy`
```
Basically, because `bevy` is in the `dev-dependencies`, the macro (of the production code) decides to use the `bevy::ecs` path instead of `bevy_ecs`. But `bevy` is not available there.
## Solution
This PR fixes the problem. I amend the macro utility responsible of finding the path of a module.
If we try to find a path, we first test if this correspond to a crate that the user directly depend on. (Like, if we search for `bevy_ecs`, we first check if there is a `bevy_ecs` dependency). If yes, we can depend on that directly. Otherwise, we proceed with the existing logic (testing `bevy` and `bevy_internal`)
# Objective
Fixes#3160
Unless I'm mistaken, the problem was caused by a simple typo
## Solution
- Fix the typo
Reference documentation: https://git-scm.com/docs/gitattributes#_eol
## Question
Are there other file-types that should be included here?
# Objective
- Shadow maps should only be sampled if the mesh is a shadow receiver AND shadow mapping is enabled for the light
## Solution
- Fix the logic in the shader
See #3165 and #3175
# Objective
- @superdump was having trouble with this loop in the GLTF loader.
## Solution
- Make it probably linear.
- Measured times:
- Old: 40s, new: 200ms
I think there's still room for improvement. For example, I think making the nodes be in `Arc`s could be a significant gain, since currently there's duplication all the way down the tree.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Use `std140_size_static()` everywhere instead of manual sizes as the crevice rewrite appears to have fixed all the problems as it claimed to do.
I've tested `3d_scene_pipelined`, `bevymark_pipelined`, and `load_gltf_pipelined` and all three look fine.
# Objective
I need to queue my own textures up for font rendering(texture arrays) and I noticed a bunch of `ImageX`, like `ImageDataLayout`, were missing from the render resources exports.
## Solution
Add new exports to render resources.
# Objective
Allow shadow mapping to be enabled/disabled per-light.
## Solution
- NOTE: This PR is on top of https://github.com/bevyengine/bevy/pull/3072
- Add `shadows_enabled` boolean property to `PointLight` and `DirectionalLight` components.
- Do not update the frusta for the light if shadows are disabled.
- Do not check for visible entities for the light if shadows are disabled.
- Do not fetch shadows for lights with shadows disabled.
- I reworked a few types for clarity: `ViewLight` -> `ShadowView`, the bulk of `ViewLights` members -> `ViewShadowBindings`, the entities Vec in `ViewLights` -> `ViewLightEntities`, the uniform offset in `ViewLights` for `GpuLights` -> `ViewLightsUniformOffset`
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
## Shader Imports
This adds "whole file" shader imports. These come in two flavors:
### Asset Path Imports
```rust
// /assets/shaders/custom.wgsl
#import "shaders/custom_material.wgsl"
[[stage(fragment)]]
fn fragment() -> [[location(0)]] vec4<f32> {
return get_color();
}
```
```rust
// /assets/shaders/custom_material.wgsl
[[block]]
struct CustomMaterial {
color: vec4<f32>;
};
[[group(1), binding(0)]]
var<uniform> material: CustomMaterial;
```
### Custom Path Imports
Enables defining custom import paths. These are intended to be used by crates to export shader functionality:
```rust
// bevy_pbr2/src/render/pbr.wgsl
#import bevy_pbr::mesh_view_bind_group
#import bevy_pbr::mesh_bind_group
[[block]]
struct StandardMaterial {
base_color: vec4<f32>;
emissive: vec4<f32>;
perceptual_roughness: f32;
metallic: f32;
reflectance: f32;
flags: u32;
};
/* rest of PBR fragment shader here */
```
```rust
impl Plugin for MeshRenderPlugin {
fn build(&self, app: &mut bevy_app::App) {
let mut shaders = app.world.get_resource_mut::<Assets<Shader>>().unwrap();
shaders.set_untracked(
MESH_BIND_GROUP_HANDLE,
Shader::from_wgsl(include_str!("mesh_bind_group.wgsl"))
.with_import_path("bevy_pbr::mesh_bind_group"),
);
shaders.set_untracked(
MESH_VIEW_BIND_GROUP_HANDLE,
Shader::from_wgsl(include_str!("mesh_view_bind_group.wgsl"))
.with_import_path("bevy_pbr::mesh_view_bind_group"),
);
```
By convention these should use rust-style module paths that start with the crate name. Ultimately we might enforce this convention.
Note that this feature implements _run time_ import resolution. Ultimately we should move the import logic into an asset preprocessor once Bevy gets support for that.
## Decouple Mesh Logic from PBR Logic via MeshRenderPlugin
This breaks out mesh rendering code from PBR material code, which improves the legibility of the code, decouples mesh logic from PBR logic, and opens the door for a future `MaterialPlugin<T: Material>` that handles all of the pipeline setup for arbitrary shader materials.
## Removed `RenderAsset<Shader>` in favor of extracting shaders into RenderPipelineCache
This simplifies the shader import implementation and removes the need to pass around `RenderAssets<Shader>`.
## RenderCommands are now fallible
This allows us to cleanly handle pipelines+shaders not being ready yet. We can abort a render command early in these cases, preventing bevy from trying to bind group / do draw calls for pipelines that couldn't be bound. This could also be used in the future for things like "components not existing on entities yet".
# Next Steps
* Investigate using Naga for "partial typed imports" (ex: `#import bevy_pbr::material::StandardMaterial`, which would import only the StandardMaterial struct)
* Implement `MaterialPlugin<T: Material>` for low-boilerplate custom material shaders
* Move shader import logic into the asset preprocessor once bevy gets support for that.
Fixes#3132
This is a squash-and-rebase of @Ku95's documentation of the new renderer onto the latest `pipelined-rendering` branch.
Original PR is #2884.
Co-authored-by: dataphract <dataphract@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Fix nested shader defs. For example, in:
```rust
#ifdef A
#ifdef B
some code here
#endif
#endif
```
...before this PR, if `A` *is not* defined, and `B` *is* defined, then `some code here` will be output.
## Solution
- Combine the logic of whether the parent and child scope guards are defined and use that as the resulting child scope guard boolean value
# Objective
Add depth prepass and support for opaque, alpha mask, and alpha blend modes for the 3D PBR target.
## Solution
NOTE: This is based on top of #2861 frustum culling. Just lining it up to keep @cart loaded with the review train. 🚂
There are a lot of important details here. Big thanks to @cwfitzgerald of wgpu, naga, and rend3 fame for explaining how to do it properly!
* An `AlphaMode` component is added that defines whether a material should be considered opaque, an alpha mask (with a cutoff value that defaults to 0.5, the same as glTF), or transparent and should be alpha blended
* Two depth prepasses are added:
* Opaque does a plain vertex stage
* Alpha mask does the vertex stage but also a fragment stage that samples the colour for the fragment and discards if its alpha value is below the cutoff value
* Both are sorted front to back, not that it matters for these passes. (Maybe there should be a way to skip sorting?)
* Three main passes are added:
* Opaque and alpha mask passes use a depth comparison function of Equal such that only the geometry that was closest is processed further, due to early-z testing
* The transparent pass uses the Greater depth comparison function so that only transparent objects that are closer than anything opaque are rendered
* The opaque fragment shading is as before except that alpha is explicitly set to 1.0
* Alpha mask fragment shading sets the alpha value to 1.0 if it is equal to or above the cutoff, as defined by glTF
* Opaque and alpha mask are sorted front to back (again not that it matters as we will skip anything that is not equal... maybe sorting is no longer needed here?)
* Transparent is sorted back to front. Transparent fragment shading uses the alpha blending over operator
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Document that the error codes will be rendered on the bevy website (see bevyengine/bevy-website#216)
- Some Cargo.toml files did not include the license or a description field
## Solution
- Readme for the errors crate
- Mark internal/development crates with `publish = false`
- Add missing license/descriptions to some crates
- [x] merge bevyengine/bevy-website#216
# Objective
bevy_ecs has several compile_fail tests that assert lifetime safety. In the past, these tests have been green for the wrong reasons (see e.g. #2984). This PR makes sure, that they will fail if the compiler error changes.
## Solution
Use [trybuild](https://crates.io/crates/trybuild) to assert the compiler errors.
The UI tests are in a separate crate that is not part of the Bevy workspace. This is to ensure that they do not break Bevy's crater builds. The tests get executed by the CI workflow on the stable toolchain.
# Objective
Document that `AssetServer::load()` is asynchronous.
## Solution
Document that `AssetServer::load()` is asynchronous, and that the asset
will not be immediately available once the call returns. Instead,
explain that the user must call `AssetServer::get_load_state()` to
monitor the loading state of an asset.