textgrid-rust/src/shader.wgsl

68 lines
No EOL
2.4 KiB
WebGPU Shading Language

struct GridParams {
cols: u32,
rows: u32,
cell_w: f32,
cell_h: f32,
window_w: f32,
window_h: f32,
atlas_cols: u32,
atlas_rows: u32,
atlas_size: f32,
flip_y: f32,
_pad1: u32,
_pad2: u32,
}
@group(0) @binding(0) var font_atlas: texture_2d<f32>;
@group(0) @binding(1) var font_sampler: sampler;
@group(0) @binding(2) var<uniform> grid: GridParams;
@group(0) @binding(3) var<storage, read> char_data: array<vec4<u32>>;
struct VIn { @location(0) pos: vec2f, @location(1) uv: vec2f, };
struct VOut { @builtin(position) position: vec4f, @location(0) uv: vec2f, @location(1) fg: vec4f, @location(2) bg: vec4f, @location(3) attr: u32, @location(4) cell_uv: vec2f, };
fn unpack_color(packed: u32) -> vec4f {
return vec4f(
f32((packed >> 24u) & 0xFFu) / 255.0,
f32((packed >> 16u) & 0xFFu) / 255.0,
f32((packed >> 8u) & 0xFFu) / 255.0,
1.0,
);
}
@vertex
fn vs_main(input: VIn, @builtin(instance_index) iid: u32) -> VOut {
let col = iid % grid.cols;
let row = iid / grid.cols;
let x = f32(col) * grid.cell_w + input.pos.x * grid.cell_w;
let y = f32(row) * grid.cell_h + input.pos.y * grid.cell_h;
let ndc_x = x / grid.window_w * 2.0 - 1.0;
let ndc_y = grid.flip_y * (1.0 - y / grid.window_h * 2.0);
var out: VOut;
out.position = vec4f(ndc_x, ndc_y, 0.0, 1.0);
let entry = char_data[iid];
out.fg = unpack_color(entry.y);
out.bg = unpack_color(entry.z);
out.attr = entry.w;
let slot = entry.x;
let ac = slot % grid.atlas_cols;
let ar = slot / grid.atlas_cols;
let uvx = (f32(ac) + input.uv.x) * grid.cell_w / grid.atlas_size;
let uvy = (f32(ar) + input.uv.y) * grid.cell_h / grid.atlas_size;
out.uv = vec2f(uvx, uvy);
out.cell_uv = input.uv;
return out;
}
@fragment
fn fs_main(@location(0) uv: vec2f, @location(1) fg: vec4f, @location(2) bg: vec4f, @location(3) attr: u32, @location(4) cell_uv: vec2f) -> @location(0) vec4f {
let texel = textureSample(font_atlas, font_sampler, uv);
let glyph_alpha = texel.a;
let is_color = texel.r != 1.0 || texel.g != 1.0 || texel.b != 1.0;
let glyph_color = select(fg.rgb * texel.rgb, texel.rgb, is_color);
var color = vec4f(mix(bg.rgb, glyph_color, glyph_alpha), 1.0);
if (attr & 4u) != 0u && cell_uv.y >= 0.79 && cell_uv.y <= 0.85 {
color = vec4f(fg.rgb, 1.0);
}
return color;
}