62 lines
1.3 KiB
WebGPU Shading Language
62 lines
1.3 KiB
WebGPU Shading Language
struct Material {
|
|
p0: vec2<f32>,
|
|
c0: vec2<f32>,
|
|
c1: vec2<f32>,
|
|
p1: vec2<f32>,
|
|
width: f32,
|
|
color: vec4<f32>,
|
|
};
|
|
|
|
@group(2) @binding(0)
|
|
var<uniform> mat: Material;
|
|
|
|
fn bezier(p0: vec2<f32>, c0: vec2<f32>, c1: vec2<f32>, p1: vec2<f32>, t: f32) -> vec2<f32> {
|
|
let u = 1.0 - t;
|
|
return
|
|
u*u*u*p0 +
|
|
3.0*u*u*t*c0 +
|
|
3.0*u*t*t*c1 +
|
|
t*t*t*p1;
|
|
}
|
|
|
|
fn distance_to_bezier(p: vec2<f32>) -> f32 {
|
|
var min_d = 1e9;
|
|
let steps = 32;
|
|
|
|
var prev = mat.p0;
|
|
for (var i = 1; i <= steps; i++) {
|
|
let t = f32(i) / f32(steps);
|
|
let cur = bezier(mat.p0, mat.c0, mat.c1, mat.p1, t);
|
|
|
|
// distance to segment
|
|
let v = cur - prev;
|
|
let w = p - prev;
|
|
let t_seg = clamp(dot(w, v) / dot(v, v), 0.0, 1.0);
|
|
let proj = prev + t_seg * v;
|
|
|
|
min_d = min(min_d, distance(p, proj));
|
|
prev = cur;
|
|
}
|
|
|
|
return min_d;
|
|
}
|
|
|
|
@fragment
|
|
fn fragment(
|
|
@location(0) world_pos: vec3<f32>,
|
|
) -> @location(0) vec4<f32> {
|
|
let d = distance_to_bezier(world_pos.xy);
|
|
|
|
let half_w = mat.width * 0.5;
|
|
let aa = fwidth(d);
|
|
|
|
let alpha = smoothstep(half_w + aa, half_w - aa, d);
|
|
|
|
if (alpha <= 0.001) {
|
|
discard;
|
|
}
|
|
|
|
return vec4(mat.color.rgb, mat.color.a * alpha);
|
|
}
|
|
|