forked from webgpu/webgpu-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmsdfText.wgsl
More file actions
85 lines (69 loc) · 2.34 KB
/
msdfText.wgsl
File metadata and controls
85 lines (69 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// Positions for simple quad geometry
const pos = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0));
struct VertexInput {
@builtin(vertex_index) vertex : u32,
@builtin(instance_index) instance : u32,
};
struct VertexOutput {
@builtin(position) position : vec4f,
@location(0) texcoord : vec2f,
};
struct Char {
texOffset: vec2f,
texExtent: vec2f,
size: vec2f,
offset: vec2f,
};
struct FormattedText {
transform: mat4x4f,
color: vec4f,
scale: f32,
chars: array<vec3f>,
};
struct Camera {
projection: mat4x4f,
view: mat4x4f,
};
// Font bindings
@group(0) @binding(0) var fontTexture: texture_2d<f32>;
@group(0) @binding(1) var fontSampler: sampler;
@group(0) @binding(2) var<storage> chars: array<Char>;
// Text bindings
@group(1) @binding(0) var<uniform> camera: Camera;
@group(1) @binding(1) var<storage> text: FormattedText;
@vertex
fn vertexMain(input : VertexInput) -> VertexOutput {
let textElement = text.chars[input.instance];
let char = chars[u32(textElement.z)];
let charPos = (pos[input.vertex] * char.size + textElement.xy + char.offset) * text.scale;
var output : VertexOutput;
output.position = camera.projection * camera.view * text.transform * vec4f(charPos, 0, 1);
output.texcoord = pos[input.vertex] * vec2f(1, -1);
output.texcoord *= char.texExtent;
output.texcoord += char.texOffset;
return output;
}
fn sampleMsdf(texcoord: vec2f) -> f32 {
let c = textureSample(fontTexture, fontSampler, texcoord);
return max(min(c.r, c.g), min(max(c.r, c.g), c.b));
}
// Antialiasing technique from Paul Houx
// https://github.com/Chlumsky/msdfgen/issues/22#issuecomment-234958005
@fragment
fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
// pxRange (AKA distanceRange) comes from the msdfgen tool. Don McCurdy's tool
// uses the default which is 4.
let pxRange = 4.0;
let sz = vec2f(textureDimensions(fontTexture, 0));
let dx = sz.x*length(vec2f(dpdx(input.texcoord.x), dpdy(input.texcoord.x)));
let dy = sz.y*length(vec2f(dpdx(input.texcoord.y), dpdy(input.texcoord.y)));
let toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);
let sigDist = sampleMsdf(input.texcoord) - 0.5;
let pxDist = sigDist * toPixels;
let edgeWidth = 0.5;
let alpha = smoothstep(-edgeWidth, edgeWidth, pxDist);
if (alpha < 0.001) {
discard;
}
return vec4f(text.color.rgb, text.color.a * alpha);
}