12import package::cluster::{ 13 CLUSTERABLE_OBJECT_TYPE_DECAL, CLUSTERABLE_OBJECT_TYPE_IRRADIANCE_VOLUME, 14 CLUSTERABLE_OBJECT_TYPE_POINT_LIGHT, CLUSTERABLE_OBJECT_TYPE_REFLECTION_PROBE, 15 CLUSTERABLE_OBJECT_TYPE_SPOT_LIGHT, CLUSTERABLE_OBJECT_TYPE_RECT_LIGHT, ClusterMetadata, 16 ClusterableObjectZSlice, calculate_sphere_cluster_bounds, compute_view_from_world_scale 18import package::render::mesh_view_types::{ 19 ClusteredDecals, ClusteredLights, LightProbes, Lights, POINT_LIGHT_FLAGS_SPOT_LIGHT_BIT, POINT_LIGHT_FLAGS_RECT_LIGHT_BIT 21import bevy_render::view::View; 24@group(0) @binding(0) var<storage, read_write> cluster_metadata: ClusterMetadata; 26@group(0) @binding(1) var<storage, read_write> z_slices: array<ClusterableObjectZSlice>; 28@group(0) @binding(2) var<storage> clustered_lights: ClusteredLights; 30@group(0) @binding(3) var<uniform> light_probes: LightProbes; 32@group(0) @binding(4) var<storage> clustered_decals: ClusteredDecals; 35@group(0) @binding(5) var<uniform> lights: Lights; 37@group(0) @binding(6) var<uniform> view: View; 41var<workgroup> shared_farthest_z: array<f32, 64>; 46@compute @workgroup_size(64, 1, 1) 48 @builtin(global_invocation_id) global_invocation_id: vec3<u32>, 49 @builtin(local_invocation_id) local_invocation_id: vec3<u32> 51 let id = global_invocation_id.x; 52 let local_id = local_invocation_id.x; 54 var object_index: u32 = 0u; 55 var object_type: u32 = 0xffffffffu; 56 var position: vec3<f32> = vec3<f32>(0.0); 57 var radius: f32 = 0.0; 68 let last_clustered_light_id = cluster_metadata.clustered_light_count; 69 let last_reflection_probe_id = last_clustered_light_id + 70 cluster_metadata.reflection_probe_count; 71 let last_irradiance_volume_id = last_reflection_probe_id + 72 cluster_metadata.irradiance_volume_count; 73 let last_decal_id = last_irradiance_volume_id + cluster_metadata.decal_count; 77 if (id < last_clustered_light_id) { 80 let flags = clustered_lights.data[object_index].flags; 81 if ((flags & POINT_LIGHT_FLAGS_RECT_LIGHT_BIT) != 0u) { 82 object_type = CLUSTERABLE_OBJECT_TYPE_RECT_LIGHT; 85 CLUSTERABLE_OBJECT_TYPE_POINT_LIGHT, 86 CLUSTERABLE_OBJECT_TYPE_SPOT_LIGHT, 87 (flags & POINT_LIGHT_FLAGS_SPOT_LIGHT_BIT) != 0u 90 position = clustered_lights.data[object_index].position_radius.xyz; 91 radius = clustered_lights.data[object_index].range; 92 } else if (id < last_reflection_probe_id) { 94 object_index = id - last_clustered_light_id; 95 object_type = CLUSTERABLE_OBJECT_TYPE_REFLECTION_PROBE; 96 position = light_probes.reflection_probes[object_index].world_position; 97 radius = light_probes.reflection_probes[object_index].bounding_sphere_radius; 98 } else if (id < last_irradiance_volume_id) { 100 object_index = id - last_reflection_probe_id; 101 object_type = CLUSTERABLE_OBJECT_TYPE_IRRADIANCE_VOLUME; 102 position = light_probes.irradiance_volumes[object_index].world_position; 103 radius = light_probes.irradiance_volumes[object_index].bounding_sphere_radius; 104 } else if (id < last_decal_id) { 106 object_index = id - last_irradiance_volume_id; 107 object_type = CLUSTERABLE_OBJECT_TYPE_DECAL; 108 position = clustered_decals.decals[object_index].world_position; 109 radius = clustered_decals.decals[object_index].bounding_sphere_radius; 112 let view_from_world_scale = compute_view_from_world_scale(view.world_from_view); 113 let is_orthographic = view.clip_from_view[3].w == 1.0; 118 accumulate_farthest_z_value(local_id, position, radius, view_from_world_scale, is_orthographic); 121 if (object_type == 0xffffffffu) { 125 let cluster_bounds = calculate_sphere_cluster_bounds( 128 view.view_from_world, 130 view_from_world_scale, 131 lights.cluster_dimensions.xyz, 132 lights.cluster_factors.zw, 137 for (var z_slice = cluster_bounds.min.z; z_slice <= cluster_bounds.max.z; z_slice += 1u) { 138 try_write_z_slice(object_index, object_type, z_slice); 147fn try_write_z_slice(object_index: u32, object_type: u32, z_slice: u32) { 148 let z_slice_offset = atomicAdd(&cluster_metadata.indirect_draw_params.instance_count, 1u); 149 if (z_slice_offset >= cluster_metadata.z_slice_list_capacity) { 153 z_slices[z_slice_offset].object_index = object_index; 154 z_slices[z_slice_offset].object_type = object_type; 155 z_slices[z_slice_offset].z_slice = z_slice; 160fn accumulate_farthest_z_value( 164 view_from_world_scale: vec3<f32>, 165 is_orthographic: bool 168 let view_from_world_row_2 = transpose(view.view_from_world)[2]; 169 let far_z = dot(-view_from_world_row_2, vec4(position, 1.0)) + radius * view_from_world_scale.z; 170 shared_farthest_z[local_id] = far_z; 175 for (var stride = 32u; stride > 0u; stride /= 2u) { 176 if (local_id < stride) { 177 shared_farthest_z[local_id] = max( 178 shared_farthest_z[local_id], 179 shared_farthest_z[local_id + stride] 186 if (local_id != 0u) { 193 atomicMax(&cluster_metadata.farthest_z, f32_bits_to_sortable_u32(bitcast<u32>(shared_farthest_z[0u]))); 202fn f32_bits_to_sortable_u32(bits: u32) -> u32 { 203 let mask = bitcast<u32>(bitcast<i32>(bits) >> 31) | 0x80000000u;