summaryrefslogtreecommitdiff
path: root/common/shaders/postprocess_inline.wgsl
blob: fcc5e27e48feda751e3afdc11cdc4336663eb55c (plain)
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
// 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);
}