Search across packages, versions, files, declarations, and comments. Use multiple terms to narrow results (AND), and add @vertex, @fragment, or @compute to filter by shader stage.
1#define_import_path bevy_pbr::irradiance_volume
3#import bevy_pbr::light_probe::query_light_probe
4#import bevy_pbr::mesh_view_bindings::{
5 irradiance_volumes,
6 irradiance_volume,
7 irradiance_volume_sampler,
8 light_probes,
9};
11#ifdef IRRADIANCE_VOLUMES_ARE_USABLE
13// See:
14// https://advances.realtimerendering.com/s2006/Mitchell-ShadingInValvesSourceEngine.pdf
15// Slide 28, "Ambient Cube Basis"
16fn irradiance_volume_light(world_position: vec3<f32>, N: vec3<f32>) -> vec3<f32> {
17 // Search for an irradiance volume that contains the fragment.
18 let query_result = query_light_probe(world_position, /*is_irradiance_volume=*/ true);
20 // If there was no irradiance volume found, bail out.
21 if (query_result.texture_index < 0) {
22 return vec3(0.0f);
23 }
25#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
26 let irradiance_volume_texture = irradiance_volumes[query_result.texture_index];
27#else
28 let irradiance_volume_texture = irradiance_volume;
29#endif
31 let atlas_resolution = vec3<f32>(textureDimensions(irradiance_volume_texture));
32 let resolution = vec3<f32>(textureDimensions(irradiance_volume_texture) / vec3(1u, 2u, 3u));
34 // Make sure to clamp to the edges to avoid texture bleed.
35 var unit_pos = (query_result.light_from_world * vec4(world_position, 1.0f)).xyz;
36 let stp = clamp((unit_pos + 0.5) * resolution, vec3(0.5f), resolution - vec3(0.5f));
37 let uvw = stp / atlas_resolution;
39 // The bottom half of each cube slice is the negative part, so choose it if applicable on each
40 // slice.
41 let neg_offset = select(vec3(0.0f), vec3(0.5f), N < vec3(0.0f));
43 let uvw_x = uvw + vec3(0.0f, neg_offset.x, 0.0f);
44 let uvw_y = uvw + vec3(0.0f, neg_offset.y, 1.0f / 3.0f);
45 let uvw_z = uvw + vec3(0.0f, neg_offset.z, 2.0f / 3.0f);
47 let rgb_x = textureSampleLevel(irradiance_volume_texture, irradiance_volume_sampler, uvw_x, 0.0).rgb;
48 let rgb_y = textureSampleLevel(irradiance_volume_texture, irradiance_volume_sampler, uvw_y, 0.0).rgb;
49 let rgb_z = textureSampleLevel(irradiance_volume_texture, irradiance_volume_sampler, uvw_z, 0.0).rgb;
51 // Use Valve's formula to sample.
52 let NN = N * N;
53 return (rgb_x * NN.x + rgb_y * NN.y + rgb_z * NN.z) * query_result.intensity;
56#endif // IRRADIANCE_VOLUMES_ARE_USABLE
Contents