fframes_three_d 1.3.0

3D scenes for fframes: a three.js style scene graph, glTF and STL models, a CPU rasterizer and a wgpu renderer
// The depth pass into a shadow map.

struct ShadowPass {
    view_proj: mat4x4f,
}

// The start of `Draw` in `scene.wgsl`.
struct Draw {
    model: mat4x4f,
}

@group(0) @binding(0) var<uniform> shadow_pass: ShadowPass;
@group(1) @binding(0) var<uniform> draw: Draw;

// The model matrix of one copy of the mesh: the identity for a mesh without copies.
struct InstanceIn {
    @location(1) model_0: vec4f,
    @location(2) model_1: vec4f,
    @location(3) model_2: vec4f,
    @location(4) model_3: vec4f,
}

struct ShadowOut {
    @builtin(position) clip: vec4f,
    @location(0) depth: f32,
}

// The light camera is orthographic: `w` is 1 and the depth is linear across a triangle.
// The rasterizer would clip a caster beyond the near plane, but a caster between the light
// and the map still throws its shadow. The vertex sits in the middle of the depth range,
// and the fragment writes the depth clamped to the near plane, as the CPU rasterizer does.
@vertex
fn vs_shadow(@location(0) position: vec3f, copy: InstanceIn) -> ShadowOut {
    let model = mat4x4f(copy.model_0, copy.model_1, copy.model_2, copy.model_3);
    let clip = shadow_pass.view_proj * (draw.model * (model * vec4f(position, 1.0)));
    var out: ShadowOut;
    out.clip = vec4f(clip.xy, 0.5 * clip.w, clip.w);
    out.depth = clip.z / clip.w;
    return out;
}

@fragment
fn fs_shadow(in: ShadowOut) -> @builtin(frag_depth) f32 {
    return clamp(in.depth, 0.0, 1.0);
}