twgpu 0.4.1

Render Teeworlds and DDNet maps
Documentation
struct QuadCorner {
    @location(0) center_offset: vec4<f32>,
    @location(1) tex_coords: vec2<f32>,
    @location(2) color: vec4<f32>,
    @location(3) env_indices: vec2<i32>,
};

struct GroupInfo {
    offset: vec2<f32>,
    parallax: vec2<f32>,
};

struct QuadFragment {
    @builtin(position) clip_position: vec4<f32>,
    @location(0) tex_coords: vec2<f32>,
    @location(1) color: vec4<f32>,
};

struct Camera {
    position: vec2<f32>,
    base_dimensions: vec2<f32>, // In tiles
    zoom: vec2<f32>,
    _padding: vec2<f32>,
};

struct LayerInfo {
    color: vec4<f32>,
    color_env: i32,
    _padding: vec3<f32>,
};

// The y-axis is inverted between the map and gpu coordinate systems. Also for the camera dimensions.
const CORRECTION = vec2<f32>(2., -2.);

@group(0)
@binding(0)
var<uniform> camera: Camera; // Vertex
@group(0)
@binding(1)
var envelope_values: texture_1d<f32>; // Vertex
@group(0)
@binding(2)
var<uniform> group: GroupInfo; // Vertex
@group(0)
@binding(3)
var tex: texture_2d<f32>; // Fragment
@group(0)
@binding(4)
var tex_sampler: sampler; // Fragment

@vertex
fn vs_main(corner: QuadCorner) -> QuadFragment {
    var frag: QuadFragment;
    let pos_env_value = textureLoad(envelope_values, corner.env_indices.y, 0);
    let rotation_sin = vec2<f32>(-corner.center_offset.w, corner.center_offset.z) * vec2<f32>(sin(pos_env_value.z));
    let rotation_cos = corner.center_offset.zw * vec2<f32>(cos(pos_env_value.z));
    var position = corner.center_offset.xy
        - camera.position * group.parallax  // Parallaxed Camera Position
        - group.offset // Group Offset
        + pos_env_value.xy
        + rotation_sin
        + rotation_cos;

    let parallax_zoom = clamp(max(group.parallax.x, group.parallax.y), 0., 1.);
    let parallax_zoom_factor = mix(vec2<f32>(1.), camera.zoom, vec2<f32>(parallax_zoom));
    let zoom_factor = CORRECTION / camera.base_dimensions / parallax_zoom_factor;
    frag.clip_position = vec4<f32>(position * zoom_factor, 0., 1.);

    frag.tex_coords = corner.tex_coords;
    frag.color = corner.color * textureLoad(envelope_values, corner.env_indices.x, 0);
    return frag;
}

@fragment
fn fs_main(frag: QuadFragment) -> @location(0) vec4<f32> {
    return textureSample(tex, tex_sampler, frag.tex_coords) * frag.color;
}