twgpu 0.4.1

Render Teeworlds and DDNet maps
Documentation
// TODO: Change order of attributes

struct TilemapVertex {
    @location(0) clip_pos_world_pos: vec4<f32>,
    @location(1) color: vec4<f32>,
    @location(2) tilemap_bounds_mipmap_level: vec3<f32>,
};

struct TilemapFragment {
    @builtin(position) clip_pos: vec4<f32>,
    @location(0) world_pos: vec2<f32>,
    @location(1) color: vec4<f32>,
    @location(2) tilemap_bounds_mipmap_level: vec3<f32>,
};

@group(0)
@binding(3)
var tex: texture_2d_array<f32>; // Fragment
@group(0)
@binding(4)
var tex_sampler: sampler; // Fragment
@group(0)
@binding(5)
var tilemap: texture_2d<u32>; // Vertex + Fragment

@vertex
fn vs_main(vertex: TilemapVertex) -> TilemapFragment {
    var frag: TilemapFragment;
    frag.clip_pos = vec4<f32>(vertex.clip_pos_world_pos.xy, 0., 1.);
    frag.world_pos = vertex.clip_pos_world_pos.zw;
    frag.color = vertex.color;
    frag.tilemap_bounds_mipmap_level = vertex.tilemap_bounds_mipmap_level;
    return frag;
}

const TILE_UV_TRANSFORMS = array<mat3x3<f32>, 8>(
    mat3x3<f32>(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0),
    mat3x3<f32>(-1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0),
    mat3x3<f32>(1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0),
    mat3x3<f32>(-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 1.0, 1.0),
    mat3x3<f32>(0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0),
    mat3x3<f32>(0.0, -1.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0),
    mat3x3<f32>(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0),
    mat3x3<f32>(0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 1.0),
);

@fragment
fn fs_main(frag: TilemapFragment) -> @location(0) vec4<f32> {
    let tilemap_bounds = frag.tilemap_bounds_mipmap_level.xy;
    let clamped = clamp(frag.world_pos, vec2<f32>(0.), tilemap_bounds);
    let tile_2d_index = vec2<u32>(floor(clamped));
    let tile = textureLoad(tilemap, tile_2d_index, 0);

    if (tile.x == u32(0)) {
        discard;
    }

    var tile_inner_uv = vec3<f32>(fract(frag.world_pos), 1.);
    var tile_uv_transforms = TILE_UV_TRANSFORMS;
    let tex_coords = tile_uv_transforms[tile.y] * tile_inner_uv;
    let mipmap_level = frag.tilemap_bounds_mipmap_level.z;
    return textureSampleLevel(tex, tex_sampler, tex_coords.xy / tex_coords.z, tile.x, mipmap_level)
        * frag.color; // Apply tilemap color
}