dvd-render 0.2.4

render a sequence of terminal screens, optionally encoding them to a video file
Documentation
@group(0) @binding(0) var<storage, read> idx_grid: array<u32>;
@group(0) @binding(1) var<storage, read> atlas: array<u32>;
@group(0) @binding(2) var output_img: texture_storage_2d<rgba8uint, write>;
@group(0) @binding(3) var<uniform> grid_width: u32;
@group(0) @binding(4) var<uniform> grid_height: u32;
@group(0) @binding(5) var<uniform> img_width: u32;
@group(0) @binding(6) var<uniform> img_height: u32;
@group(0) @binding(7) var<storage, read> color_grid: array<u32>;

fn grid_idx(img_pos: vec2<u32>) -> u32 {
	let gx = (img_pos.x * grid_width) / img_width;
	let gy = (img_pos.y * grid_height) / img_height;

	return (gy * grid_width) + gx;
}

fn rel_grid_pos(img_pos: vec2<u32>, glyph_size: vec2<u32>) -> vec2<u32> {
	return img_pos % glyph_size;
}

fn atlas_idx(gidx: u32) -> u32 {
	return idx_grid[gidx];
}

fn sample_colors(gidx: u32) -> vec2<u32> {
	return vec2(color_grid[gidx * 2], color_grid[(gidx * 2) + 1]);
}

fn atlas_val_at(aidx: u32, rg_pos: vec2<u32>, glyph_size: vec2<u32>) -> u32 {
	let ax = rg_pos.x;
	let ay = (aidx * glyph_size.y) + rg_pos.y;
	let abidx = (ay * glyph_size.x) + ax;
	let qidx = abidx / 4;
	let n_byte = abidx % 4;

	return unpack4xU8(atlas[qidx])[n_byte];
}

// lerp between `a` and `b` from `t=0` to `t=255`
fn qlerp(a: vec4<u32>, b: vec4<u32>, t: u32) -> vec4<u32> {
	let a1 = a * t;
	let b1 = b * (255 - t);

	return (a1 + b1) / 255;
}

@compute @workgroup_size(16, 16, 1)
fn sample_atlas(@builtin(global_invocation_id) global_id: vec3<u32>) {
	if (global_id.x >= img_width || global_id.y >= img_height) {
		return;
	}

	let img_pos = vec2(global_id.x, global_id.y);
	let glyph_size = vec2(
		img_width / grid_width,
		img_height / grid_height
	);

	let gidx = grid_idx(img_pos);
	let rg_pos = rel_grid_pos(img_pos, glyph_size);
	let aidx = atlas_idx(gidx);

	let cov = atlas_val_at(aidx, rg_pos, glyph_size);
	let cols = sample_colors(gidx);
	let fg_col = unpack4xU8(cols[0]);
	let bg_col = unpack4xU8(cols[1]);
	textureStore(output_img, img_pos, qlerp(fg_col, bg_col, cov));
}