brepkit-render 3.2.13

Offscreen GPU renderer for brepkit B-Rep solids
Documentation
// Mesh pass: MVP transform + Lambert headlight shading.
// Writes shaded color to the color target and the triangle's FaceId to the
// id target. Positions arrive relative to the model center (RTC); the f64
// center is already folded into `view_proj` on the CPU.

struct Globals {
    view_proj: mat4x4<f32>,
    // World-space direction the camera looks along (the headlight points
    // opposite this). xyz used; w is padding for 16-byte alignment.
    view_dir: vec4<f32>,
    ambient: f32,
    // Encoded FaceId (index + 1) to highlight, or 0 for "no selection". Matches
    // the encoding written to the id target so a picked id round-trips directly.
    selected_id: u32,
    _pad1: f32,
    _pad2: f32,
};

@group(0) @binding(0)
var<uniform> globals: Globals;

struct VsIn {
    @location(0) position: vec3<f32>,
    @location(1) normal: vec3<f32>,
    @location(2) face_id: u32,
};

struct VsOut {
    @builtin(position) clip_position: vec4<f32>,
    @location(0) normal: vec3<f32>,
    @location(1) @interpolate(flat) face_id: u32,
};

struct FsOut {
    @location(0) color: vec4<f32>,
    @location(1) face_id: u32,
};

@vertex
fn vs_main(in: VsIn) -> VsOut {
    var out: VsOut;
    out.clip_position = globals.view_proj * vec4<f32>(in.position, 1.0);
    out.normal = in.normal;
    out.face_id = in.face_id;
    return out;
}

@fragment
fn fs_main(in: VsOut) -> FsOut {
    let n = normalize(in.normal);
    // Headlight points along -view_dir (toward the camera). Two-sided so
    // back-facing triangles still receive light rather than going black.
    let light_dir = -normalize(globals.view_dir.xyz);
    let diffuse = abs(dot(n, light_dir));
    let intensity = clamp(globals.ambient + (1.0 - globals.ambient) * diffuse, 0.0, 1.0);

    // Tint the selected face warm orange; everything else uses the neutral base.
    var base = vec3<f32>(0.72, 0.74, 0.78);
    if (globals.selected_id != 0u && in.face_id == globals.selected_id) {
        base = vec3<f32>(0.95, 0.55, 0.18);
    }
    var out: FsOut;
    out.color = vec4<f32>(base * intensity, 1.0);
    out.face_id = in.face_id;
    return out;
}