webgpu-app/font.wgsl
2026-08-05 18:50:04 -05:00

91 lines
2.1 KiB
WebGPU Shading Language

struct View {
viewProj: mat4x4f,
lightViewProj: mat4x4f,
lightPosition: vec4f,
eyePosition: vec4f,
aspect: f32,
};
struct Config {
scale: f32,
translateX: f32,
translateY: f32,
};
struct GlyphBuffer {
texPosition: vec2f,
texSize: vec2f,
size: vec2f,
unused: vec2f,
};
struct LayoutBuffer {
position: vec4f, // glyph_index w
};
@group(0) @binding(0) var<uniform> view: View;
@group(1) @binding(0) var linearSampler: sampler;
@group(1) @binding(1) var fontTexture: texture_2d<f32>;
@group(1) @binding(2) var<storage> glyphBuffer: array<GlyphBuffer>;
@group(2) @binding(0) var<storage> layoutBuffer: array<LayoutBuffer>;
@group(2) @binding(1) var<uniform> config: Config;
struct VertexInput {
@builtin(vertex_index) vertex_index: u32,
@builtin(instance_index) instance_index: u32,
};
struct VertexOutput {
@builtin(position) position: vec4f,
@location(0) texture: vec2f,
@location(1) @interpolate(flat) glyphIndex: u32,
@location(2) foo: vec4f,
};
const vertices = array(
vec2f(1.0, 0.0),
vec2f(0.0, 1.0),
vec2f(0.0, 0.0),
vec2f(1.0, 1.0),
);
@vertex
fn vertexMain(input: VertexInput) -> VertexOutput
{
let texture = vertices[input.vertex_index];
let position = vec2f(texture.x, 1.0 - texture.y);
let glyphIndex = u32(layoutBuffer[input.instance_index].position.w);
let viewPosition = position * glyphBuffer[glyphIndex].size + layoutBuffer[input.instance_index].position.xy;
let screenPosition = viewPosition * vec2f(1 / view.aspect, 1) * config.scale + vec2f(config.translateX, config.translateY);
var output: VertexOutput;
output.position = vec4f(screenPosition, 0.0, 1.0);
output.texture = texture;
output.glyphIndex = glyphIndex;
output.foo = vec4f(layoutBuffer[glyphIndex].position.xy, 0, 0);
return output;
}
@fragment
fn fragmentMain(input: VertexOutput) -> @location(0) vec4f
{
var color = vec3f(input.texture.xy, 0);
let p = glyphBuffer[input.glyphIndex].texPosition;
let s = glyphBuffer[input.glyphIndex].texSize;
let base = textureSample(fontTexture, linearSampler, input.texture * s + p);
let t = f32(base.x > 0.5);
if (base.x < 0.5) {
discard;
}
return vec4f(t, t, t, 1);
}