#define_import_path nightshade_renderer::meshlet_data
/// The layout and packing every meshlet shader shares.
///
/// The bit split arrives from the cpu as a shader def: it is derived from the
/// triangles a meshlet holds, which the cpu also uses to size the draw and the
/// dispatch.
const CENTIMETERS_PER_METER: f32 = 100.0;
/// Bits the payload gives the triangle index within its cluster.
const MESHLET_TRIANGLE_ID_BITS: u32 = #{MESHLET_TRIANGLE_ID_BITS};
struct Meshlet {
start_vertex_position_bit: u32,
start_vertex_attribute_id: u32,
start_index_id: u32,
packed_counts: u32,
packed_bits: u32,
min_vertex_position_channel_x: f32,
min_vertex_position_channel_y: f32,
min_vertex_position_channel_z: f32,
}
/// One rasterizable cluster: the instance it belongs to and the meshlet it
/// draws.
struct InstancedOffset {
instance_id: u32,
offset: u32,
}
/// Padding is spelled as scalars rather than a `vec3<u32>` on purpose: a vec3
/// aligns to 16 bytes and would stride this struct at 96 rather than the 80 the
/// cpu side writes, so every instance past the first would read the wrong
/// transform. The first instance reads from offset zero either way, which is
/// what makes that mistake invisible until a second instance exists.
struct MeshletInstance {
world_from_local: mat4x4<f32>,
root_bvh_node_index: u32,
material_id: u32,
padding_y: u32,
padding_z: u32,
}
/// What a covered pixel carries: which cluster, and which triangle of it. Both
/// rasterizers write this and the resolve reads it.
fn meshlet_payload(cluster_id: u32, triangle_id: u32) -> u32 {
return (cluster_id << MESHLET_TRIANGLE_ID_BITS) | triangle_id;
}
fn meshlet_payload_cluster(payload: u32) -> u32 {
return payload >> MESHLET_TRIANGLE_ID_BITS;
}
fn meshlet_payload_triangle(payload: u32) -> u32 {
return payload & ((1u << MESHLET_TRIANGLE_ID_BITS) - 1u);
}
fn get_meshlet_triangle_count(meshlet: ptr<function, Meshlet>) -> u32 {
return extractBits((*meshlet).packed_counts, 8u, 8u);
}
fn octahedral_decode_signed(encoded: vec2<f32>) -> vec3<f32> {
var normal = vec3<f32>(encoded.xy, 1.0 - abs(encoded.x) - abs(encoded.y));
let wrapped = (1.0 - abs(normal.yx)) * select(vec2<f32>(-1.0), vec2<f32>(1.0), normal.xy >= vec2<f32>(0.0));
if normal.z < 0.0 {
normal = vec3<f32>(wrapped, normal.z);
}
return normalize(normal);
}