Commit 7b866ee
Environment Map Filtering GPU pipeline (#19076)
# Objective
This PR implements a robust GPU-based pipeline for dynamically
generating environment maps in Bevy. It builds upon PR #19037, allowing
these changes to be evaluated independently from the atmosphere
implementation.
While existing offline tools can process environment maps, generate mip
levels, and calculate specular lighting with importance sampling,
they're limited to static file-based workflows. This PR introduces a
real-time GPU pipeline that dynamically generates complete environment
maps from a single cubemap texture on each frame.
Closes #9380
## Solution
Implemented a Single Pass Downsampling (SPD) pipeline that processes
textures without pre-existing mip levels or pre-filtered lighting data.
Single Pass Downsampling (SPD) pipeline:
- accepts any square, power-of-two cubemap up to 8192 × 8192 per face
and generates the complete mip chain in one frame;
- copies the base mip (level 0) in a dedicated compute dispatch
(`copy_mip0`) before the down-sampling pass;
- performs the down-sampling itself in two compute dispatches to fit
within subgroup limits;
- heavily inspired by Jasmine's prototype code.
Pre-filtering pipeline:
- generates the specular Radiance Map using bounded-VNDF GGX importance
sampling for higher quality highlights and fewer fireflies;
- computes the diffuse Irradiance Map with cosine-weighted hemisphere
sampling;
- mirrors the forward-/reverse-tonemap workflow used by TAA instead of
exposing a separate *white-point* parameter;
- is based on the resources below together with the “Bounded VNDF
Sampling for Smith-GGX Reflections” paper.
The pre-filtering pipeline is largely based on these articles:
-
https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/
- https://bruop.github.io/ibl/
-
https://gpuopen.com/download/Bounded_VNDF_Sampling_for_Smith-GGX_Reflections.pdf
> The forward-/reverse-tonemap trick removes almost all fireflies
without the need for a separate white-point parameter.
Previous work: #9414
## Testing
The `reflection_probes.rs` example has been updated:
- The camera starts closer to the spheres so the reflections are easier
to see.
- The GLTF scene is spawned only when the reflection probe mode is
active (press Space).
- The third display mode (toggled with Space) shows the generated
cubemap chain.
- You can change the roughness of the center sphere with the Up/Down
keys.
## Render Graph
Composed of two nodes and a graph edge:
```
Downsampling -> Filtering
```
Pass breakdown:
```
dowsampling_first_pass -> dowsampling_second_pass ->
radiance_map_pass -> irradiance_map_pass
```
<img width="1601" height="2281" alt="render-graph"
src="https://github.com/user-attachments/assets/3c240688-32f7-447a-9ede-6050b77c0bd1"
/>
---
## Showcase
<img width="2564" height="1500" alt="image"
src="https://github.com/user-attachments/assets/56e68dd7-9488-4d35-9bba-7f713a3e2831"
/>
User facing API:
```rust
commands.entity(camera)
.insert(GeneratedEnvironmentMapLight {
environment_map: world.load_asset("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
..default()
});
```
## Computed Environment Maps
To use fully dynamic environment maps, create a new placeholder image
handle with `Image::new_fill`, extract it to the render world. Then
dispatch a compute shader, bind the image as a 2d array storage texture.
Anything can be rendered to the custom dynamic environment map.
This is already demonstrated in PR #19037 with the `atmosphere.rs`
example.
We can extend this idea further and run the entire PBR pipeline from the
perspective of the light probe, and it is possible to have some form of
global illumination or baked lighting information this way, especially
if we make use of irradiance volumes for the realtime aspect. This
method could very well be extended to bake indirect lighting in the
scene.
#13840 should make this possible!
## Notes for reviewers
This PR no longer bundles any large test textures.
---------
Co-authored-by: atlas <[email protected]>1 parent 6634300 commit 7b866ee
File tree
18 files changed
+2232
-117
lines changed- crates
- bevy_light/src
- bevy_pbr/src
- light_probe
- render
- bevy_solari/src
- pathtracer
- realtime
- scene
- examples/3d
- release-content/release-notes
18 files changed
+2232
-117
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
111 | 143 | | |
112 | 144 | | |
113 | 145 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
91 | | - | |
92 | | - | |
| 91 | + | |
| 92 | + | |
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| |||
133 | 133 | | |
134 | 134 | | |
135 | 135 | | |
136 | | - | |
| 136 | + | |
137 | 137 | | |
138 | 138 | | |
139 | 139 | | |
| |||
185 | 185 | | |
186 | 186 | | |
187 | 187 | | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
188 | 195 | | |
189 | 196 | | |
190 | 197 | | |
| |||
273 | 280 | | |
274 | 281 | | |
275 | 282 | | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
276 | 287 | | |
277 | 288 | | |
278 | 289 | | |
279 | 290 | | |
280 | 291 | | |
281 | 292 | | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
282 | 296 | | |
283 | 297 | | |
284 | 298 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
0 commit comments