diff options
| author | skal <pascal.massimino@gmail.com> | 2026-03-09 08:44:09 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-03-09 08:44:09 +0100 |
| commit | 9f53f8cbeb599dafc57ed80193b79e2c48700376 (patch) | |
| tree | 7249c1108feeceaaee49358efa3114a96d30f8af /src/shaders/math/color.wgsl | |
| parent | cc13cf590ae524b509486d26029a9cc949a5d404 (diff) | |
refactor: extract YIQ and C64 dither to common WGSL shaders
- math/color.wgsl: add rgba_to_yiqa, yiqa_to_rgba, rgba_to_luma_chroma_phase
- math/color_c64.wgsl: new file with C64 palette, Bayer 8x8, Dither()
- ntsc.wgsl: include both, remove local duplicates; Dither() now takes xsize/ysize
handoff(Claude): YIQ/dither helpers now reusable by other effects
Diffstat (limited to 'src/shaders/math/color.wgsl')
| -rw-r--r-- | src/shaders/math/color.wgsl | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/shaders/math/color.wgsl b/src/shaders/math/color.wgsl index 9352053..0639bf7 100644 --- a/src/shaders/math/color.wgsl +++ b/src/shaders/math/color.wgsl @@ -1,4 +1,40 @@ // Common color space and tone mapping functions. +// Includes: sRGB, ACES, HSV, YIQ (NTSC) conversions. +// Use rgba_to_luma_chroma_phase() to encode YIQ into a temp buffer for NTSC-style effects. + +const TAU_COLOR = 6.28318530718; + +// RGB <-> YIQ (NTSC) color space +fn rgba_to_yiqa(rgba: vec4f) -> vec4f { + const m = mat4x4f( + 0.299, 0.596, 0.211, 0., + 0.587, -0.274, -0.523, 0., + 0.114, -0.322, 0.312, 0., + 0., 0., 0., 1., + ); + return m * rgba; +} + +fn yiqa_to_rgba(yiq: vec4f) -> vec4f { + const m = mat4x4f( + 1.000, 1.000, 1.000, 0., + 0.956, -0.272, -1.106, 0., + 0.621, -0.647, 1.703, 0., + 0., 0., 0., 1., + ); + return m * yiq; +} + +// Convert RGBA to packed luma/chroma/phase signal for NTSC processing. +// Returns vec4f(luma, chroma_level, phase/TAU, alpha). +// ysize: virtual scanline count (e.g. 33.*8.); drives 22.5-degree inter-line phase shift. +fn rgba_to_luma_chroma_phase(rgba: vec4f, uv_y: f32, ysize: f32) -> vec4f { + let yiq = rgba_to_yiqa(rgba); + let chroma_level = length(yiq.yz); + let mscanl = (uv_y * ysize) % 2.0; + let phase = atan2(yiq.y, yiq.z) - 0.3926991 + mscanl * 0.19634954; + return vec4f(yiq.x, chroma_level, phase / TAU_COLOR, yiq.a); +} // sRGB to Linear approximation // Note: Assumes input is in sRGB color space. |
