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
|
struct Camera {
scale: vec2f,
centre: vec2f,
};
struct MaterialDef {
color: vec4f,
// the length of the path segment for t
length: f32,
};
struct VfxLine {
a: vec2f,
b: vec2f,
width: f32,
material: u32,
alive_for: f32,
lifetime: f32,
}
@group(0) @binding(0) var<uniform> camera: Camera;
@group(0) @binding(1) var<storage, read> materials: array<MaterialDef>;
@group(0) @binding(2) var<storage, read> vfx_lines: array<VfxLine>;
struct VertexOutput {
@builtin(position) clip_position: vec4f,
@location(0) @interpolate(flat) color: vec4f,
// the length of the path segment for t
@location(1) @interpolate(flat) length: f32,
@location(2) @interpolate(flat) cur_centre: f32,
@location(3) dist: f32,
};
@vertex
fn vs_main(
@builtin(vertex_index) i: u32,
@builtin(instance_index) n: u32,
) -> VertexOutput {
let vfx_line = vfx_lines[n];
let d = vfx_line.b - vfx_line.a;
// (-y, x) is a 90deg ccw rotation
let p = normalize(vec2f(-d.y, d.x)) * (vfx_line.width * 0.5);
// 0=a,1=b
let cv = f32(i & 1u);
// direction to offset the orthogonal width
let co = f32(i >> 1u) * 2.0 - 1.0;
// select a/b, add offset
let world = mix(vfx_line.a, vfx_line.b, cv) + p * co;
var out: VertexOutput;
out.clip_position = vec4f((world - camera.centre) * camera.scale, 0.0, 1.0);
// material
let material = materials[vfx_line.material];
out.color = material.color;
out.length = material.length;
// computed
let l = length(d);
out.cur_centre = (l + material.length) * (vfx_line.alive_for / vfx_line.lifetime) - (material.length / 2);
// interpolated
out.dist = cv * l;
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
// distance on line of the centre of the current (w.r.t. time) line segment
// can do this in vertex
// our distance along the line vs the current centre
let dist_from_centre = abs(in.dist - in.cur_centre);
let c = in.color;
return vec4f(c.r, c.g, c.b, c.a * (1 - smoothstep(0.0, in.length / 2, dist_from_centre)));
}
|