Commit Graph

686 Commits

Author SHA1 Message Date
Dan Aloni 7496e1b639 light: add SunDisk::MARS preset for Mars atmosphere (#24618)
In the atmosphere example we can change between Earth and Mars, but the
size of the sun does not change. This somewhat bothered me from an
astronomical accuarcy.

This commit introduces a new `SunDisk::MARS` constant to accurately
represent the sun’s apparent size when viewed from Mars. The
implementation updates the documentation and adds the corresponding
constant with an angular size of ~21 arcminutes (0.00615 radians).

Key modifications:

- Added `SunDisk::MARS` constant in `directional_light.rs`
- Updated documentation to reference the new Mars preset
- Modified `atmosphere` example to switch sun disk alongside atmosphere
presets

I tested this manually.

---------

Co-authored-by: Máté Homolya <mate.homolya@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-06-17 17:46:34 +00:00
Elabajaba b2b7b452c3 Rename the PbrNeutral tonemapper to KhronosPbrNeutral and improve the docs. (#24530)
# Objective

`PbrNeutral` is poorly named as it implies it's a good default neutral
tonemapper when it really isn't. The docs also don't really describe how
it looks visually unlike the doc comments on the other tonemappers.

## Solution

Rename `PbrNeutral` to `KhronosPbrNeutral` to make it more clear that
it's specifically the Khronos Pbr Neutral tonemapper and not a generic
neutral pbr tonemapper, and improve the docs to better describe it and
essentially recommend against it.
2026-06-05 19:40:06 +00:00
Doonv 3f401d1507 Update examples to use Image::new_target_texture instead of manual image creation when possible (#23715)
# Objective

Fix #19101. (Kinda, this is not the exact solution proposed in that
issue, but it still shortens most of the examples)

## Solution

Most of the images created in examples are for use in render targets.
`Image::new_target_texture` is made for exactly that and significantly
shortens the image creation process.

## Testing

I tested all the examples I changed and they seem to work fine.

--- 

btw for some reason most of the examples use
`TextureFormat::Bgra8UnormSrgb` while the documentation for
`Image::new_target_texture` recommends `TextureFormat::Rgba8UnormSrgb`
for SDR images. What's up with that?

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-22 14:33:16 +00:00
Christophe Dehais 5ec83e1185 Improve Order Independent Transparency example (#22781)
# Objectives

- Use a cleaner UI inspired by other examples
- Add a scene with custom material to fix #20297 

## Testing

Running the example
 ## Showcase 
<details>
<summary>Click to view showcase</summary>
<img width="872" height="732" alt="Screenshot From 2026-02-06 11-35-19"
src="https://github.com/user-attachments/assets/cc294c33-bb53-4ed4-9dce-7558f3bb8fee"
/>
<img width="872" height="732" alt="Screenshot From 2026-02-06 11-35-30"
src="https://github.com/user-attachments/assets/c2b79651-c99e-4bcc-8089-518d11631b9f"
/>
</details>

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-21 15:13:25 +00:00
Schmarni 2c3bdfdd25 Implement Premultiplied Alpha for OIT (#22821)
# Objective

- Allow rendering objects with `AlphaMode::Premultiplied` and
`AlphaMode::Add` while using Order Independent Transparency.
- Fixes #20373.

## Solution

- Store Premultiplied color in the OIT buffer and premultiply in the
case of `AlphaMode::Blend`, this shouldn't have any downsides since
blending was done with premultiplied alpha anyway.
- It might be useful to actively break the `oit_draw` signature by
adding a `premultiply` bool to ensure that shader authors are aware of
the changed meaning of the `color` argument.

## Testing

- These changes have been tested by running the modified
`order_independent_transparency` example, an older version of these
changes has been in use in a project i work on.

---

## Showcase

Here the Red Sphere uses `AlphaMode::Blend`, the Blue Sphere
`AlphaMode::Add` and the Green Sphere `AlphaMode::Premultiplied`.

<img width="1270" height="708" alt="bevy-oit-example"
src="https://github.com/user-attachments/assets/282d7083-458f-4ecd-b098-20b3539de796"
/>

---------

Signed-off-by: Schmarni <marnistromer@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-21 14:01:32 +00:00
GHowe 2837e0372d Expose ssao radius (#24267)
Expose the SSAO sampling radius as a public configuration option on
  ScreenSpaceAmbientOcclusion.

Right now Bevy exposes SSAO quality and constant object thickness, but
the effect
radius is still hardcoded internally in the SSAO shader. That makes it
impossible for
  users to tune the size of the occlusion effect from app code.

  ## Solution

Add a radius: f32 field to ScreenSpaceAmbientOcclusion and preserve
existing behavior
  by defaulting it to the shader’s previous hardcoded value.

To wire that through cleanly, the SSAO render path now uploads a small
SSAO settings
uniform containing both radius and constant_object_thickness, and the
SSAO shader
  reads settings.radius instead of a hardcoded constant.

The SSAO example was also updated to expose the new setting
interactively so the
  feature is discoverable and easy to validate.

  ## Testing

  I tested this by:

  - Running cargo check -p bevy_pbr --quiet
  - Building and running cargo build --example ssao
- Launching target/debug/examples/ssao and verifying the example starts
successfully
- Verifying that the new radius control can be adjusted interactively in
the example
    with Left / Right

  Parts that could use more testing:

  - Visual validation across a wider range of scenes and camera scales
  - Broader GPU/platform coverage, since I only tested locally

  How reviewers can test this:

  1. Run cargo build --example ssao
  2. Launch target/debug/examples/ssao
  3. Use Left / Right to decrease/increase SSAO radius
4. Confirm that larger values produce broader occlusion while the
default matches
     existing behavior

  Platform tested:

  - Linux (EndeavourOS)

  Platforms not tested:

  - Windows
  - macOS
  - Web targets
2026-05-21 12:50:06 +00:00
KategoryBee c046ff2816 Fix switching between earth/mars in atmosphere example (#24349)
# Objective

The keys for switching between earth and mars atmospheres in the
atmosphere example currently do nothing. This change restores the
functionality.

I'm guessing the issue is from the Atmosphere component changing from
using `Transform` to `GlobalTransform` directly in
`Atmosphere::set_default_transform`. The example is expecting to iterate
over a `Transform`, never finds one, and thus never changes the
atmosphere.

## Solution

Change the example to modify `GlobalTransform` instead of `Transform`. 

It may be preferable to modify the example to insert a `Transform` in
set-up. Let me know if this is the case and i'll update the PR.

## Testing

- Tested by running the atmosphere example, hitting the 3 and 4 keys and
seeing sufficiently earth and mars like atmospheres, as well as messages
in the console.
2026-05-21 10:40:10 +00:00
Patrick Walton a0baf1a2c8 Reapply GPU-driven HLOD evaluation, using the new HLOD view origin. (#24343)
This PR undoes the revert of #23115 that was done in #24252. As part of
doing so, it makes GPU-driven visibility range evaluation use the same
semantics, introduced in #24289, as CPU-driven visibility range
evaluation.

The first commit in this PR is the un-revert, and the second commit is
the change to use the new machinery #24289. This means that you can
simply review the second commit (which is very short).

To test, run the `visibility_range` example with `--no-cpu-culling`, and
use the WASD keys to move behind the flight helmet and zoom out, while
closely watching the shadow. Note that the shadow now properly reflects
the LOD of the model.
2026-05-19 00:42:06 +00:00
Kevin Chen dc3a6cbb9c Revert "Move visibility range checking from the CPU to the GPU if NoCpuCulling is specified. (#23115) (#24252)
This reverts commit ebfbc3f5c8.

# Objective

- A third PR that fixes #23991 

## Solution

- Reverts the commit that causes the issue.
- This can be considered if the other solutions (#24197 & #24133) I’ve
put up are not satisfactory, and we need more time to come up with a
good solution (i.e. post 0.19 rc) that:
- Implements PointLight and SpotLight shadow view behavior for gpu vis
range culling that is agreed upon and looks good
- Finalizes an appropriate way of sending this camera view world
position data to the gpu (Immediates vs ViewUniformBuffer or other
Uniform)
- Note: Meshes that are tagged with `NoCpuCulling` will **not** undergo
cpu visibility range culling. That was implemented in a separate PR:
https://github.com/bevyengine/bevy/pull/23107/changes#diff-fec33d34072b7b4be336571ceecf2c10fc9bafd8366c1b29531089b7e3ef621cL745-L748.
If you want to use `VisibilityRange` culling, you will still need to
have CPU culling enabled for the mesh.

## Testing

- `cargo run --example visibility_range` works normal now.
- Tested some other 3d examples make sure the pipeline is ok —
atmosphere, pccm
2026-05-13 08:42:41 +00:00
JMS55 56f414ac7b Solari: Misc fixes (#24203) 2026-05-08 22:29:11 +00:00
Richard Braakman e626337b00 Use the shorthand functions to construct Val in examples (#24096)
This is my first bevy PR, please tell me if I'm doing anything wrong.

# Objective

Contribute to #22695.
Showcase the preferred coding style in all examples.

## Solution

Replace Val:: constructors with the more ergonomic shorthand functions.
Change their float literals to integer literals if they are integral.

Exceptions:
  - const contexts (the shorthand functions are not const)
- inside bsn! macros (these are new and presumably know what they are
doing)
  - in testbed (these are not really examples)
  - Val::ZERO (no helper function)

## Testing

Ran the changed examples before and after, except the library example
`widgets` where I just checked that it still builds.

## Context

There was PR #22765 that fixed the same thing but only in the UI
examples.

---------

Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
2026-05-03 23:54:21 +00:00
ickshonpe b00ff93c87 Remove new_with_ prefix from the TextLayout constuctor functions (#24049)
# Objective

Remove the `new_with_` prefixes from the `TextLayout` constuctor
functions. Generally, the "new" part is redundant and "with" is used by
fluent APIs.

## Solution

Just delete the prefixes, shorten the names (all on `TextLayout`).
* `new_with_justify` -> `justify`
* `new_with_linebreak` -> `linebreak`
* `new_with_no_wrap` -> `no_wrap`
2026-05-01 21:08:18 +00:00
Luo Zhihao 160e26d24b Fix dof and background motion vectors on webgpu (#23629)
# Objective

WebGPU-only fix extracted from #22554 and #22555. Fixes #20459

## Solution

Fix normal + motion vector prepass by setting write mask to empty. This
is a firefox/wgpu bug that it's not validated
https://github.com/gfx-rs/wgpu/issues/9147, but chromium does.

Fix dof with bokeh mode. I guess it's `naga_oil` bug but I'm not sure.

## Testing

I tested dof and skybox examples on web.
2026-04-28 04:44:26 +00:00
Carter Anderson 9c09a3bbc3 Use scene.spawn() in 3d_scene (#23942)
# Objective

`3d_scene` doesn't use the new `scene.spawn()` pattern.

## Solution

- Use it!
2026-04-22 21:32:30 +00:00
breakdown_dog 2317f7be42 Implements post-process lens distortion effects (#23110)
# Objective

- Implements post-process lens distortion effects based on
`EffectStackPlugin`.

## Solution

- This PR's implementation is based on a simplified special case of the
Brown-Conrady model, where p₁ = p₂ = 0 and control is retained only for
k₁ and k₂.
- Additionally, supports controlling the degree of distortion in the
horizontal and vertical directions based on the direction vector.

## Testing

- These effect components can work independently.
- The example works as expected.
- CI

---

## Showcase

- Barrel distortion
<img width="1918" height="1104" alt="tu"
src="https://github.com/user-attachments/assets/6d1b1660-0892-4433-a152-4ac277b9382c"
/>

- Pincushion distortion
<img width="1935" height="1084" alt="ao"
src="https://github.com/user-attachments/assets/2d3c5373-43a8-427c-bd0a-59ccce4448fc"
/>

- Pincushion distortion with no distortion on the x-axis.
<img width="1921" height="1089" alt="ao_no_x"
src="https://github.com/user-attachments/assets/c1b4b55d-7b7f-4cb7-8459-debe4cf2f283"
/>

- With all effects.
<img width="2559" height="1314" alt="cur"
src="https://github.com/user-attachments/assets/724cfa30-9b36-42b9-a480-0d96720f760b"
/>
2026-04-21 16:58:45 +00:00
Carter Anderson 6e9522c5af Asset Value Templates via asset_value() and HandleTemplate::Value (#23839)
# Objective

Temporary simple / suboptimal solution to #23822

It would be very nice to be able to define assets inline in BSN.

## Solution

- Add a new `HandleTemplate::Value` variant, which contains an
`Arc<Mutex<AssetOrHandle<T>>>`
- This template, when first applied, will lock the mutex, insert the
asset value as a new asset, cache the handle in the
`Arc<Mutex<HandleOrTemplate>` and return the handle. Future calls will
lock the mutex and return the cached handle.
- Add `asset_value(SOME_ASSET)` function to improve ergonomics.
- Port `3d_scene` to illustrate

Doing a lock on every spawn is obviously suboptimal. The long term plan
for "inline assets in BSN" is defined in #23822 and will not use this
locking approach.
2026-04-20 00:52:10 +00:00
andriyDev 61127f6d01 Replace all different load variants in AssetServer with a builder. (#23663)
# Objective

- In 0.18, we had 10 different functions that load assets (I'm not even
counting `load_folder`).
- In 0.19, we've even added `load_erased` - but it unfortunately doesn't
support all the features that the other variants support.
- We apparently needed `load_acquire_with_settings_override` which 1)
loads the asset, 2) uses the settings provided, 3) allows reading
unapproved asset paths, and 4) drops a guard once the load completes.
- That's fine if that's necessary. But we needed to create an explicit
variant for that.
- We need fewer load paths!

## Solution

- Create a builder.
- Store all these options dynamically instead of statically handling
each case.
- Have the caller choose a particular "kind" of load when they are
ready: `load`, `load_erased`, `load_untyped`, or `load_untyped_async`.
- I intentionally didn't provide a `load_async` or `load_erased_async`,
since those can be replicated using `load`/`load_erased` +
`AssetServer::wait_for_asset_id` to get the exact same effect.

I am also intentionally leaving `NestedLoader` untouched in this PR, but
a followup will duplicate this API for `NestedLoader`, which should make
it easier to understand.

Unlike the `NestedLoader` API, we aren't doing any type-state craziness,
so the docs are much more clear: users don't need to understand how
type-state stuff works, they just call the handful of methods on the
type. The "cost" here is we now need to be careful about including the
cross product of loads between static asset type, runtime asset type, or
dynamic asset type, crossed with deferred or async. In theory, if we
added more kinds on either side, we would need to expand this cross
product a lot. In practice though, it seems unlikely there will be any
more variants there. (maybe there could be a blocking variant? I don't
think this is a popular opinion though).

A big con here is some somewhat common calls are now more verbose.
Specifically, `asset_server.load_with_settings()` has become
`asset_server.load_builder().with_settings().load()`. I am not really
concerned about this though, since it really isn't that painful.

## Testing

- Tests all pass!

---

## Showcase

Now instead of:

```rust
asset_server.load_acquire_with_settings_override("some_path", |settings: &mut GltfLoaderSettings| { ... }, my_lock_guard);
```

You can instead do:

```rust
asset_server.load_builder()
    .with_guard(my_lock_guard)
    .with_settings(|settings: &mut GltfLoaderSettings| { ... })
    .override_unapproved()
    .load("some_path");
```

We also now cover more variants! For example, you can now load an asset
untyped with a guard, or with override_unapproved, etc.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-04-15 18:32:25 +00:00
Brian Chirls f8bdd2b9db Add PBR Neutral tone mapping (#23761)
# Objective

Add a tonemapping option for for e-commerce, architecture and CAD
applications.

## Solution

Implemented [PBR
Neutral](https://github.com/KhronosGroup/ToneMapping/tree/main/PBR_Neutral)
tone mapping

- Added to 2d and 3d materials, deferred and forward rendering
- Added to bloom_2d example
- Added to tonemapping example

## Testing

Run bloom_2d and tonemapping examples

---------

Co-authored-by: Brian Chirls <brian.chirls@ambr.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2026-04-13 21:56:47 +00:00
Kevin Reid ec254ded7d Make Skybox’s image optional so that Skybox::default() is valid. (#23691)
# Objective

- Partially addresses #23688.
- Prevents use of `Skybox::default()` from causing errors.

## Solution

`Skybox::default()` is problematic because it contains an `Image` that
is not a valid skybox. ~~This change removes the `Default`
implementation and instead provides a `new()` function which takes the
image as a parameter (and also the brightness, which is practically
required).~~ This change makes the `image` field optional so that the
default `None` renders nothing.

Things we could do instead of this:
* Make `Skybox` not implement `Default`. I am informed this is a bad
idea.
* Create a default cubemap image for `default()` to use.

## Testing

Ran the `skybox` and `irradiance_volumes` examples.
2026-04-10 02:41:17 +00:00
Mat 9e7355d490 Calculate UVs and Normals in ConvexPolygonMeshBuilder (#23540)
# Objective

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

## Solution

- Added UVs to `ConvexPolygonMeshBuilder`
- Whilst testing I noticed that normals were also not generated for the
mesh so i've added these as well.

## Testing

- Added `test_convex_polygon` to bevy_mesh which imitates a different
test but for regular polygons.
- Added `Extrusion<ConvexPolygon>` to the 3d_shapes example - you can
use this example to validate UVs and Normals are working as expected.
2026-04-09 04:23:31 +00:00
Máté Homolya 18596dc888 Atmosphere as entity with transforms (#23651)
# Objective

**Anecdotal feedback:** 
- no floating origin support for implementing large-scale worlds, forked
Bevy's atmosphere at
https://github.com/philpax/veldera/blob/main/crates/bevy_pbr_atmosphere_planet/NOTICE.md
- no custom up axis support, resorted to using a custom sky shader for
flight simulator with Z up coordinate system. Bevy's atmosphere appears
tilted at a 90 degree angle with no way of changing it.

## Solution

- Atmosphere component can be spawned stand-alone
- AtmosphereSettings remains on camera
- A closest-to-camera heuristic is used to pick the primary atmosphere
to render. Deliberately no multi-atmosphere support to keep the scope of
this PR small and self contained. See
https://github.com/mate-h/bevy/pull/19 at an attempt.
- `scene_units_to_m` removed in favor of using `Transform`
- Z up now possible by offsetting the viewer position to the equator
- Floating origin systems now possible
- Simplify the `AtmosphereBuffer` / `AtmosphereData` structs to just use
the plain extracted `GpuAtmosphere` struct. this reduces the complexity
of the struct in the mesh view bindings. Since atmosphere settings is
coupled with the rendering pipeline of the atmosphere this makes sense
architecturally.
- We no longer hard code the offset to the north pole from the planet
center in places.

**Why not multi atmosphere:**
The atmosphere uses multiple LUTs (lookup textures) to accelerate the
rendering performance. Some of them are not view dependent:
- Transmittance LUT
- Multiple scattering LUT
- Scattering / density LUTs

These can be coupled and rendered for each atmosphere individually.
However the remainder of the pipeline is view dependent:
- Aerial View LUT
- Sky View LUT
- Render Sky pass

In raymarched rendering mode, these LUTs can be skipped and only the
render sky pass runs sampling on all of the atmospheres with a raymarch
in screen space.

Further, the Sky View LUT uses a local reference frame to concentrate
texel density along the horizon's local up axis. This in turn means it's
coupled with both a _specific_ atmosphere's local coordinates as well as
the view's transform matrix. We cannot consider rendering both
atmospheres into a single LUT for this reason. So it has to be unique
for each pair of (view, atmosphere). Given two views and two atmospheres
we would need 4 of these Sky View LUTs and at some point, raymarched
rendering will become the less expensive option.

Lastly the Render Sky pass needs to happen once per view, we cannot
realistically composite them in sequence with simple dual-source
blending as we do with the scene, this would result in incorrect
scattering integration. This in turn means we need to bind ALL of the
luts calculated previously so a single render sky pass and render aerial
view lut - perhaps making use of array textures. Rely on unified
volumetric ingegration in the raymarching loop: for each light,for each
atmosphere, attenuate inscattering and transmittance along the path
integral. It is suffice to say this change is overall _too complex_ for
the time being and is likely the reason Unreal Engine also do not
support multiple atmospheres. For context: our research is based heavily
on Sebastian Hillarie's work, one of the Unreal graphics engineers.

That being said about multiple atmospheres - I am thinking of this PR as
a segway into unified volumetrics in Bevy. that is: Render the FogVolume
and Atmosphere in a single pass! Making use of the frustum aligned voxel
grid "froxel" approach to accelerate the rendering. This would
drastically increase the performance for scenes wanting to make use of
both the atmosphere and local fog volumes.

## Testing

- Ran the `examples/3d/atmosphere.rs` example.

---

## Showcase

(example screenshot unchanged compared to main.)

```rs
// Spawn earth atmosphere
commands.spawn(Atmosphere::earth(earth_medium));

commands.spawn((
    Camera3d::default(),
    // Can be adjusted to change the rendering quality
    AtmosphereSettings::default(),
));
```

---------

Co-authored-by: Emerson Coskey <emerson@coskey.dev>
2026-04-06 23:08:30 +00:00
Dylan Sechet 128450bdcc Add rectangular area lights (#23288)
# Objective

Adds initial support for rectangle area lights, closing #7662.

Implements Linearly Transformed Cosines ([Heitz et al,
2016](https://eheitzresearch.wordpress.com/415-2/)), with some tricks
from [these
slides](https://advances.realtimerendering.com/s2016/s2016_ltc_rnd.pdf)
and [the reference
implementation](https://github.com/selfshadow/ltc_code).

## Limitations
There's currently no support for:
- Anisotropic materials (there's [a follow-up
paper](https://aakashkt.github.io/ltc_anisotropic.html) that shouldn't
be too hard to implement on top of this, though)
- Shadows
- Textured lights
- Clustering

## Testing

-  Compared results to eevee/cycles, see showcase section.
- Ran the new example with `cargo run --example rect_light --features
free_camera`, and made sure everythign works at grazing angles and from
behind the light.
- Clearcoat and transmission could probably use more testing, I just
made sure nothing looked obviously broken.
 
---

## Showcase


<img width="1919" height="941" alt="Showcase"
src="https://github.com/user-attachments/assets/f506f05c-4869-4387-aeba-d16944497825"
/>
<img width="1919" height="941" alt="Screenshot From 2026-03-11 11-43-42"
src="https://github.com/user-attachments/assets/c4a44903-784f-4c3e-bd44-84c3fe7bff29"
/>


Varying ground plane roughness:


![grid](https://github.com/user-attachments/assets/4426e9df-cde0-450e-b3b7-5e8c2b9fbdcb)
2026-04-06 22:28:53 +00:00
Carter Anderson 535cf401cc Reframe old "scene" terminology as "world serialization" (#23630)
Part 2 of #23619 

In **Bevy 0.19** we are landing a subset of Bevy's Next Generation Scene
system (often known as BSN), which now lives in the `bevy_scene` /
`bevy::scene` crate. However the old `bevy_scene` system still needs to
stick around for a bit longer, as it provides some features that Bevy's
Next Generation Scene system doesn't (yet!):

1. It is not _yet_ possible to write a World _to_ BSN, so the old system
is still necessary for "round trip World serialization".
2. The GLTF scene loader has not yet been ported to BSN, so the old
system is still necessary to spawn GLTF scenes in Bevy.

For this reason, we have renamed the old `bevy_scene` crate to
`bevy_world_serialization`. If you were referencing `bevy_scene::*` or
`bevy::scene::*` types, rename those paths to
`bevy_world_serialization::*` and `bevy::world_serialization::*`
respectively.

Additionally, to avoid confusion / conflicts with the new scene system,
all "scene" terminology / types have been reframed as "world
serialization":

- `Scene` -> `WorldAsset` (as this was always just a World wrapper)
- `SceneRoot` -> `WorldAssetRoot`
- `DynamicScene` -> `DynamicWorld`
    - `DynamicScene::from_scene` -> `DynamicWorld::from_world_asset`
- `DynamicSceneBuilder` -> `DynamicWorldBuilder`
- `DynamicSceneRoot` -> `DynamicWorldRoot`
- `SceneInstanceReady` -> `WorldInstanceReady`
- `SceneLoader` -> `WorldAssetLoader`
- `ScenePlugin` -> `WorldSerializationPlugin`
- `SceneRootTemplate` -> `WorldAssetRootTemplate`
- `SceneSpawner` -> `WorldInstanceSpawner`
- `SceneFilter` -> `WorldFilter`
- `SceneLoaderError` -> `WorldAssetLoaderError`
- `SceneSpawnError` -> `WorldInstanceSpawnError`

Note that I went with `bevy_world_serialization` over
`bevy_ecs_serialization`, as that is what all of the internal features
described themselves as. I think it is both more specific and does a
better job of making itself decoupled from `bevy_ecs` proper.
2026-04-04 00:31:47 +00:00
Luo Zhihao a172a32276 Fix depth prepass with msaa on webgpu (#22531)
# Objective

Fixes #19148.
Should fix #19177, too, because wgpu webgl2 just doesn't support
sampling depth or creating multisampled texture with `TEXTURE_BINDING`.

## Solution

`feature="webgl"` and `feature="webgpu"` can enable together(webgpu
overrides webgl), so we should bind multisampled depth texture even
`webgl` feature is enabled.

## Testing

Run `decal` example
2026-03-29 16:28:25 +00:00
Dylan Sechet 4f40093068 Update filament links (#23517)
# Objective

Quite a few comments in the rendering code link to the filament spec. 
The address changed from https://google.github.io/filament/Filament.html
to https://google.github.io/filament/Filament.md.html at some point.
There is an automated redirect set up, but fragment identifiers are
dropped during the redirect so section links no longer work.

## Solution

Find and replace :)  
I also fixed two of the links that were broken.
2026-03-25 19:50:34 +00:00
JMS55 886ae0e5fa Solari BRDF fixes (#23442)
* Handle non-metals correctly (specular lobe _layered_ over diffuse,
which means two fresnel weighings at the boundary for enter and exit
rays)
* Throw away invalid GGX VNDF samples
* Make sure mirror lobe evaluates to 0 and INF for eval and pdf when not
aligned with mirror direction, and make balance/power heuristic MIS code
handle INF
* Pathtracer now picks a lobe based on fresnel when importance sampling
the BRDF
* Stop taking specular tint into account (making reflectance now a f32
instead of vec3), as it does not work with deferred rendering
* Fresnel is no longer imported from bevy, as it does this weird f90
thing for ambient occlusion

We're still not passing the white furnace test, but oh well.

Many thanks to @devshgraphicsprogramming for the help!

<img width="3206" height="1875" alt="image"
src="https://github.com/user-attachments/assets/e500cc04-9e3e-48bb-9650-0ef282018d79"
/>
<img width="3206" height="1875" alt="image"
src="https://github.com/user-attachments/assets/eb7a1789-a470-43f2-b6ff-4a78b8c269d6"
/>
2026-03-25 16:07:10 +00:00
Luo Zhihao 25ac10100f Enable primitive restart (#22188)
# Objective

Depends on #22187. Fixes #17794. ~For platform consistency I think it’s
reasonable to enable primitive restart by default.~ wgpu will force
primitive restart after https://github.com/gfx-rs/wgpu/pull/8850.

## Solution

Add index format to MeshPipelineKey, replace
`MeshPipelineKey::from_primitive_topology` with
`MeshPipelineKey::from_primitive_topology_and_index`, and enable
`strip_index_format` in render pipeline.

## Testing

I modified the `lines` example to demonstrate primitive restart.

## Showcase

<details>
  <summary>Click to view showcase</summary>

<img width="1550" height="852" alt="屏幕截图_20251218_210849"
src="https://github.com/user-attachments/assets/a7c41943-f22b-415a-8132-98455f21735d"
/>

</details>
2026-03-23 22:30:34 +00:00
Patrick Walton ebfbc3f5c8 Move visibility range checking from the CPU to the GPU if NoCpuCulling is specified. (#23115)
People generally expect GPU-driven renderers to perform LOD selection on
the GPU. Visibility ranges constitute our LOD feature, but they're
currently checked on the CPU. This commit moves that to the GPU and
avoids checking on CPU if `NoCpuCulling` is present.

Note that, even with this patch, LOD buffers (i.e. the on-GPU buffers
that store the visibility ranges) are still built afresh on the CPU
every frame. This will probably be a bottleneck eventually, but that's
for a follow-up.

A `--no-cpu-culling` feature has been added to the `visibility_range`
example, for testing.
2026-03-15 20:40:02 +00:00
atlv 90f90954a0 Fix Meshlets (#23307)
# Objective

- Fix meshlets

## Solution

- Fix loop conditions being inverted (typo bug)
- Fix instance unpack logic being flipped around
- Fix non-existent shaderdef usage to actually match FIRST_CULLING_PASS
-> MESHLET_FIRST_CULLING_PASS (it would be interesting to come up with a
way to fix this class of bug with wesl, but im not really sure how)
- Fix the view projections being flipped inside that shaderdef that
didnt exist
- FIX A HORRIBLE METAL BUG FROM HELL 😭😱😫😵😵‍💫😹🫣😬🤬👺🫠 this cost me a
significant chunk of sanity please appreciate it
https://github.com/gfx-rs/wgpu/pull/9185 (hopefully lands in wgpu 29 and
then its in for bevy 19 once we migrate)

## Testing

- also adds the BunnyWiggler to be able to verify moving instances are
correctly handled with prev transform logic.
- run meshlet example
- It finally works fine again! After 2 releases of it being broken!
2026-03-11 19:49:09 +00:00
DoceAzedo 10243aaab5 Fix AlphaMode::Mask threshold being ignored on unlit materials (#23206)
# Objective

I noticed that changing the `AlphaMode::Mask` threshold value had no
effect on my material. Looking into the PBR shaders, I found out it was
only reading the `alpha_cutoff` for lit materials, alongside
lighting-related properties.

For unlit materials, it was fallbacking to the [0.5
default](https://github.com/bevyengine/bevy/blob/main/crates/bevy_pbr/src/render/pbr_types.wgsl#L86).

## Solution

Moved the `alpha_cutoff` read out of the lit-only block.

## Testing

The transparency_3d example has an unlit sphere with `AlphaMode::Mask`.
I changed its threshold from 0.5 to 0.1 so the difference is visible
(see below).

_I wasn't sure if I should include the example changes, but I think it
might be good to show off the Mask mode in general._

---

## Showcase

Both examples below have the left unlit sphere with
`AlphaMose::Mask(0.1)`. Before the fix, the unlit sphere appears at the
same time at the lit sphere (because it's fallbacking to 0.5). After the
fix, the unlit sphere appears much earlier.

**Before:**


https://github.com/user-attachments/assets/6a8cb76f-507f-45e2-aa79-72ab7e019760

**After:**


https://github.com/user-attachments/assets/875d6587-40ae-4eda-b245-eda1e94656ce

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2026-03-04 07:34:18 +00:00
Máté Homolya acd1091c3e Add Martian atmosphere constant (#22884)
# Objective

- Generally hard to customize meter-based metrics for atmospheres
- Address user concerns described in issue #22882 for creating a mars
atmosphere

## Solution

- Provide a default for mars like atmospheres, a common use case for a
good base to start with.
- The values in this pull request are based on this paper:
https://www.researchgate.net/publication/380239530_Physically_Based_Real-Time_Rendering_of_Atmospheres_using_Mie_Theory
- I created a pre-computed lookup texture for the mie scattering and
enabled the use of such textures within the atmosphere's `medium`
struct. note that this is only 16kb and doesn't weigh much in the repo.
however it could be moved to an asset on the network.
- Full derivation of the texture and constants can be found in this repo
I created: https://github.com/mate-h/mars-atmo

## Testing

- Updated the atmosphere example

---

## Showcase

<img width="1280" height="723" alt="Screenshot 2026-02-14 at 1 20 35 AM"
src="https://github.com/user-attachments/assets/3487c67d-ce46-428e-a62b-88f6d9accbc6"
/>
<img width="1278" height="719" alt="Screenshot 2026-02-14 at 1 18 44 AM"
src="https://github.com/user-attachments/assets/2613182d-27e6-41d6-85fd-57cf40277909"
/>
<img width="1276" height="721" alt="Screenshot 2026-02-14 at 1 17 41 AM"
src="https://github.com/user-attachments/assets/cedb8d51-74eb-4c1c-9aaf-1994f6776b88"
/>
<img width="1278" height="721" alt="Screenshot 2026-02-14 at 1 13 53 AM"
src="https://github.com/user-attachments/assets/357a6907-1012-401b-857b-107f20c24fdd"
/>
<img width="1281" height="721" alt="Screenshot 2026-02-14 at 1 12 30 AM"
src="https://github.com/user-attachments/assets/aac10fed-d06f-4fad-9057-4ea5634d7a78"
/>
<img width="1279" height="722" alt="Screenshot 2026-02-14 at 1 09 26 AM"
src="https://github.com/user-attachments/assets/7ddb3663-e6dd-413f-a771-26ae620da480"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: atlv <email@atlasdostal.com>
2026-03-01 19:31:06 +00:00
Máté Homolya 1ad0fc233e Update atmosphere example fix reflection (#23121)
# Objective

- The atmosphere example had no reflections since PR #22379 , I wanted
to fix this
- Got feedback from pcwalton@ that the spheres need to be removed. These
are no longer needed to test generated environment map lighting since
that also shows up in the water.
- Placed the camera lower such that the volumetric lighting renders
correctly and you can see more of the reflection.

## Solution

- Updated atmosphere example. 

## Testing

- Ran atmosphere example with the proper feature flags
(bluenoise_texture)

---

## Showcase

Before: no reflection, spheres, no "orange glow" in the volumetric fog
towards the top face of the fog volume cuboid. This is likely a bug in
the fog volume rendering depending on the camera angle.
<img width="1280" height="721" alt="Screenshot 2026-02-23 at 10 29
34 AM"
src="https://github.com/user-attachments/assets/4322e38a-7957-48ad-84fd-852ba8c712a8"
/>

After
<img width="1281" height="723" alt="Screenshot 2026-02-23 at 10 29
58 AM"
src="https://github.com/user-attachments/assets/f6777459-b555-4714-a1d0-2df4297fb8f1"
/>
2026-02-24 01:48:38 +00:00
JMS55 7c6ca68204 Solari: Improved many lights test (#23050)
Make the test harder. The previous one was too easy.

<img width="3206" height="1875" alt="image"
src="https://github.com/user-attachments/assets/5454fb1b-8e8f-40bb-98ad-6e10e14e34ee"
/>
2026-02-20 01:11:17 +00:00
Gonçalo Rica Pais da Silva f255b8e57a Upgrade glam, hexasphere, rand & uuid to latest versions (#22928)
# Objective

- `glam`, `hexasphere` & `rand` have released their latest versions,
update Bevy to support them.

## Solution

- The above have been updated to their compatible versions. `rand_distr`
updated as well to match `rand` v0.10 support.
- `rand_chacha` is soft deprecated and no longer used by `rand`, so its
usage has been changed to `chacha20` to match `rand` dep tree.
- `uuid` is in the process of updating to `getrandom` v0.4, which `rand`
v0.10 supports. This PR remains in draft until a new `uuid` release hits
crates.io.
- `RngCore` is now `Rng`, and `Rng` is now `RngExt`, so this required
updating across many files.
- `choose_multiple` method is deprecated, changed to `sample`.

## Testing

- Chase all compiler errors, since this should not regress any already
existing behaviour.
- This must pass CI without regressions.

## Additional Notes

`getrandom` v0.4 doesn't add anything new for Web WASM support, so the
same `wasm_js` feature is used.
2026-02-19 22:17:25 +00:00
charlotte 🌸 7cd6f4db4a Add line width and quad support for wireframes. (#22986)
Adds support for line width (stroke) and quad topology for wireframes.

The triangle line fast path stays the same, but we add a new "wide" draw
function path that uses a specialized vertex shader in order to do the
following via vertex pulling from the appropriate mesh slab:
- Compute screen-space altitudes for our edges.
- Find and suppress diagonals when quad topology is enabled.

Doing this in the vertex shader allows us to avoid needing to de-dupe on
the CPU or spend additional bandwidth uploading a mesh copy at the
expense of a bit of extra shading.

Right now, we have to break batches on the mesh when in the "wide" path,
meaning we don't get full advantage of MDI, but this is mostly because
we don't have a great way to support per-draw data. This could be fixed
in the future.

## Examples:

<img width="1924" height="1126" alt="image"
src="https://github.com/user-attachments/assets/cd73eb9d-f215-413d-ba28-bddc6bd980b0"
/>

<img width="1924" height="1127" alt="Screenshot 2026-02-16 160350"
src="https://github.com/user-attachments/assets/901f5dbb-c900-43b3-bd6b-ce5c9eece82f"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: atlv <email@atlasdostal.com>
2026-02-17 23:16:21 +00:00
Rostyslav Lesovyi 9fd2637846 Add tools to avoid unnecessary AssetEvent::Modified events that lead to rendering performance costs (#16751) (#22460)
# Objective

- Fixes #16751

## Solution

- `Assets::get_mut` now returns a wrapper `AssetMut` type instead of
`&mut impl Asset`.
- `AssetMut` implements `Deref` and `DerefMut`.
- `DerefMut` marks assets as changed.
- when dropped `AssetMut` will add `AssetEvent::Modified` event to a
queue only in case asset was marked as changed.

## Testing

- Did you test these changes? If so, how?
  - No unit tests were added, change is pretty straightforward.
  - Test project: https://github.com/MatrixDev/bevy-feature-16751-test.
    - With change: ~100 fps.
    - Without change: ~15 fps.
- Are there any parts that need more testing?
- I don't really see how this can break anything or add a measurable
overhead.
- `AssetEvent::Modified` will now be sent after the asset was modified
instead of before. It should not affect anything but still worth noting.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Have a big amount of entities that constantly update their materials.
- Properties of those materials should be animated in a stepped maned
(like changing color every 0.1 seconds).
  - Update material only if value has actually changed:
```rust
if material.base_color != new_color {
    material.base_color = new_color;
}
```
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - tested on macos (Mackbook M1)
  - not a platform-specific issue

PS: This is my first PR, so please don’t judge.
2026-02-10 18:39:37 +00:00
breakdown_dog 2949353d9e Remove commented-out code in example post-processing (#22815)
# Objective

- Remove commented-out code in example `post-processing`

## Testing

- CI

---
2026-02-06 07:42:01 +00:00
Luo Zhihao afe0e5d9f5 Implement per-pixel linked list for OIT (#21831)
# Objective

The current OIT stores viewport-sized fragments per layer. It uses much
more memory than it can be.

## Solution

Implements per-pixel linked list for OIT, which saves memory and can
handle more layers. The implementation references
https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/api/oit_linked_lists

## Testing

Tested with the `order_independent_transparency` example. I also added a
new scene in it.

<details>

<img width="1763" height="1098" alt="屏幕截图_20251114_100337"
src="https://github.com/user-attachments/assets/cd76a6be-69db-4700-88a8-34a2ab140c16"
/>

</details>

---------

Co-authored-by: Christophe Dehais <christophe.dehais@gmail.com>
2026-02-05 21:00:36 +00:00
atlv 71dd9ea7db Render Recovery (#22761)
# Objective

- Recover from rendering errors.
- Another step towards render recovery after #22714 #22759 and #16481 

## Solution

- Use `wgpu::Device::set_device_lost_callback` and
`wgpu::Device::on_uncaptured_error` to listen for errors.
- Add a state machine for the renderer
- Update it on error
- Add a `RenderErrorHandler` to let users specify behavior on error by
returning a specific `RenderErrorPolicy`
- This lets us for example ignore validation errors, delete responsible
entities, or reload the renderer if the device was lost.

## Testing

- #22757 with any of
```rs
    .insert_resource(bevy_render::error_handler::RenderErrorHandler(|_, _, _| {
        bevy_render::error_handler::RenderErrorPolicy::StopRendering
    }))
```
```rs
    .insert_resource(bevy_render::error_handler::RenderErrorHandler(|_, _, _| {
        bevy_render::error_handler::RenderErrorPolicy::Recover(default())
    }))
```

Note: no release note yet, as recovery does not exactly work well: this
PR gets us to the point of being able to care about it, but we currently
instantly crash on recover due to gpu resources not existing anymore. We
need to build more resilience before publicizing imo.

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2026-02-05 17:11:16 +00:00
Patrick Walton 5397e9d201 Implement gradual falloff and blending for light probes. (#22610)
Currently, if a fragment overlaps multiple reflection probes and/or
irradiance volumes, Bevy arbitrarily chooses one to provide diffuse
and/or specular light. This is unsightly. The standard approach is to
accumulate radiance and irradiance as a weighted sum. In most engines,
light probes have an artist-controllable *falloff* range, which causes
the weight of each probe to diminish gradually from the center of the
probe.

This PR implements both falloff and blending for light probes.
Reflection probes and irradiance volumes are blended using a weighted
sum. In the case of reflection probes, if the weights sum to less than
1.0, and an environment map is present on the camera, than the
environment map receives the remaining weight necessary to bring the
total weight up to 1.0. This is useful for reflection probes that
correspond to building interiors, to allow smooth transitions between
the indoor building and an exterior environment map when exiting the
building.

Falloff is specified as a fraction of the *interior* of each light probe
that applies gradual falloff, instead of specifying a distance *outside*
the light probe over which the influence diminishes. (See the
documentation comments in `LightProbe` for more detail.) The reason why
I chose to do it this way is that the voxel contents of an irradiance
volume would be ill-defined within the falloff range otherwise. Clamping
to the edge of the 3D voxel cube inside the falloff region (i.e.
extending the edge voxels out) is likely to be incorrect, and extending
the voxel region to encompass the falloff range plus the interior range
would complicate the calculations in the performance-critical PBR
shader.

A new example, `light_probe_blending`, has been added. This example
shows a reflective sphere that moves between two rooms, each of which
has a reflection probe with a falloff range, so the sphere smoothly
blends between the two. The user can pan and zoom the camera.

<img width="2564" height="1500" alt="Screenshot 2026-01-25 215214"
src="https://github.com/user-attachments/assets/67098769-8082-47c3-ae96-4124732b73f6"
/>
2026-02-04 00:24:30 +00:00
atlv 0cb11b841b Transmission cleanup (#22763)
# Objective

- shorten some overly long names

## Solution

- rename

## Testing

- ran transmission example, it works
2026-02-02 23:21:20 +00:00
ickshonpe 6ca4769128 Minimal responsive FontSize support (#22614)
# Objective

Add responsive font sizes supporting rem and viewport units to
`bevy_text` with minimal changes to the APIs and systems.

## Solution

Introduce a new `FontSize` enum:

```rust
pub enum FontSize {
    /// Font Size in logical pixels.
    Px(f32),
    /// Font size as a percentage of the viewport width.
    Vw(f32),
    /// Font size as a percentage of the viewport height.
    Vh(f32),
    /// Font size as a percentage of the smaller of the viewport width and height.
    VMin(f32),
    /// Font size as a percentage of the larger of the viewport width and height.
    VMax(f32),
    /// Font Size relative to the value of the `RemSize` resource.
    Rem(f32),
}
```

This replaces the `f32` value of `TextFont`'s `font_size` field.

The viewport variants work the same way as their respective `Val`
counterparts.

`Rem` values are multiplied by the value of the `RemSize` resource
(which newtypes an `f32`).

`FontSize` provides an `eval` method that takes a logical viewport size
and rem base size and returns an `f32` logical font size. The resolved
logical font size is then written into the `Attributes` passed to Cosmic
Text by `TextPipeline::update_buffer`.

Any text implementation using `bevy_text` must now provide viewport and
rem base values when calling `TextPipeline::update_buffer` or
`create_measure`.

`Text2d` uses the size of the primary window to resolve viewport values
(or `Vec2::splat(1000)` if no primary window is found). This is a
deliberate compromise, a single `Text2d` can be rendered to multiple
viewports using `RenderLayers`, so it's difficult to find a rule for
which viewport size should be chosen.

### Change detection 

`ComputedTextBlock` has two new fields: `uses_viewport_sizes` and
`uses_rem_sizes`, which are set to true in `TextPipeline::update_buffer`
iff any text section in the block uses viewport or rem font sizes,
respectively.

The `ComputedTextBlock::needs_rerender` method has been modified to take
take two bool parameters:
```rust
    pub fn needs_rerender(
        &self,
        is_viewport_size_changed: bool,
        is_rem_size_changed: bool,
    ) -> bool {
        self.needs_rerender
            || (is_viewport_size_changed && self.uses_viewport_sizes)
            || (is_rem_size_changed && self.uses_rem_sizes)
    }
 ```
This ensures that text reupdates will also be scheduled if one of the text section's uses a viewport font size and the local viewport size changed, or if one of the text section's uses a rem font size and the rem size changed.

#### Limitations

There are some limitations because we don't have any sort of font style inheritance yet:

* "rem" units aren't proper rem units, and just based on the value of a resource. 
* "em" units are resolved based on inherited font size, so can't be implemented without inheritance support.

#### Notes

* This PR is quite small and not very technical. Reviewers don't need to be especially familiar with `bevy_text`. Most of the changes are to the examples.

* We could consider using `Val` instead of `FontSize`, then we could use `Val`'s constructor functions which would be much nicer, but some variants might not have sensible interpretations in both UI and Text2d contexts. Also we'd have to make `Val` accessible to `bevy_text`.

## Testing

The changes to the text systems are relatively trivial and easy to understand.  I already added a minor change to the `text` example to use `Vh` font size for the "hello bevy" text in the bottom right corner. If you change the size of the window, you should see the text change size in response. The text initially flickers before it updates because of some unrelated asset/image changes that mean that font textures aren't ready until the frame after the text update that changes the font size.

Most of the example migrations were automated using regular expressions, and there are bound to be mistakes in those changes. It's infeasible to check every single example thoroughly, but it's early enough in the release cycle that I don't think we should be too worried if a few bugs slip in.

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-02-02 22:52:33 +00:00
charlotte 🌸 f1f41547fc Replace RenderGraph with systems (#22144)
# render-graph-as-systems

> [!NOTE]
> Remember to check hide whitespace in diff view options when reviewing
this PR

This PR removes the `RenderGraph` in favor of using systems.

## Motivation

The `RenderGraph` API was originally created when the ECS was
significantly more immature. It was also created with the intention of
supporting an input/output based slot system for managing resources that
has never been used. While resource management is an important potential
use of a render graph, current rendering code doesn't make use of any
patterns relating to it.

Since the ECS has improved, the functionality of `Schedule` has
basically become co-extensive with what the `RenderGraph` API is doing,
i.e. ordering bits of system-like logic relative to one another and
executing them in a big chunk. Additionally, while there's still desire
for more advanced techniques like resource management in the graph, it's
desirable to implement those in ECS terms rather than creating more
`RenderGraph` specific abstraction.

In short, this sets us up to iterate on a more ECS based approach, while
deleting ~3k lines of mostly unused code.

## Implementation

At a high level: We use `Schedule` as our "sub-graph." Rather than
running the graph, we run a schedule. Systems can be ordered relative to
one another.

The render system uses a `RenderGraph` schedule to define the "root" of
the graph. `core_pipeline` adds a `camera_driver` system that runs the
per-camera schedules. This top level schedule provides an extension
point for apps that may want to do custom rendering, or non-camera
rendering.

### `CurrentView` / `ViewQuery`

When running schedules per-camera in the `camera_driver` system, we
insert a `CurrentView` resource that's used to mark the currently
iterating view. We also add a new param `ViewQuery` that internally uses
this resource to execute the query and skip the system if it doesn't
match as a convenience.

### `RenderContext`

The `RenderContext` is now a system param that wraps a `Deferred` for
tracking the state of the current command encoder and queued buffers.

### `SystemBuffer`

We use an system buffer impl to track command encoders in the render
context and rely on apply deferred in order to encode them all.
Currently, this encodes them in series. There are likely opportunities
here to make this more efficient.

## Benchmarks

### Bistro

<img width="1635" height="825" alt="Screenshot 2026-01-15 at 7 57 40 PM"
src="https://github.com/user-attachments/assets/8e55a959-89a3-4947-bfc5-c04780f82e7b"
/>

### Caldera

<img width="1631" height="828" alt="Screenshot 2026-01-15 at 8 13 06 PM"
src="https://github.com/user-attachments/assets/e7e8ae0d-41c3-430f-8b4d-9099b3d922a0"
/>

## Future steps

There are a number of exciting potential changes that could follow here:

- We can explore adding something like a read-only schedule to pick up
some more potential parallelism in graph execution.
- We can use more things like run conditions in order to prevent systems
from running at all in the first place.
- We can explore things like automating resource creation via system
params.

## TODO:
- [x] Make sure 100% of everything still works.
- [x] Benchmark to make sure we don't regress performance
- [x] Re-add docs

---------

Co-authored-by: atlas dostal <rodol@rivalrebels.com>
2026-01-28 21:09:59 +00:00
atlv 419f25d321 move Atmosphere to bevy_light (#22709)
# Objective

- Another day, another step towards scene description outside of render
crates

## Solution

- Move Atmosphere to bevy_light.

## Testing

- atmosphere example looks good.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-01-27 21:49:59 +00:00
atlv 3ae32d500b move transmission stuff to bevy_pbr (#22687)
# Objective

- It makes no sense for bevy_camera::Camera3d to talk about transmission
quality settings
- transmission is not a core thing its a purely pbr thing, why is in
bevy_core_pipelines
- the implementation is generally scattered all over the place
- ScreenSpaceTransmissionQuality is a resource for no reason at all

## Solution

- split out a struct for transmission stuff
- consolidate stuff in bevy_pbr
- make ScreenSpaceTransmissionQuality not a resource

## Testing

transmission example looks good
2026-01-25 20:36:42 +00:00
atlv 65abe44a2f move Skybox to bevy_light (#22682)
# Objective

- Skybox is a main world component for scene definition, it shouldnt be
in a rendering crate

## Solution

- Move it to bevy_light, alongside EnvironmentMapLight component sibling
which lets it influence lighting.

## Testing

- skybox example works
2026-01-25 01:16:38 +00:00
atlv badca1c48a move Hdr to bevy_camera (#22683)
# Objective

- whether a Camera needs to draw Hdr content or not is an aspect of
scene description
- as such, it should live in a non-rendering crate

## Solution

- move it to bevy_camera
- dont extract it to the render world anymore. audited all usages of it
and none are in the render world queries, instead `ExtractedCamera::hdr`
is used.

## Testing

- manual spot check of a few examples
- example runner regression test
2026-01-24 21:32:24 +00:00
JMS55 7b0a905d8f Fix timestamp queries for DLSS (#22668)
Timestamp queries have never worked for DLSS because I setup them up
wrong when I initially wrote the code. This fixes it (and adds DLSS-RR
time to the Solari example).

Basically we need to put the timestamp start on the command buffer
before DLSS, and then the timestamp end on the command buffer right
after DLSS.

Debug groups had to be removed because I can't use them across different
command encoders.
2026-01-24 19:19:05 +00:00
Patrick Walton 07bdee178c Move occlusion culling out of the experimental namespace. (#22631)
With #22603 landed, all known issues that could cause Bevy to cull
meshes that shouldn't have been culled are fixed, so there now seems to
be consensus that we can remove occlusion culling from the
`experimental` namespace. This patch does that (and in fact removes the
`experimental` module from `bevy_render` entirely, as it's now empty).
2026-01-21 22:37:59 +00:00
atlv dd230f2f4a Parallax-corrected cubemaps for reflection probes (adopted) (#22582)
# Objective

- Adopts and closes #22288

## Solution

- change the example to make it easier to tell if the reflection is
actually matching
- fix the assets because the reflection doesnt actually match
- throw the assets into the asset repo
https://github.com/bevyengine/bevy_asset_files/pull/7

## Testing

- running the example

---------

Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-01-20 20:18:34 +00:00