summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-16 09:43:06 +0100
committerskal <pascal.massimino@gmail.com>2026-02-16 09:43:06 +0100
commit766c0b0a41ddb4ac1fae68f720a9176a1b5f6070 (patch)
treeb8530354de7133c7828d177889a6a4eb1d0570ba /common
parent04938fc4a3335e1459e5fb23d0d091fd2a40c296 (diff)
feat(sequence): add inline post-process functions for v2
- Create postprocess_inline.wgsl with 7 inline effect functions - Functions: vignette, flash, fade, theme, solarize, chroma_aberration, distort - Add example combined_postprocess_v2.wgsl showing usage - Register postprocess_inline snippet with ShaderComposer - Add to main and test workspace assets - All tests passing (36/36) Strategy: Simple effects become inline functions instead of separate classes. Complex effects (rotating_cube, hybrid_3d, particles) remain as TODO for v2 port. handoff(Claude): Inline functions ready, 7 simple effects consolidated
Diffstat (limited to 'common')
-rw-r--r--common/shaders/combined_postprocess_v2.wgsl36
-rw-r--r--common/shaders/postprocess_inline.wgsl61
2 files changed, 97 insertions, 0 deletions
diff --git a/common/shaders/combined_postprocess_v2.wgsl b/common/shaders/combined_postprocess_v2.wgsl
new file mode 100644
index 0000000..a934dce
--- /dev/null
+++ b/common/shaders/combined_postprocess_v2.wgsl
@@ -0,0 +1,36 @@
+// Example: Combined post-process using inline functions
+// Demonstrates how to chain multiple simple effects without separate classes
+
+#include "sequence_v2_uniforms"
+#include "postprocess_inline"
+
+@group(0) @binding(0) var input_sampler: sampler;
+@group(0) @binding(1) var input_texture: texture_2d<f32>;
+@group(0) @binding(2) var<uniform> uniforms: UniformsSequenceParams;
+
+struct VertexOutput {
+ @builtin(position) position: vec4<f32>,
+ @location(0) uv: vec2<f32>,
+};
+
+@vertex fn vs_main(@builtin(vertex_index) vid: u32) -> VertexOutput {
+ var out: VertexOutput;
+ let x = f32((vid & 1u) << 1u);
+ let y = f32((vid & 2u));
+ out.position = vec4<f32>(x * 2.0 - 1.0, 1.0 - y * 2.0, 0.0, 1.0);
+ out.uv = vec2<f32>(x, y);
+ return out;
+}
+
+@fragment fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
+ // Sample base color
+ var color = textureSample(input_texture, input_sampler, in.uv);
+
+ // Apply effects in sequence (customize as needed)
+ // color = apply_solarize(color, 0.4, 0.4, uniforms.time);
+ // color = apply_theme(color, vec3<f32>(1.0, 0.8, 0.6), 0.3);
+ color = apply_vignette(color, in.uv, 0.6, 0.1, uniforms.audio_intensity);
+ // color = apply_flash(color, uniforms.beat_phase * 0.2);
+
+ return color;
+}
diff --git a/common/shaders/postprocess_inline.wgsl b/common/shaders/postprocess_inline.wgsl
new file mode 100644
index 0000000..fcc5e27
--- /dev/null
+++ b/common/shaders/postprocess_inline.wgsl
@@ -0,0 +1,61 @@
+// Inline post-process functions for simple effects
+// Use these instead of separate effect classes for v2 sequences
+
+// Vignette: darkens edges based on distance from center
+fn apply_vignette(color: vec4<f32>, uv: vec2<f32>, radius: f32, softness: f32, intensity: f32) -> vec4<f32> {
+ let d = distance(uv, vec2<f32>(0.5, 0.5));
+ let vignette = smoothstep(radius, radius - softness, d);
+ return vec4<f32>(color.rgb * mix(1.0, vignette, intensity), color.a);
+}
+
+// Flash: additive white flash
+fn apply_flash(color: vec4<f32>, flash_intensity: f32) -> vec4<f32> {
+ return color + vec4<f32>(flash_intensity, flash_intensity, flash_intensity, 0.0);
+}
+
+// Fade: linear interpolation to target color
+fn apply_fade(color: vec4<f32>, fade_amount: f32, fade_color: vec3<f32>) -> vec4<f32> {
+ return vec4<f32>(mix(color.rgb, fade_color, fade_amount), color.a);
+}
+
+// Theme modulation: multiply by color tint
+fn apply_theme(color: vec4<f32>, theme_color: vec3<f32>, strength: f32) -> vec4<f32> {
+ return vec4<f32>(mix(color.rgb, color.rgb * theme_color, strength), color.a);
+}
+
+// Solarize: threshold-based color inversion
+fn apply_solarize(color: vec4<f32>, threshold: f32, strength: f32, time: f32) -> vec4<f32> {
+ let pattern_num = u32(time / 2.0);
+ let is_even = (pattern_num % 2u) == 0u;
+ let thr = threshold + 0.15 * sin(time);
+ var col = color;
+
+ if (is_even) {
+ if (col.r < thr) { col.r = mix(col.r, 1.0 - col.r, strength); }
+ if (col.g < thr) { col.g = mix(col.g, 1.0 - col.g * 0.7, strength * 0.7); }
+ if (col.b < thr) { col.b = mix(col.b, col.b * 0.5, strength); }
+ } else {
+ if (col.r < thr) { col.r = mix(col.r, col.r * 0.6, strength); }
+ if (col.g < thr) { col.g = mix(col.g, 1.0 - col.g * 0.8, strength * 0.8); }
+ if (col.b < thr) { col.b = mix(col.b, 1.0 - col.b, strength); }
+ }
+ return col;
+}
+
+// Chroma aberration: RGB channel offset
+fn apply_chroma_aberration(input_tex: texture_2d<f32>, input_sampler: sampler,
+ uv: vec2<f32>, offset: f32, resolution: vec2<f32>) -> vec4<f32> {
+ let pixel_offset = offset / resolution;
+ let r = textureSample(input_tex, input_sampler, uv + vec2<f32>(pixel_offset.x, 0.0)).r;
+ let g = textureSample(input_tex, input_sampler, uv).g;
+ let b = textureSample(input_tex, input_sampler, uv - vec2<f32>(pixel_offset.x, 0.0)).b;
+ let a = textureSample(input_tex, input_sampler, uv).a;
+ return vec4<f32>(r, g, b, a);
+}
+
+// Distort: UV distortion based on time
+fn apply_distort(uv: vec2<f32>, time: f32, strength: f32) -> vec2<f32> {
+ let distort_x = sin(uv.y * 10.0 + time * 2.0) * strength;
+ let distort_y = cos(uv.x * 10.0 + time * 2.0) * strength;
+ return uv + vec2<f32>(distort_x, distort_y);
+}