nightshade-renderer 0.57.0

GPU-driven wgpu renderer with a built-in frame graph.
#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);
}