pub const BG_VERTEX: &str = r#" struct BgInstance { col: u32, row: u32, bg_r: u32, bg_g: u32, bg_b: u32, bg_a: u32, }; @group(0) @binding(0) var instances: array; struct Uniforms { cell_width: f32, cell_height: f32, screen_cols: u32, screen_rows: u32, }; @group(0) @binding(1) var uniforms: Uniforms; struct VertexOutput { @builtin(position) position: vec4, @location(0) color: vec4, }; @vertex fn main(@builtin(vertex_index) vertex_idx: u32, @builtin(instance_index) instance_idx: u32) -> VertexOutput { let cell = instances[instance_idx]; var corners = array, 6>( vec2(0.0, 0.0), vec2(1.0, 0.0), vec2(0.0, 1.0), vec2(0.0, 1.0), vec2(1.0, 0.0), vec2(1.0, 1.0), ); let corner = corners[vertex_idx]; let x = (f32(cell.col) + corner.x) * uniforms.cell_width; let y = (f32(cell.row) + corner.y) * uniforms.cell_height; let screen_w = f32(uniforms.screen_cols) * uniforms.cell_width; let screen_h = f32(uniforms.screen_rows) * uniforms.cell_height; let ndc_x = (x / screen_w) * 2.0 - 1.0; let ndc_y = -((y / screen_h) * 2.0 - 1.0); var out: VertexOutput; out.position = vec4(ndc_x, ndc_y, 0.0, 1.0); out.color = vec4(f32(cell.bg_r) / 255.0, f32(cell.bg_g) / 255.0, f32(cell.bg_b) / 255.0, f32(cell.bg_a) / 255.0); return out; } "#; pub const BG_FRAGMENT: &str = r#" struct VertexOutput { @builtin(position) position: vec4, @location(0) color: vec4, }; @fragment fn main(in: VertexOutput) -> @location(0) vec4 { return in.color; } "#; pub const TEXT_VERTEX: &str = r#" struct TextInstance { col: f32, row: f32, bearing_x: f32, bearing_y: f32, glyph_w: f32, glyph_h: f32, atlas_x: f32, atlas_y: f32, atlas_w: f32, atlas_h: f32, fg_r: u32, fg_g: u32, fg_b: u32, flags: u32, thickening: f32, }; @group(0) @binding(0) var instances: array; struct Uniforms { cell_width: f32, cell_height: f32, atlas_size: f32, screen_cols: u32, screen_rows: u32, }; @group(0) @binding(1) var uniforms: Uniforms; struct VertexOutput { @builtin(position) position: vec4, @location(0) uv: vec2, @location(1) fg_color: vec4, @location(2) atlas_uv: vec4, @location(3) thickening: f32, @location(4) flags: u32, }; @vertex fn main(@builtin(vertex_index) vertex_idx: u32, @builtin(instance_index) instance_idx: u32) -> VertexOutput { let cell = instances[instance_idx]; var corners = array, 6>( vec2(0.0, 0.0), vec2(1.0, 0.0), vec2(0.0, 1.0), vec2(0.0, 1.0), vec2(1.0, 0.0), vec2(1.0, 1.0), ); let corner = corners[vertex_idx]; let x = (cell.col * uniforms.cell_width) + cell.bearing_x + corner.x * cell.glyph_w; let y = (cell.row * uniforms.cell_height) + cell.bearing_y + corner.y * cell.glyph_h; let screen_w = f32(uniforms.screen_cols) * uniforms.cell_width; let screen_h = f32(uniforms.screen_rows) * uniforms.cell_height; let ndc_x = (x / screen_w) * 2.0 - 1.0; let ndc_y = -((y / screen_h) * 2.0 - 1.0); var out: VertexOutput; out.position = vec4(ndc_x, ndc_y, 0.0, 1.0); out.uv = corner; out.fg_color = vec4(f32(cell.fg_r) / 255.0, f32(cell.fg_g) / 255.0, f32(cell.fg_b) / 255.0, 1.0); let norm = uniforms.atlas_size; out.atlas_uv = vec4(cell.atlas_x / norm, cell.atlas_y / norm, cell.atlas_w / norm, cell.atlas_h / norm); out.thickening = cell.thickening; out.flags = cell.flags; return out; } "#; pub const TEXT_FRAGMENT: &str = r#" @group(0) @binding(2) var atlas_sampler: sampler; @group(0) @binding(3) var atlas_texture: texture_2d; struct VertexOutput { @builtin(position) position: vec4, @location(0) uv: vec2, @location(1) fg_color: vec4, @location(2) atlas_uv: vec4, @location(3) thickening: f32, @location(4) flags: u32, }; fn median(r: f32, g: f32, b: f32) -> f32 { return max(min(r, g), min(max(r, g), b)); } @fragment fn main(in: VertexOutput) -> @location(0) vec4 { let atlas_pos = vec2( in.atlas_uv.x + in.uv.x * in.atlas_uv.z, in.atlas_uv.y + in.uv.y * in.atlas_uv.w, ); let sample = textureSample(atlas_texture, atlas_sampler, atlas_pos); let sig_dist = median(sample.r, sample.g, sample.b); let threshold = 0.5 - in.thickening * 0.15; let smoothing = 0.05; let opacity = smoothstep(threshold - smoothing, threshold + smoothing, sig_dist); let is_colored = (in.flags & 0x0040u) != 0u; if is_colored { return vec4(sample.rgb, opacity); } else { return vec4(in.fg_color.rgb, opacity); } } "#;