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#import bevy_pbr::{
2 meshlet_bindings::{
3 meshlet_cluster_meshlet_ids,
4 meshlets,
5 meshlet_cluster_instance_ids,
6 meshlet_instance_uniforms,
7 meshlet_raster_clusters,
8 meshlet_previous_raster_counts,
9 meshlet_visibility_buffer,
10 view,
11 get_meshlet_triangle_count,
12 get_meshlet_vertex_id,
13 get_meshlet_vertex_position,
14 },
15 mesh_functions::mesh_position_local_to_world,
17#import bevy_render::maths::affine3_to_square
18var<immediate> meshlet_raster_cluster_rightmost_slot: u32;
20/// Vertex/fragment shader for rasterizing large clusters into a visibility buffer.
22struct VertexOutput {
23 @builtin(position) position: vec4<f32>,
24#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
25 @location(0) @interpolate(flat) packed_ids: u32,
26#endif
29@vertex
30fn vertex(@builtin(instance_index) instance_index: u32, @builtin(vertex_index) vertex_index: u32) -> VertexOutput {
31 let cluster_in_draw = meshlet_previous_raster_counts[1] + instance_index;
32 let cluster_id = meshlet_raster_cluster_rightmost_slot - cluster_in_draw;
33 let instanced_offset = meshlet_raster_clusters[cluster_id];
34 var meshlet = meshlets[instanced_offset.offset];
36 let triangle_id = vertex_index / 3u;
37 if triangle_id >= get_meshlet_triangle_count(&meshlet) { return dummy_vertex(); }
38 let index_id = vertex_index;
39 let vertex_id = get_meshlet_vertex_id(meshlet.start_index_id + index_id);
41 let instance_uniform = meshlet_instance_uniforms[instanced_offset.instance_id];
43 let vertex_position = get_meshlet_vertex_position(&meshlet, vertex_id);
44 let world_from_local = affine3_to_square(instance_uniform.world_from_local);
45 let world_position = mesh_position_local_to_world(world_from_local, vec4(vertex_position, 1.0));
46 let clip_position = view.clip_from_world * vec4(world_position.xyz, 1.0);
48 return VertexOutput(
49 clip_position,
50#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
51 (cluster_id << 7u) | triangle_id,
52#endif
53 );
56@fragment
57fn fragment(vertex_output: VertexOutput) {
58 let depth = bitcast<u32>(vertex_output.position.z);
59#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
60 let visibility = (u64(depth) << 32u) | u64(vertex_output.packed_ids);
61#else
62 let visibility = depth;
63#endif
64 textureAtomicMax(meshlet_visibility_buffer, vec2<u32>(vertex_output.position.xy), visibility);
67fn dummy_vertex() -> VertexOutput {
68 return VertexOutput(
69 vec4(divide(0.0, 0.0)), // NaN vertex position
70#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
71 0u,
72#endif
73 );
76// Naga doesn't allow divide by zero literals, but this lets us work around it
77fn divide(a: f32, b: f32) -> f32 {
78 return a / b;
Contents