diff --git a/ntsc/ntsc-vcr.slangp b/vhs/ntsc-vcr.slangp similarity index 55% rename from ntsc/ntsc-vcr.slangp rename to vhs/ntsc-vcr.slangp index fb44d3e..9da582a 100644 --- a/ntsc/ntsc-vcr.slangp +++ b/vhs/ntsc-vcr.slangp @@ -1,15 +1,13 @@ -shaders = 6 -shader0 = shaders/ntsc-pass1-composite-3phase.slang -shader1 = shaders/ntsc-pass2-3phase.slang -shader2 = shaders/ntsc-stock.slang -shader3 = shaders/ntsc-stock.slang -shader4 = shaders/ntsc-vcr/loose-connection.slang -shader5 = ../misc/image-adjustment.slang +shaders = 5 +shader0 = ../ntsc/shaders/ntsc-pass1-composite-3phase.slang +shader1 = ../ntsc/shaders/ntsc-pass2-3phase.slang +shader2 = ../ntsc/shaders/ntsc-stock.slang +shader3 = shaders/static.slang +shader4 = ../misc/image-adjustment.slang filter_linear0 = false filter_linear1 = false filter_linear2 = false -filter_linear3 = true scale_type0 = source scale_x0 = 4.0 @@ -25,7 +23,7 @@ scale_type_x2 = source scale_type_y2 = viewport scale2 = 1.0 -scale_type4 = source +scale_type3 = source scale4 = 1.0 parameters = "GRAIN_STR;luminance;bright_boost;target_gamma;saturation" @@ -35,5 +33,5 @@ bright_boost = 0.10 target_gamma = 3.50 saturation = 0.70 -textures = "overlay" -overlay = shaders/ntsc-vcr/vcr-overlay.png +textures = "play" +play = resources/play.png diff --git a/ntsc/shaders/ntsc-vcr/vcr-overlay.png b/vhs/resources/play.png similarity index 100% rename from ntsc/shaders/ntsc-vcr/vcr-overlay.png rename to vhs/resources/play.png diff --git a/ntsc/shaders/ntsc-vcr/loose-connection.slang b/vhs/shaders/static.slang similarity index 74% rename from ntsc/shaders/ntsc-vcr/loose-connection.slang rename to vhs/shaders/static.slang index c11f90d..ad6bb36 100644 --- a/ntsc/shaders/ntsc-vcr/loose-connection.slang +++ b/vhs/shaders/static.slang @@ -22,8 +22,6 @@ layout(push_constant) uniform Push #pragma parameter magnitude "Distortion Magnitude" 0.9 0.0 25.0 0.1 #pragma parameter always_on "OSD Always On" 0.0 0.0 1.0 1.0 -#define framecount vec2(params.FrameCount, params.FrameCount).x - layout(std140, set = 0, binding = 0) uniform UBO { mat4 MVP; @@ -65,7 +63,7 @@ float n( in vec3 x ){ } //tape noise -float nn(vec2 p){ +float nn(vec2 p, float framecount){ float y = p.y; @@ -83,7 +81,7 @@ float nn(vec2 p){ return v; } -vec3 distort(sampler2D tex, vec2 uv, float magnitude){ +vec3 distort(sampler2D tex, vec2 uv, float magnitude, float framecount){ float mag = params.magnitude * 0.0001; vec2 offset_x = vec2(uv.x); @@ -95,17 +93,17 @@ vec3 distort(sampler2D tex, vec2 uv, float magnitude){ texture(tex, uv).b); } -float onOff(float a, float b, float c) +float onOff(float a, float b, float c, float framecount) { return step(c, sin((framecount * 0.001) + a*cos((framecount * 0.001)*b))); } -vec2 jumpy(vec2 uv) +vec2 jumpy(vec2 uv, float framecount) { vec2 look = uv; float window = 1./(1.+80.*(look.y-mod(framecount/4.,1.))*(look.y-mod(framecount/4.,1.))); - look.x += 0.05 * sin(look.y*10. + framecount)/20.*onOff(4.,4.,.3)*(0.5+cos(framecount*20.))*window; - float vShift = 0.4*onOff(2.,3.,.9)*(sin(framecount)*sin(framecount*20.) + + look.x += 0.05 * sin(look.y*10. + framecount)/20.*onOff(4.,4.,.3, framecount)*(0.5+cos(framecount*20.))*window; + float vShift = 0.4*onOff(2.,3.,.9, framecount)*(sin(framecount)*sin(framecount*20.) + (0.5 + 0.1*sin(framecount*200.)*cos(framecount))); look.y = mod(look.y - 0.01 * vShift, 1.); return look; @@ -118,26 +116,26 @@ layout(location = 0) out vec2 vTexCoord; void main() { - gl_Position = global.MVP * Position; - vTexCoord = TexCoord; + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; } #pragma stage fragment layout(location = 0) in vec2 vTexCoord; layout(location = 0) out vec4 FragColor; layout(set = 0, binding = 2) uniform sampler2D Source; -layout(set = 0, binding = 3) uniform sampler2D overlay; +layout(set = 0, binding = 3) uniform sampler2D play; void main() { -float timer = vec2(params.FrameCount, params.FrameCount).x; -vec3 res = distort(Source, jumpy(vTexCoord), params.magnitude); -float col = nn(-vTexCoord * params.SourceSize.y * 4.0); -vec3 play = distort(overlay, jumpy(vTexCoord), params.magnitude); -float overlay_alpha = texture(overlay, jumpy(vTexCoord)).a; -float show_overlay = (mod(timer, 100.0) < 50.0) && (timer < 500.0) ? texture(overlay, jumpy(vTexCoord)).a : 0.0; -show_overlay = clamp(show_overlay + params.always_on * overlay_alpha, 0.0, 1.0); -res = mix(res, play, show_overlay); + float timer = float(params.FrameCount); + vec3 res = distort(Source, jumpy(vTexCoord, timer), params.magnitude, timer); + float col = nn(-vTexCoord * params.SourceSize.y * 4.0, timer); + vec3 play_osd = distort(play, jumpy(vTexCoord, timer), params.magnitude, timer); + float overlay_alpha = texture(play, jumpy(vTexCoord, timer)).a; + float show_overlay = (mod(timer, 100.0) < 50.0) && (timer < 500.0) ? texture(play, jumpy(vTexCoord, timer)).a : 0.0; + show_overlay = clamp(show_overlay + params.always_on * overlay_alpha, 0.0, 1.0); + res = mix(res, play_osd, show_overlay); - FragColor = vec4(res + clamp(vec3(col), 0.0, 0.5), 1.0); + FragColor = vec4(res + clamp(vec3(col), 0.0, 0.5), 1.0); } \ No newline at end of file diff --git a/vhs/shaders/vhs.slang b/vhs/shaders/vhs.slang new file mode 100644 index 0000000..8eb6205 --- /dev/null +++ b/vhs/shaders/vhs.slang @@ -0,0 +1,169 @@ +#version 450 + +// VHS shader +// by hunterk +// adapted from ompuco's more AVdistortion shadertoy: +// https://www.shadertoy.com/view/XlsczN + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float wiggle; + float smear; +} params; + +#pragma parameter wiggle "Wiggle" 0.0 0.0 10.0 1.0 +#pragma parameter smear "Chroma Smear" 0.5 0.0 1.0 0.05 + +#define wiggle params.wiggle +#define smear params.smear +#define FrameCount params.FrameCount + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +#define iTime mod(float(FrameCount), 7.0) +#define iChannel0 Source + +//YIQ/RGB shit +vec3 rgb2yiq(vec3 c){ + return vec3( + (0.2989*c.x + 0.5959*c.y + 0.2115*c.z), + (0.5870*c.x - 0.2744*c.y - 0.5229*c.z), + (0.1140*c.x - 0.3216*c.y + 0.3114*c.z) + ); +} + +vec3 yiq2rgb(vec3 c){ + return vec3( + (1.0*c.x + 1.0*c.y + 1.0*c.z), + (0.956*c.x - 0.2720*c.y - 1.1060*c.z), + (0.6210*c.x - 0.6474*c.y + 1.7046*c.z) + ); +} + +vec2 Circle(float Start, float Points, float Point) +{ + float Rad = (3.141592 * 2.0 * (1.0 / Points)) * (Point + Start); + //return vec2(sin(Rad), cos(Rad)); + return vec2(-(.3+Rad), cos(Rad)); + +} + +vec3 Blur(vec2 uv, float d){ + float t = (sin(iTime*5.0+uv.y*5.0))/10.0; + float b = 1.0; + t=0.0; + vec2 PixelOffset=vec2(d+.0005*t,0); + + float Start = 2.0 / 14.0; + vec2 Scale = 0.66 * 4.0 * 2.0 * PixelOffset.xy; + + vec3 N0 = texture(iChannel0, uv + Circle(Start, 14.0, 0.0) * Scale).rgb; + vec3 N1 = texture(iChannel0, uv + Circle(Start, 14.0, 1.0) * Scale).rgb; + vec3 N2 = texture(iChannel0, uv + Circle(Start, 14.0, 2.0) * Scale).rgb; + vec3 N3 = texture(iChannel0, uv + Circle(Start, 14.0, 3.0) * Scale).rgb; + vec3 N4 = texture(iChannel0, uv + Circle(Start, 14.0, 4.0) * Scale).rgb; + vec3 N5 = texture(iChannel0, uv + Circle(Start, 14.0, 5.0) * Scale).rgb; + vec3 N6 = texture(iChannel0, uv + Circle(Start, 14.0, 6.0) * Scale).rgb; + vec3 N7 = texture(iChannel0, uv + Circle(Start, 14.0, 7.0) * Scale).rgb; + vec3 N8 = texture(iChannel0, uv + Circle(Start, 14.0, 8.0) * Scale).rgb; + vec3 N9 = texture(iChannel0, uv + Circle(Start, 14.0, 9.0) * Scale).rgb; + vec3 N10 = texture(iChannel0, uv + Circle(Start, 14.0, 10.0) * Scale).rgb; + vec3 N11 = texture(iChannel0, uv + Circle(Start, 14.0, 11.0) * Scale).rgb; + vec3 N12 = texture(iChannel0, uv + Circle(Start, 14.0, 12.0) * Scale).rgb; + vec3 N13 = texture(iChannel0, uv + Circle(Start, 14.0, 13.0) * Scale).rgb; + vec3 N14 = texture(iChannel0, uv).rgb; + + vec4 clr = texture(iChannel0, uv); + float W = 1.0 / 15.0; + + clr.rgb= + (N0 * W) + + (N1 * W) + + (N2 * W) + + (N3 * W) + + (N4 * W) + + (N5 * W) + + (N6 * W) + + (N7 * W) + + (N8 * W) + + (N9 * W) + + (N10 * W) + + (N11 * W) + + (N12 * W) + + (N13 * W) + + (N14 * W); + return vec3(clr.xyz)*b; +} + +float onOff(float a, float b, float c, float framecount) +{ + return step(c, sin((framecount * 0.001) + a*cos((framecount * 0.001)*b))); +} + +vec2 jumpy(vec2 uv, float framecount) +{ + vec2 look = uv; + float window = 1./(1.+80.*(look.y-mod(framecount/4.,1.))*(look.y-mod(framecount/4.,1.))); + look.x += 0.05 * sin(look.y*10. + framecount)/20.*onOff(4.,4.,.3, framecount)*(0.5+cos(framecount*20.))*window; + float vShift = (0.1*wiggle) * 0.4*onOff(2.,3.,.9, framecount)*(sin(framecount)*sin(framecount*20.) + + (0.5 + 0.1*sin(framecount*200.)*cos(framecount))); + look.y = mod(look.y - 0.01 * vShift, 1.); + return look; +} + +void main() +{ + float d = .1-round(mod(iTime/3.0,1.0))*.1; + vec2 uv = jumpy(vTexCoord.xy, iTime); + vec2 uv2 = uv; + + float s = 0.0001 * -d + 0.0001 * wiggle * sin(iTime); + + float e = min(.30,pow(max(0.0,cos(uv.y*4.0+.3)-.75)*(s+0.5)*1.0,3.0))*25.0; + float r = (iTime*(2.0*s)); + uv.x += abs(r*pow(min(.003,(-uv.y+(.01*mod(iTime, 17.0))))*3.0,2.0)); + + d = .051+abs(sin(s/4.0)); + float c = max(0.0001,.002*d) * smear; + vec2 uvo = uv; + vec4 final; + final.xyz =Blur(uv,c+c*(uv.x)); + float y = rgb2yiq(final.xyz).r; + + uv.x += .01*d; + c *= 6.0; + final.xyz =Blur(uv,c); + float i = rgb2yiq(final.xyz).g; + + uv.x += .005*d; + + c *= 2.50; + final.xyz =Blur(uv,c); + float q = rgb2yiq(final.xyz).b; + final = vec4(yiq2rgb(vec3(y,i,q))-pow(s+e*2.0,3.0), 1.0); + + FragColor = final; +} \ No newline at end of file diff --git a/vhs/vhs.slangp b/vhs/vhs.slangp new file mode 100644 index 0000000..9003756 --- /dev/null +++ b/vhs/vhs.slangp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/vhs.slang +filter_linear0 = true \ No newline at end of file