viewport-lib 0.19.0

3D viewport rendering library
Documentation
// Shadow depth pass for point lights : renders one cubemap face per pass.
//
// Writes linear distance-to-light (normalised by light range) into
// @builtin(frag_depth). The lit pass then compares fragment distance against
// this linear depth, sidestepping the inverse perspective non-linearity that
// makes biasing point shadows awkward.
//
// Group 0: per-face uniform (view_proj + light_pos + range, dynamic offset).
// Group 1: object uniform (model + deform_flags, shared with main pass).
// Group 2: deformer data (shared with main pass).

struct PointFace {
    view_proj: mat4x4<f32>,
    // Packed as vec4 to avoid vec3 + f32 uniform-buffer layout ambiguity:
    // `light_pos.xyz` is the light's world position, `light_pos.w` is the
    // light range (used to normalise frag_depth into [0, 1]).
    light_pos: vec4<f32>,
};

struct Object {
    model: mat4x4<f32>,
    _pad_to_deform: array<vec4<u32>, 13>,
    deform_flags: u32,
};

@group(0) @binding(0) var<uniform> face: PointFace;
@group(1) @binding(0) var<uniform> object: Object;

// Per-vertex deformation hook contract.
// #include "deform.wgsl"

struct VsOut {
    @builtin(position) clip_pos: vec4<f32>,
    @location(0) world_pos:      vec3<f32>,
};

@vertex
fn vs_main(
    @location(0) position: vec3<f32>,
    @builtin(vertex_index) vertex_index: u32,
) -> VsOut {
    var dv = DeformVertex(position, vec3<f32>(0.0, 0.0, 1.0), vertex_index);
    let dctx = DeformContext(object.model, object.model[3].xyz, 0.0, object.deform_flags, 0u);
    dv = viewport_deform_object_space(dv, dctx);
    let world_pos4 = object.model * vec4<f32>(dv.position, 1.0);
    dv.position = world_pos4.xyz;
    dv = viewport_deform_world_space(dv, dctx);
    var out: VsOut;
    out.world_pos = dv.position;
    out.clip_pos = face.view_proj * vec4<f32>(dv.position, 1.0);
    return out;
}

@fragment
fn fs_main(in: VsOut) -> @builtin(frag_depth) f32 {
    let d = length(in.world_pos - face.light_pos.xyz) / max(face.light_pos.w, 1e-5);
    return clamp(d, 0.0, 1.0);
}