#define_import_path nightshade_renderer::meshlet_streams
#import nightshade_renderer::meshlet_data::{Meshlet, InstancedOffset, MeshletInstance, CENTIMETERS_PER_METER, octahedral_decode_signed}
/// The shared meshlet streams, and the decode that pulls vertices out of the
/// quantized bitstream by index.
///
/// Group one throughout, so a pass keeps group zero for what is its own. The
/// group is identical for both rasterizers and the resolve, so one layout and
/// one bind group serve all three. A pass that reads only some of these still
/// binds all of them.
@group(1) @binding(0) var<storage, read> raster_clusters: array<InstancedOffset>;
@group(1) @binding(1) var<storage, read> meshlets: array<Meshlet>;
@group(1) @binding(2) var<storage, read> meshlet_indices: array<u32>;
@group(1) @binding(3) var<storage, read> meshlet_vertex_positions: array<u32>;
@group(1) @binding(4) var<storage, read> meshlet_vertex_normals: array<u32>;
@group(1) @binding(5) var<storage, read> meshlet_vertex_uvs: array<vec2<f32>>;
@group(1) @binding(6) var<storage, read> meshlet_instances: array<MeshletInstance>;
fn get_meshlet_vertex_id(index_id: u32) -> u32 {
let packed_index = meshlet_indices[index_id / 4u];
let bit_offset = (index_id % 4u) * 8u;
return extractBits(packed_index, bit_offset, 8u);
}
fn get_meshlet_vertex_position(meshlet: ptr<function, Meshlet>, vertex_id: u32) -> vec3<f32> {
var bits_per_channel = vec3<u32>(
extractBits((*meshlet).packed_bits, 0u, 8u),
extractBits((*meshlet).packed_bits, 8u, 8u),
extractBits((*meshlet).packed_bits, 16u, 8u),
);
let bits_per_vertex = bits_per_channel.x + bits_per_channel.y + bits_per_channel.z;
var start_bit = (*meshlet).start_vertex_position_bit + (vertex_id * bits_per_vertex);
var vertex_position_packed = vec3<u32>(0u);
for (var channel = 0u; channel < 3u; channel++) {
let lower_word_index = start_bit / 32u;
let lower_word_bit_offset = start_bit & 31u;
var next_32_bits = meshlet_vertex_positions[lower_word_index] >> lower_word_bit_offset;
if lower_word_bit_offset + bits_per_channel[channel] > 32u {
next_32_bits |= meshlet_vertex_positions[lower_word_index + 1u] << (32u - lower_word_bit_offset);
}
vertex_position_packed[channel] = extractBits(next_32_bits, 0u, bits_per_channel[channel]);
start_bit += bits_per_channel[channel];
}
var vertex_position = vec3<f32>(vertex_position_packed) + vec3<f32>(
(*meshlet).min_vertex_position_channel_x,
(*meshlet).min_vertex_position_channel_y,
(*meshlet).min_vertex_position_channel_z,
);
let quantization_factor = extractBits((*meshlet).packed_bits, 24u, 8u);
vertex_position /= f32(1u << quantization_factor) * CENTIMETERS_PER_METER;
return vertex_position;
}
fn get_meshlet_vertex_normal(meshlet: ptr<function, Meshlet>, vertex_id: u32) -> vec3<f32> {
let packed_normal = meshlet_vertex_normals[(*meshlet).start_vertex_attribute_id + vertex_id];
return octahedral_decode_signed(unpack2x16snorm(packed_normal));
}
fn get_meshlet_vertex_uv(meshlet: ptr<function, Meshlet>, vertex_id: u32) -> vec2<f32> {
return meshlet_vertex_uvs[(*meshlet).start_vertex_attribute_id + vertex_id];
}