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::light_probe
3#import bevy_pbr::mesh_view_bindings::light_probes
4#import bevy_pbr::mesh_view_types::LightProbe
6// The result of searching for a light probe.
7struct LightProbeQueryResult {
8 // The index of the light probe texture or textures in the binding array or
9 // arrays.
10 texture_index: i32,
11 // A scale factor that's applied to the diffuse and specular light from the
12 // light probe. This is in units of cd/m² (candela per square meter).
13 intensity: f32,
14 // Transform from world space to the light probe model space. In light probe
15 // model space, the light probe is a 1×1×1 cube centered on the origin.
16 light_from_world: mat4x4<f32>,
17};
19fn transpose_affine_matrix(matrix: mat3x4<f32>) -> mat4x4<f32> {
20 let matrix4x4 = mat4x4<f32>(
21 matrix[0],
22 matrix[1],
23 matrix[2],
24 vec4<f32>(0.0, 0.0, 0.0, 1.0));
25 return transpose(matrix4x4);
28// Searches for a light probe that contains the fragment.
29//
30// TODO: Interpolate between multiple light probes.
31fn query_light_probe(
32 world_position: vec3<f32>,
33 is_irradiance_volume: bool,
34) -> LightProbeQueryResult {
35 var result: LightProbeQueryResult;
36 result.texture_index = -1;
38 var light_probe_count: i32;
39 if is_irradiance_volume {
40 light_probe_count = light_probes.irradiance_volume_count;
41 } else {
42 light_probe_count = light_probes.reflection_probe_count;
43 }
45 for (var light_probe_index: i32 = 0;
46 light_probe_index < light_probe_count && result.texture_index < 0;
47 light_probe_index += 1) {
48 var light_probe: LightProbe;
49 if is_irradiance_volume {
50 light_probe = light_probes.irradiance_volumes[light_probe_index];
51 } else {
52 light_probe = light_probes.reflection_probes[light_probe_index];
53 }
55 // Unpack the inverse transform.
56 let light_from_world =
57 transpose_affine_matrix(light_probe.light_from_world_transposed);
59 // Check to see if the transformed point is inside the unit cube
60 // centered at the origin.
61 let probe_space_pos = (light_from_world * vec4<f32>(world_position, 1.0f)).xyz;
62 if (all(abs(probe_space_pos) <= vec3(0.5f))) {
63 result.texture_index = light_probe.cubemap_index;
64 result.intensity = light_probe.intensity;
65 result.light_from_world = light_from_world;
67 // TODO: Workaround for ICE in DXC https://github.com/microsoft/DirectXShaderCompiler/issues/6183
68 // We can't use `break` here because of the ICE.
69 // So instead we rely on the fact that we set `result.texture_index`
70 // above and check its value in the `for` loop header before
71 // looping.
72 // break;
73 }
74 }
76 return result;
Contents