Skip to main content

CANOPY_COOKIE_WGSL

Constant CANOPY_COOKIE_WGSL 

Source
pub const CANOPY_COOKIE_WGSL: &str = r#"
struct CanopyParams {
    center_extent: vec4f,
    sun_receiver: vec4f,
    wind: vec4f,
    direction: vec4f,
    projected_extent: vec4f,
    mode_sharpness: vec4f,
}
struct Card {
    position_size: vec4f,
    right_size: vec4f,
    up: vec4f,
    pivot_level: vec4f,
    motion_color: vec4f,
    atlas: vec4f,
    lod: vec4f,
}
@group(0) @binding(0) var<uniform> params: CanopyParams;
@group(0) @binding(1) var<storage, read> cards: array<Card>;
@group(0) @binding(2) var alpha_atlas: texture_2d<f32>;
@group(0) @binding(3) var alpha_sampler: sampler;
fn tree_sway(rest: vec3f, pivot: vec3f, level: f32, stiffness: f32, wind_time: f32, strength: f32, direction: vec3f) -> vec3f {
    let d = normalize(direction.xz + vec2f(0.00001, 0.0));
    let arm = length(rest - pivot);
    let phase = wind_time * (0.7 + level * 0.41) + pivot.x * 0.83 + pivot.z * 0.67;
    let bend = sin(phase) * strength * (1.0 - stiffness) * arm * (0.012 + 0.009 * level);
    return rest + vec3f(d.x * bend, -abs(bend) * 0.12, d.y * bend);
}
struct Varying { @builtin(position) clip: vec4f, @location(0) uv: vec2f, @location(1) @interpolate(flat) atlas: vec4f, @location(2) @interpolate(flat) lod: vec4f, }
@vertex fn vertex(@builtin(vertex_index) vertex: u32, @builtin(instance_index) instance: u32) -> Varying {
    let card = cards[instance];
    let corners = array<vec2f, 6>(vec2f(-1.0,-1.0), vec2f(1.0,-1.0), vec2f(-1.0,1.0), vec2f(-1.0,1.0), vec2f(1.0,-1.0), vec2f(1.0,1.0));
    let corner = corners[vertex];
    let rest = card.position_size.xyz + card.right_size.xyz * card.position_size.w * corner.x + card.up.xyz * card.right_size.w * corner.y;
    let moved = tree_sway(rest, card.pivot_level.xyz, card.pivot_level.w, card.motion_color.x, params.wind.x, params.wind.y, params.direction.xyz) + vec3f(params.center_extent.x, params.wind.z, params.center_extent.y);
    let sun_input = params.sun_receiver.xyz;
    let sun = select(vec3f(0.0, 1.0, 0.0), sun_input / max(length(sun_input), 1e-6), length(sun_input) > 1e-6);
    let reference = select(vec3f(0.0, 1.0, 0.0), vec3f(0.0, 0.0, 1.0), abs(sun.y) > 0.99);
    let axis_u = normalize(cross(sun, reference));
    let axis_v = cross(axis_u, sun);
    let projected = vec2f(dot(moved, axis_u), dot(moved, axis_v));
    let uv = (projected - params.projected_extent.xy) / params.projected_extent.zw + vec2f(0.5);
    var out: Varying;
    out.clip = vec4f(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0, 0.0, 1.0);
    out.uv = (corner + vec2f(1.0)) * 0.5;
    out.atlas = card.atlas;
    out.lod = card.lod;
    return out;
}
@fragment fn fragment(input: Varying) -> @location(0) f32 {
    let uv = input.atlas.xy + input.uv * input.atlas.zw;
    let weight = select(1.0 - input.lod.x, input.lod.x, input.lod.z > 0.5);
    return textureSample(alpha_atlas, alpha_sampler, uv).r * weight;
}
"#;