From 054c967e4a06bbbf79359bae701e1b467625839c Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Wed, 9 Sep 2026 22:29:14 -0700 Subject: lighting --- src/shader/instance.wgsl | 22 +++++++++++++++++++++- src/shader/lpv.wgsl | 31 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/shader/lpv.wgsl (limited to 'src/shader') diff --git a/src/shader/instance.wgsl b/src/shader/instance.wgsl index a549801..4b921ab 100644 --- a/src/shader/instance.wgsl +++ b/src/shader/instance.wgsl @@ -1,8 +1,16 @@ +const AMBIENT_LIGHT = vec4f(0.4, 0.4, 0.4, 1.0); +const LIGHT_RESOLUTION = 1.0; + struct Camera { scale: vec2f, centre: vec2f, }; +struct Lighting { + origin: vec2f, + _padding: vec2f, +}; + struct Instance { centre: vec2f, cos_sin: vec2f, @@ -15,6 +23,9 @@ struct Instance { @group(0) @binding(1) var palette: array; @group(0) @binding(2) var instances: array; @group(0) @binding(3) var cells: array; +@group(0) @binding(4) var lighting: texture_2d_array; +@group(0) @binding(5) var light_sampler: sampler; +@group(0) @binding(6) var light_params: Lighting; struct VertexOutput { @builtin(position) clip_position: vec4f, @@ -67,5 +78,14 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { discard; } - return palette[material]; + var total = vec3f(0.0); + let light_dims = vec2f(textureDimensions(lighting)); + let light_texel = (in.world - light_params.origin) * LIGHT_RESOLUTION; + let light_uv = light_texel / light_dims; + for (var d = 0u; d < 4u; d++) { + total += textureSample(lighting, light_sampler, light_uv, d).rgb; + } + let light = vec4f(total.r, total.g, total.b, 1.0); + + return palette[material] * (light + AMBIENT_LIGHT); } diff --git a/src/shader/lpv.wgsl b/src/shader/lpv.wgsl new file mode 100644 index 0000000..1f84e40 --- /dev/null +++ b/src/shader/lpv.wgsl @@ -0,0 +1,31 @@ +const DIRS = array(vec2i(1, 0), vec2i(0, 1), vec2i(-1, 0), vec2i(0, -1)); +const ATTEN: f32 = 0.999; +const W_FWD: f32 = 0.70; +const W_SIDE: f32 = 0.15; + +@group(0) @binding(0) var scene: texture_2d; +@group(0) @binding(1) var src: texture_2d_array; +@group(0) @binding(2) var dst: texture_storage_2d_array; + +@compute @workgroup_size(8, 8, 1) +fn propagate(@builtin(global_invocation_id) gid: vec3) { + let dims = textureDimensions(dst); + if gid.x >= dims.x || gid.y >= dims.y { + return; + } + + let p = vec2(gid.xy); + let s = textureLoad(scene, p, 0); + let t = s.a; + + for (var d = 0u; d < 4u; d++) { + let q = p - DIRS[d]; + var inc = vec3f(0.0); + inc += textureLoad(src, q, d, 0).rgb * W_FWD; + inc += textureLoad(src, q, (d + 1u) % 4u, 0).rgb * W_SIDE; + inc += textureLoad(src, q, (d + 3u) % 4u, 0).rgb * W_SIDE; + + let o = inc * t * ATTEN + s.rgb * 0.25; + textureStore(dst, p, d, vec4f(o, 1.0)); + } +} \ No newline at end of file -- cgit v1.3.1