diff options
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. |
