summaryrefslogtreecommitdiff
path: root/src/shaders/math/color.wgsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/shaders/math/color.wgsl')
-rw-r--r--src/shaders/math/color.wgsl36
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.