summaryrefslogtreecommitdiff
path: root/src/effects/ntsc.wgsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/effects/ntsc.wgsl')
-rw-r--r--src/effects/ntsc.wgsl112
1 files changed, 5 insertions, 107 deletions
diff --git a/src/effects/ntsc.wgsl b/src/effects/ntsc.wgsl
index ad29c79..9901c88 100644
--- a/src/effects/ntsc.wgsl
+++ b/src/effects/ntsc.wgsl
@@ -1,6 +1,8 @@
#include "sequence_uniforms"
#include "render/fullscreen_uv_vs"
#include "math/noise"
+#include "math/color"
+#include "math/color_c64"
#include "debug/debug_print"
const PI = 3.14159265;
@@ -22,28 +24,6 @@ const CROSS_TALK = 0.1;
const CROSS_Y_INTERFERENCE = 30.;
const CHROMA_MOD_FREQ = (0.4 * PI);
-const NUM_COLORS : u32 = 16;
-const C64Colors = array<vec3f, NUM_COLORS>(
- vec3f(13.0/255.0, 13.0/255.0, 13.0/255.0), // 0 black
- vec3f(242.0/255.0, 242.0/255.0, 242.0/255.0), // 1 white
- vec3f(89.0/255.0, 39.0/255.0, 33.0/255.0), // 2 red
- vec3f(170.0/255.0, 220.0/255.0, 240.0/255.0), // 3 cyan
-
- vec3f(101.0/255.0, 27.0/255.0, 109.0/255.0), // 4 purple
- vec3f(120.0/255.0, 198.0/255.0, 112.0/255.0), // 5 green
- vec3f(54.0/255.0, 53.0/255.0, 152.0/255.0), // 6 blue
- vec3f(226.0/255.0, 229.0/255.0, 115.0/255.0), // 7 yellow
-
- vec3f(141.0/255.0, 85.0/255.0, 50.0/255.0), // 8 orange
- vec3f(89.0/255.0, 63.0/255.0, 13.0/255.0), // 9 brown
- vec3f(189.0/255.0, 110.0/255.0, 115.0/255.0), // 10 pink
- vec3f(80.0/255.0, 80.0/255.0, 80.0/255.0), // 11 dark gray
-
- vec3f(124.0/255.0, 124.0/255.0, 124.0/255.0), // 12 gray
- vec3f(165.0/255.0, 242.0/255.0, 156.0/255.0), // 13 bright green
- vec3f(114.0/255.0, 111.0/255.0, 224.0/255.0), // 14 light blue
- vec3f(128.0/255.0, 128.0/255.0, 128.0/255.0) // 15 middle gray
-);
@group(0) @binding(0) var input_sampler: sampler;
@group(0) @binding(1) var input_texture: texture_2d<f32>;
@@ -63,37 +43,10 @@ fn vignette(uv: vec2f) -> f32 {
return smoothstep(0., vignetteSmoothness, amount);
}
-fn rgba_to_yiqa(rgba: vec4f) -> vec4f {
- const rgb_yiq_mat = 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 rgb_yiq_mat * rgba;
-}
-
-fn yiqa_to_rgba(yiq: vec4f) -> vec4f {
- const yiq_rgb_mat = 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 yiq_rgb_mat * yiq;
-}
-
// returns Luma, chroma subcarrier level, phase, transparency
fn get_luma_chroma_phase_a(uv: vec2f) -> vec4f {
- let rgba = Dither(textureSample(input_texture, input_sampler, uv), uv);
- let yiq = rgba_to_yiqa(textureSample(input_texture, input_sampler, uv));
- let chroma_level = length(yiq.yz);
-
- // 22.5 degrees phase shift between lines
-// let mscanl = (uv.y * uniforms.resolution.y / 4.) % 2.0;
- 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, yiq.a);
+ let rgba = textureSample(input_texture, input_sampler, uv);
+ return rgba_to_luma_chroma_phase(rgba, uv.y, YSIZE);
}
fn get_value(uv: vec2f, off: f32, yscale: f32) -> vec4f {
@@ -124,61 +77,6 @@ fn randomized_f32(p: vec2f, t: f32) -> f32 {
return hash_2f_alt(vec2f(p * 0.152 + t * 1500. + 50.0));
}
-const BAYER_8X8 = array<u32, 64>(
- 0, 32, 8, 40, 2, 34, 10, 42,
- 48, 16, 56, 24, 50, 18, 58, 26,
- 12, 44, 4, 36, 14, 46, 6, 38,
- 60, 28, 52, 20, 62, 30, 54, 22,
- 3, 35, 11, 43, 1, 33, 9, 41,
- 51, 19, 59, 27, 49, 17, 57, 25,
- 15, 47, 7, 39, 13, 45, 5, 37,
- 63, 31, 55, 23, 61, 29, 53, 21
-);
-
-const DistanceParam = 0.65;
-fn colorDistance(color: vec4f, c1: vec4f, c2: vec4f, frac: f32) -> f32 {
- return mix(distance(color, mix(c1, c2, frac)),
- distance(color, c1) + distance(color, c2),
- 0.5 * DistanceParam * DistanceParam);
-}
-
-fn Dither(col: vec4f, uv: vec2f) -> vec4f {
- let ix = u32(floor(uv.x * XSIZE / 2.)) % 8;
- let iy = u32(floor(uv.y * YSIZE / 2.)) % 8;
- let thresh = f32(BAYER_8X8[ix + 8 * iy]) / 64.;
-
- var color = min(col, vec4f(1.));
- color *= color; // ~gamma
-
- var c1 = vec4f(0.);
- var c2 = vec4f(0.);
- var frac = 0.0;
- var best = 1.e5;
-
- for (var i = 0u; i < NUM_COLORS; i += 1u) {
- var p1 = vec4f(C64Colors[i], 1.);
- p1 *= p1;
- for (var j = i + 1u; j < NUM_COLORS; j += 1u) {
- var p2 = vec4f(C64Colors[j], 1.);
- p2 *= p2;
-
- // min-L2 optim
- let dc = p1 - p2;
- var a = dot(dc, p1 - color) / dot(dc, dc);
- a = clamp(a, 0., 1.);
- let dist = colorDistance(color, p1, p2, a);
- if (dist < best) {
- best = dist;
- c1 = p1;
- c2 = p2;
- frac = a;
- }
- }
- }
- color = mix(c1, c2, f32(frac > thresh));
-// color = mix(c1, c2, frac);
- return sqrt(color);
-}
fn get_border_col(uv: vec2f) -> vec4f {
let t = uniforms.beat_time;
@@ -241,7 +139,7 @@ fn get_border_col(uv: vec2f) -> vec4f {
signal.z *= 1.0 + scarrier * q_mod;
var col = yiqa_to_rgba(signal);
- col = Dither(col, uv);
+ col = Dither(col, uv, XSIZE, YSIZE);
let border_col = get_border_col(uv);