summaryrefslogtreecommitdiff
path: root/src/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader')
-rw-r--r--src/shader/instance.wgsl6
-rw-r--r--src/shader/particle.wgsl11
-rw-r--r--src/shader/vfx_line.wgsl76
3 files changed, 85 insertions, 8 deletions
diff --git a/src/shader/instance.wgsl b/src/shader/instance.wgsl
index fb1e0b1..a549801 100644
--- a/src/shader/instance.wgsl
+++ b/src/shader/instance.wgsl
@@ -17,8 +17,8 @@ struct Instance {
@group(0) @binding(3) var<storage, read> cells: array<u32>;
struct VertexOutput {
- @builtin(position) clip_position: vec4<f32>,
- @location(0) world: vec2<f32>,
+ @builtin(position) clip_position: vec4f,
+ @location(0) world: vec2f,
@location(1) @interpolate(flat) instance: u32,
};
@@ -46,7 +46,7 @@ fn vs_main(
}
@fragment
-fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
+fn fs_main(in: VertexOutput) -> @location(0) vec4f {
let instance = instances[in.instance];
let d = in.world - instance.centre;
diff --git a/src/shader/particle.wgsl b/src/shader/particle.wgsl
index 3dd61a9..227468b 100644
--- a/src/shader/particle.wgsl
+++ b/src/shader/particle.wgsl
@@ -14,8 +14,8 @@ struct Particle {
@group(0) @binding(2) var<storage, read> particles: array<Particle>;
struct VertexOutput {
- @builtin(position) clip_position: vec4<f32>,
- @location(0) world: vec2<f32>,
+ @builtin(position) clip_position: vec4f,
+ @location(0) world: vec2f,
@location(1) @interpolate(flat) instance: u32,
@location(2) @interpolate(flat) material: u32,
@location(3) @interpolate(flat) life: f32,
@@ -29,7 +29,7 @@ fn vs_main(
let particle = particles[n];
// (0,0),(1,0),(0,1),(1,1)
- let corner = vec2<f32>(f32(i & 1u), f32((i >> 1u) & 1u));
+ let corner = vec2f(f32(i & 1u), f32((i >> 1u) & 1u));
let world = particle.position + corner;
var out: VertexOutput;
@@ -43,9 +43,10 @@ fn vs_main(
}
@fragment
-fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
+fn fs_main(in: VertexOutput) -> @location(0) vec4f {
let particle = particles[in.instance];
// TODO can pack more in here and shift
let c = palette[in.material];
- return vec4<f32>(c.r, c.g, c.b, c.a * smoothstep(0.0, 1, in.life));
+ // if life is less than 1, smoothly reduce alpha to 0
+ return vec4f(c.r, c.g, c.b, c.a * smoothstep(0.0, 1, in.life));
}
diff --git a/src/shader/vfx_line.wgsl b/src/shader/vfx_line.wgsl
new file mode 100644
index 0000000..bef7645
--- /dev/null
+++ b/src/shader/vfx_line.wgsl
@@ -0,0 +1,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)));
+}