add VHSPro ported from reshade

This commit is contained in:
hunterk 2020-06-19 16:19:28 -05:00
parent 9a8b4a70fc
commit 1ea4c2f33d
13 changed files with 1736 additions and 0 deletions

38
vhs/VHSPro.slangp Normal file
View file

@ -0,0 +1,38 @@
shaders = 6
#moved this to the first pass to avoid complications with feedback
shader0 = shaders/VHSPro/VHSPro_Third.slang
alias0 = third
scale_type0 = source
filter_linear0 = true
shader1 = shaders/VHSPro/VHSPro_Tape.slang
alias1 = tape
filter_linear1 = true
scale_type1 = source
shader2 = shaders/VHSPro/VHSPro_First.slang
alias2 = first
filter_linear2 = true
scale_type2 = source
shader3 = shaders/VHSPro/VHSPro_Second.slang
alias3 = second
filter_linear3 = true
scale_type3 = source
#doesn't really do anything for us
#shader4 = shaders/VHSPro/VHSPro_LastFrame.slang
#alias4 = lastframe
#filter_linear4 = true
#scale_type4 = source
shader4 = shaders/VHSPro/VHSPro_Forth.slang
alias4 = forth
filter_linear4 = true
scale_type4 = source
shader5 = shaders/VHSPro/VHSPro_Clear.slang
alias5 = clear
filter_linear5 = true
scale_type5 = source

View file

@ -0,0 +1,37 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#define SamplerColorVHS Source
#include "VHSPro_params.inc"
#include "VHSPro_constants.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 txcoord;
void main()
{
gl_Position = global.MVP * Position;
txcoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 txcoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#include "VHSPro_functions.inc"
void main()
{
FragColor = vec4(texture(SamplerColorVHS, txcoord).rgb, 1.0);
}

View file

@ -0,0 +1,282 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
int FrameDirection;
} params;
#define SamplerColorVHS Original
#include "VHSPro_params.inc"
#include "VHSPro_constants.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 txcoord;
void main()
{
gl_Position = global.MVP * Position;
txcoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 txcoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Original;
layout(set = 0, binding = 3) uniform sampler2D tape;
#include "VHSPro_functions.inc"
#define SamplerTape tape
void main()
{
const float t = float(params.FrameCount) * 0.0075;//_Time.y;
vec2 p = txcoord.xy;
float SLN = screenLinesNum; //TODO use only SLN
float SLN_Noise = noiseLinesNum; //TODO only SLN_Noise
float ONE_X = 0.0;
float ONE_Y = 0.0;
//basically if its 0 -> set it to fullscreen
//TODO calc it before shader / already float done
SLN = screenLinesNum; //TODO use only SLN
SLN_Noise = noiseLinesNum; //TODO only SLN_Noise
if(SLN==0.0) SLN = _ScreenParams.y;
if(SLN_Noise==0 || SLN_Noise>SLN) SLN_Noise = SLN;
ONE_X = 1.0/_ScreenParams.x; //assigning works only here
ONE_Y = 1.0/_ScreenParams.y;
if (VHS_Twitch_V){
p = twitchVertical(0.5*twitchVFreq, p, t);
}
if (VHS_Twitch_H){
p = twitchHorizonal(0.1*twitchHFreq, p, t);
}
//make discrete lines /w or wo float
if(VHS_LinesFloat){
float sh = fract(-t*linesFloatSpeed); //shift // float sh = fmod(t, 1.); //shift
// if(p.x>0.5)
p.y = -floor( -p.y * SLN + sh )/SLN + sh/SLN; //v1.3
// p.y = floor( p.y * SLN + sh )/SLN - sh/SLN; //v1.2
} else {
// if(p.x>0.5)
p.y = -floor( -p.y * SLN )/SLN; //v1.3
// p.y = floor( p.y * SLN )/SLN; //v1.2
}
if (VHS_Stretch){
p = stretch(p, t, 15.0, 1.0, 0.5, 0.0);
p = stretch(p, t, 8.0, 1.2, 0.45, 0.5);
p = stretch(p, t, 11.0, 0.5, -0.35, 0.25); //up
}
if (VHS_Jitter_H){
if( fmod( p.y * SLN, 2.0)<1.0)
p.x += ONE_X*sin(t*130.0)*jitterHAmount;
}
//just init
vec3 col = vec3(0.0,0.0,0.0);
vec3 signal = vec3(0.0,0.0,0.0);// rgb2yiq(col);
//gotta initiate all these things here coz of tape noise distortion
//[NOISE uv init]
//if SLN_Noise different from SLN->recalc linefloat
vec2 pn = p;
if(SLN!=SLN_Noise){
if(VHS_LineNoise){
const float sh = fract(t); //shift // float sh = fmod(t, 1.); //shift
pn.y = floor( pn.y * SLN_Noise + sh )/SLN_Noise - sh/SLN_Noise;
} else {
pn.y = floor( pn.y * SLN_Noise )/SLN_Noise;
}
}
//SLN_X is quantization of X. goest from _ScreenParams.x to SLN_X
const float ScreenLinesNumX = SLN_Noise * _ScreenParams.x / _ScreenParams.y;
const float SLN_X = noiseQuantizeX*(_ScreenParams.x - ScreenLinesNumX) + ScreenLinesNumX;
pn.x = floor( pn.x * SLN_X )/SLN_X;
const vec2 pn_ = pn*_ScreenParams.xy;
//TODO probably it shud be 1.0/SLN_Noise
const float ONEXN = 1.0/SLN_X;
//[//noise uv init]
float distShift = 0; // for 2nd part of tape noise
if (VHS_TapeNoise) {
//uv distortion part of tapenoise
distShift = 0; // for 2nd part of tape noise
for (int ii = 0; ii < 20 % 1023; ii++){
//this is t.n. line value at pn.y and down each pixel
//TODO i guess ONEXN shud be 1.0/sln noise
float tnl = textureLod(SamplerTape, vec2(0.0,pn.y-ONEXN*ii), 0.).y;
// float tnl = texture(SamplerTape, vec2(0.0,pn.y-ONEXN*ii)).y;
// float tnl = tapeNoiseLines(vec2(0.0,pn.y-ONEXN*i), t*tapeNoiseSpeed)*tapeNoiseAmount;
tnl -= 0.15 * float(params.FrameDirection);
// float fadediff = hash12(vec2(pn.x-ONEXN*i,pn.y));
if(tnl>0.27) {
//TODO get integer part other way
const float sh = sin( 1.0*PI*(float(ii)/float(20))) ; //0..1
p.x -= float(int(sh)*4.0*ONEXN); //displacement
distShift += sh ; //for 2nd part
// p.x += ONEXN * float(int(((tnl-thth)/thth)*4.0));
// col.x = sh;
}
}
}
//uv transforms over
//picture proccess start
if (VHS_Jitter_V){
signal = yiqDist(p, jitterVAmount, t*jitterVSpeed);
} else {
col = texture(SamplerColorVHS, p).rgb;
// col = vec3(p.xy, 0.0);//debug
signal = rgb2yiq(col);
}
if (VHS_LineNoise || VHS_FilmGrain){
signal.x += texture(SamplerTape, pn).z;
}
//iq noise from yiq
if (VHS_YIQNoise){
if (signalNoiseType == 0) {
//TODO make cheaper noise
//type 1 (best) w Y mask
const vec2 noise = n4rand_bw( pn_,t,1.0-signalNoisePower ) ;
signal.y += (noise.x*2.0-1.0)*signalNoiseAmount*signal.x;
signal.z += (noise.y*2.0-1.0)*signalNoiseAmount*signal.x;
} else if (signalNoiseType == 1){
//type 2
const vec2 noise = n4rand_bw( pn_,t, 1.0-signalNoisePower ) ;
signal.y += (noise.x*2.0-1.0)*signalNoiseAmount;
signal.z += (noise.y*2.0-1.0)*signalNoiseAmount;
} else {
//type 3
const vec2 noise = n4rand_bw( pn_,t, 1.0-signalNoisePower )*signalNoiseAmount ;
signal.y *= noise.x;
signal.z *= noise.y;
signal.x += (noise.x*2.0-1.0)*0.05;
}
}
//2nd part with noise, tail and yiq col shift
if (VHS_TapeNoise){
//here is normilized p (0..1)
float tn = texture(SamplerTape, pn).x;
signal.x = bms(signal.x, tn*tapeNoiseAmount ).x;
// float tn = tapeNoise(pn, t*tapeNoiseSpeed)*tapeNoiseAmount;
//tape noise tail
const int tailLength=10; //TODO adjustable
for(int j = 0; j < tailLength % 1023; j++){
const float jj = float(j);
const vec2 d = vec2(pn.x-ONEXN*jj,pn.y);
tn = textureLod(SamplerTape, vec2(d), 0. ).x;
// tn = texture(SamplerTape, d).x;
// tn = tapeNoise(vec2(pn.x-ONEXN*i,pn.y), t*tapeNoiseSpeed)*tapeNoiseAmount;
float fadediff = 0.0;
//for tails length difference
// if(__RENDERER__ == 0x0A100 || __RENDERER__ == 0x0B000) {
// fadediff = textureLod(SamplerTape, vec2(d), 0.).a; //hash12(d);
// }
// if(__RENDERER__ == 0x09300 || __RENDERER__ >= 0x10000) {
fadediff = texture(SamplerTape, d).a; //hash12(d);
// }
if( tn > 0.8 ){
float nsx = 0.0; //new signal x
const float newlength = float(tailLength)*(1.0-fadediff); //tail lenght diff
if( jj <= newlength ) nsx = 1.0-( jj/ newlength ); //tail
signal.x = bms(signal.x, nsx*tapeNoiseAmount).x;
}
}
//tape noise color shift
if(distShift>0.4){
// float tnl = tapeNoiseLines(vec2(0.0,pn.y), t*tapeNoiseSpeed)*tapeNoiseAmount;
const float tnl = texture(SamplerTape, pn).y;//tapeNoiseLines(vec2(0.0,pn.y), t*tapeNoiseSpeed)*tapeNoiseAmount;
signal.y *= 1.0/distShift;//tnl*0.1;//*distShift;//*signal.x;
signal.z *= 1.0/distShift;//*distShift;//*signal.x;
}
}
//back to rgb color space
//signal has negative values
col = yiq2rgb(signal);
//TODO put it into 2nd pass
if (VHS_ScanLines){
col *= scanLines(txcoord.xy, t);
}
//fisheye cutoff / outside fisheye
//helps to remove noise outside the fisheye
if (VHS_FishEye){
p = txcoord.xy;
float far;
const vec2 hco = vec2(ONE_X*cutoffX, ONE_Y*cutoffY) * 0.25; //hard cuttoff x
const vec2 sco = vec2(ONE_X*cutoffFadeX, ONE_Y*cutoffFadeY) * 0.25; //soft cuttoff x
//hard cutoff
if( p.x<=(0.0+hco.x) || p.x>=(1.0-hco.x) || p.y<=(0.0+hco.y) || p.y>=(1.0-hco.y) ){
col = vec3(0.0,0.0,0.0);
} else {
//fades
if( //X
(p.x>(0.0+hco.x) && p.x<(0.0+(sco.x+hco.x) )) || (p.x>(1.0-(sco.x+hco.x)) && p.x<(1.0-hco.x))
){
if(p.x<0.5) far = (0.0-hco.x+p.x)/(sco.x);
else
far = (1.0-hco.x-p.x)/(sco.x);
col *= float(far).xxx;
};
if( //Y
(p.y>(0.0+hco.y) && p.y<(0.0+(sco.y+hco.y) )) || (p.y>(1.0-(sco.y+hco.y)) && p.y<(1.0-hco.y))
){
if(p.y<0.5) far = (0.0-hco.y+p.y)/(sco.y);
else
far = (1.0-hco.y-p.y)/(sco.y);
col *= float(far).xxx;
}
}
}
// col = texture(SamplerTape, txcoord.xy).x;
FragColor = vec4(col, 1.0);
// FragColor = (VHS_TapeNoise && params.FrameDirection < 0) ? FragColor + (vec4(texture(tape, txcoord).g)) * 2. : FragColor;
}

View file

@ -0,0 +1,56 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#define SamplerColorVHS second
#define _FeedbackTex third
#include "VHSPro_params.inc"
#include "VHSPro_constants.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 texcoord;
void main()
{
gl_Position = global.MVP * Position;
texcoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 texcoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D second;
layout(set = 0, binding = 3) uniform sampler2D third;
#include "VHSPro_functions.inc"
void main()
{
// needed to add distortion here or the trails don't match up to the image
vec2 p = texcoord;
//distortions
if (VHS_FishEye){
p = fishEye(p, fisheyeSize, fisheyeBend); // p = fishEye(p, 1.2, 2.0);
// return vec4( fract(p*5.0)/2.5, 1.0, 1.0); //debug
}
vec3 col = texture( SamplerColorVHS, texcoord).rgb; //curent frame
const vec3 fbb = texture( _FeedbackTex, p).rgb; //feedback buffer
if (VHS_Feedback){
col = bm_screen(col, fbb*feedbackAmp);
if (feedbackDebug){
col = fbb;
}
}
FragColor = vec4(col, 1.0);
}

View file

@ -0,0 +1,49 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#define SamplerColorVHS second
#define _FeedbackTex Source
#include "VHSPro_params.inc"
#include "VHSPro_constants.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 texcoord;
void main()
{
gl_Position = global.MVP * Position;
texcoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 texcoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D second;
#include "VHSPro_functions.inc"
void main()
{
vec3 col = texture( SamplerColorVHS, texcoord).rgb; //curent frame
const vec3 fbb = texture( _FeedbackTex, texcoord).rgb; //feedback buffer
if (VHS_Feedback){
col = bm_screen(col, fbb*feedbackAmp);
if (feedbackDebug){
col = fbb;
}
}
FragColor = vec4(col, 1.0);
}

View file

@ -0,0 +1,152 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#define SamplerColorVHS Source
#include "VHSPro_params.inc"
#include "VHSPro_constants.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 txcoord;
void main()
{
gl_Position = global.MVP * Position;
txcoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 txcoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#include "VHSPro_functions.inc"
void main()
{
const float t = float(params.FrameCount) * 0.25;//_Time.y;
vec2 p = txcoord.xy;
float SLN = screenLinesNum; //TODO use only SLN
//basically if its 0 -> set it to fullscreen
if(SLN==0.0) SLN = _ScreenParams.y;
//TODO maybe make it based on num of lines? and height ?
//TODO make switch between real pixels and pixelated pixels!
// ONE_X = 1.0 / screenLinesNum;
float ONE_X = 1.0 / _ScreenParams.x; // 1px
ONE_X *= bleedAmount; // longer tails, more bleeding, default 1.
//distortions
if (VHS_FishEye){
p = fishEye(p, fisheyeSize, fisheyeBend); // p = fishEye(p, 1.2, 2.0);
// return vec4( fract(p*5.0)/2.5, 1.0, 1.0); //debug
}
int bleedLength = 21;
if((VHS_BleedMode == 0 || VHS_BleedMode == 1 || VHS_BleedMode == 3))
{
bleedLength = 25;
}
if((VHS_BleedMode == 2 || VHS_BleedMode == 4))
{
bleedLength = 32;
}
#include "taps.inc"
//Bleeding
vec3 signal = vec3(0.0,0.0,0.0);
if (VHS_Bleed){
vec3 norm = vec3(0.0,0.0,0.0);
vec3 adj = vec3(0.0,0.0,0.0);
const int taps = bleedLength-4;
//int taps = bleedLength; //RetroArch
for (int ii = 0; float(ii) < mod(float(taps) , float(1023)); ii++){
const float offset = float(ii);
const vec3 sums = fetch_offset(offset - float(taps), ONE_X) +
fetch_offset(float(taps) - offset, ONE_X) ;
adj = vec3(luma_filter[ii+3], chroma_filter[ii], chroma_filter[ii]);
//adj = vec3(luma_filter[ii], chroma_filter[ii], chroma_filter[ii]); //RetroArch
signal += sums * adj;
norm += adj;
}
adj = vec3(luma_filter[taps], chroma_filter[taps], chroma_filter[taps]);
signal += t2d(fixCoord) * adj;
norm += adj;
signal = signal / norm;
} else {
//no bleeding
signal = t2d(p);
}
//[Signal Tweak]
if (VHS_SignalTweak){
//adjust
signal.x += signalAdjustY;
signal.y += signalAdjustI;
signal.z += signalAdjustQ;
//shift
signal.x *= signalShiftY;
signal.y *= signalShiftI;
signal.z *= signalShiftQ;
// //test YIQ
// signal.x = 0.5;
// signal.y = p.x*2.0-1.0;
// signal.z = p.y*2.0-1.0;
//signal noise
// vec2 noise = n4rand_bw( p,t, 1.0-signalNoisePower )*signalNoiseAmount ;
// signal.y *= noise.x;
// signal.z *= noise.y;
//phase - it cant be dont coz of intervals
// signal.x = fract( (signal.x +1.0)*0.5f )*2.0f - 1.0f ;
//signal.y = fract( (signal.y +1.0)*0.5f )*2.0f - 1.0f ;
//signal.z = fract( (signal.z +1.0)*0.5f )*2.0f - 1.0f ;
}
vec3 rgb = yiq2rgb(signal);
if (VHS_SignalTweak){
if(gammaCorection!=1.0) rgb = pow(abs(rgb), vec3(gammaCorection)); //vec3(gammaCorection).rgb
}
//cut trash after fish eye
// if( p.x<0. || p.x>1. || p.y<0. || p.y>1.){
// rgb *= 0.0;
// }
//TODO maybe on yiq channel
if (VHS_Vignette){
rgb *= vignette(p, t*vignetteSpeed); //TODO params //txcoord.xy
}
FragColor = vec4(rgb, 1.0);
}

View file

@ -0,0 +1,68 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#define SamplerColorVHS Original
#include "VHSPro_params.inc"
#include "VHSPro_constants.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 txcoord;
void main()
{
gl_Position = global.MVP * Position;
txcoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 txcoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Original;
#include "VHSPro_functions.inc"
void main()
{
const float t = float(params.FrameCount) * 0.025;
vec2 p = txcoord.xy;
p.y=1-p.y;
const vec2 p_ = p*_ScreenParams;
float ns = 0.0; //signal noise //tex2D(_TapeTex, p);
float nt = 0.0; //tape noise
float nl = 0.0; //lines for tape noise
float ntail = 0.0; //tails values for tape noise
if (VHS_TapeNoise) {
//here is normilized p (0..1)
nl = tapeNoiseLines(p, t*tapeNoiseSpeed)*1.0;//tapeNoiseAmount;
nt = tapeNoise(nl, p, t*tapeNoiseSpeed)*1.0;//tapeNoiseAmount;
ntail = hash12(p+ vec2(0.01,0.02) );
}
if (VHS_LineNoise) {
ns += lineNoise(p_, t*lineNoiseSpeed)*lineNoiseAmount;
// col += lineNoise(pn_, t*lineNoiseSpeed)*lineNoiseAmount;//i.uvn
}
//y noise from yiq
if (VHS_FilmGrain) {
//cheap n ok atm
ns += filmGrain((p_-0.5*_ScreenParams.xy)*0.5, t, filmGrainPower ) * filmGrainAmount;
}
FragColor = vec4(nt,nl,ns,ntail);
}

View file

@ -0,0 +1,66 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#include "VHSPro_params.inc"
#include "VHSPro_constants.inc"
#define SamplerColorVHS Original
#define VHS_InputB OriginalHistory1
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 texcoord;
void main()
{
gl_Position = global.MVP * Position;
texcoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 texcoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Original;
layout(set = 0, binding = 3) uniform sampler2D OriginalHistory1;
layout(set = 0, binding = 4) uniform sampler2D PassFeedback0;
#define _FeedbackTex PassFeedback0
#include "VHSPro_functions.inc"
void main()
{
vec2 p = texcoord.xy;
const float one_x = 1.0/_ScreenParams.x;
vec3 fc = texture( SamplerColorVHS, texcoord).rgb; // curent frame
//new feedback
const vec3 fl = texture( VHS_InputB, texcoord).rgb; //last frame without feedback
float diff = abs(fl.x-fc.x + fl.y-fc.y + fl.z-fc.z)/3.0; //dfference between frames
if(diff<feedbackThresh) diff = 0.0;
vec3 fbn = fc*diff*feedbackAmount; //feedback new
// fbn = vec3(0.0, 0.0, 0.0);
//feedback buffer
vec3 fbb = ( //blur old bufffer a bit
texture( _FeedbackTex, texcoord).rgb +
texture( _FeedbackTex, texcoord + vec2(one_x, 0.0)).rgb +
texture( _FeedbackTex, texcoord - vec2(one_x, 0.0)).rgb
) / 3.0;
fbb *= feedbackFade;
//blend
fc = bm_screen(fc, fbb);
fbn = bm_screen(fbn, fbb); //feedback
vec4 feedbackoutput = vec4(fc, 1.0);
vec4 feedback = vec4(fbn * feedbackColor, 1.0);
FragColor = feedback;
}

View file

@ -0,0 +1,21 @@
//textures and samplers
#ifndef screenLinesRes
#define screenLinesRes 480.0 //Screen Resolution (to use in _TapeTex, has to be the same as screenLinesNum)
#endif
#ifndef noiseLinesRes
#define noiseLinesRes 480.0 //Vertical Resolution (to use in _TapeTex, has to be the same as noiseLinesNum)
#endif
const float fisheyeSize = 1.2; //Size (DO NOT CHANGE)
const float filmGrainPower = 1.0; //Film Grain Power (DO NOT CHANGE)
const float feedbackAmp = 1.0; //Feedback Amp (DO NOT CHANGE)
#define _ScreenParams vec2(params.OutputSize.x, params.OutputSize.y)
#undef PixelSize
#define PixelSize vec2(params.OutputSize.z, params.OutputSize.w)
const float Pi2 = 6.283185307;
#define TEXHEIGHT int(noiseLinesRes)
#define TEXWIDTH int((float(TEXHEIGHT)*float(params.OutputSize.x)/float(params.OutputSize.y)))

View file

@ -0,0 +1,361 @@
//functions
#define PI 3.14159265359
const vec3 MOD3 = vec3(443.8975, 397.2973, 491.1871);
float fmod(float a, float b) {
const float c = fract(abs(a / b)) * abs(b);
if (a < 0)
return -c;
else
return c;
}
vec3 bms(vec3 c1, vec3 c2){ return 1.0- (1.0-c1)*(1.0-c2); }
float bms(float c1, float c2){ return 1.0- (1.0-c1)*(1.0-c2); }
//turns sth on and off //a - how often
float onOff(float a, float b, float c, float t)
{
return step(c, sin(t + a*cos(t*b)));
}
float hash( float n ){ return fract(sin(n)*43758.5453123); }
float hash12(vec2 p){
vec3 p3 = fract(vec3(p.xyx) * MOD3);
p3 += dot(p3, p3.yzx + 19.19);
return fract(p3.x * p3.z * p3.y);
}
vec2 hash22(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * MOD3);
p3 += dot(p3.zxy, p3.yzx+19.19);
return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y));
}
//random hash
vec4 hash42(vec2 p)
{
vec4 p4 = fract(vec4(p.xyxy) * vec4(443.8975,397.2973, 491.1871, 470.7827));
p4 += dot(p4.wzxy, p4 + 19.19);
return fract(vec4(p4.x * p4.y, p4.x*p4.z, p4.y*p4.w, p4.x*p4.w));
}
float niq( in vec3 x ){
const vec3 p = floor(x);
vec3 f = fract(x);
f = f*f*(3.0-2.0*f);
const float n = p.x + p.y*57.0 + 113.0*p.z;
return mix(mix( mix( hash(n+ 0.0), hash(n+ 1.0),f.x),
mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y),
mix( mix( hash(n+113.0), hash(n+114.0),f.x),
mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}
float filmGrain(vec2 uv, float t, float c )
{
//cheap noise - is ok atm
return pow(hash12( uv + 0.07*fract( t ) ), 3);
}
vec2 n4rand_bw( vec2 p, float t, float c )
{
t = fract( t );//that's why its sort of twitching
vec2 nrnd0 = hash22( p + 0.07*t );
c = 1.0 / (10.0*c); //iMouse.y / iResolution.y
return pow(nrnd0, vec2(c,c)); //TODO try to invert 1-...
}
float scanLines(vec2 p, float t)
{
//cheap (maybe make an option later)
// float scanLineWidth = 0.26;
// float scans = 0.5*(cos((p.y*screenLinesNum+t+.5)*2.0*PI) + 1.0);
// if(scans>scanLineWidth) scans = 1.; else scans = 0.;
float t_sl = 0.0;
//if lines aren't floating -> scanlines also shudn't
if (VHS_LinesFloat) {
t_sl = t*linesFloatSpeed;
}
//expensive but better
float scans = 0.5*(cos( (p.y*(screenLinesNum * 0.5)+t_sl)*2.0*PI) + 1.0);
scans = pow(scans, scanLineWidth);
return 1.0 - scans;
}
float gcos(vec2 uv, float s, float p)
{
return (cos( uv.y * PI * 2.0 * s + p)+1.0)*0.5;
}
//mw - maximum width
//wcs = widthChangeSpeed
//lfs = line float speed = .5
//lf phase = line float phase = .0
vec2 stretch(vec2 uv, float t, float mw, float wcs, float lfs, float lfp){
const float SLN = screenLinesNum; //TODO use only SLN
//width change
const float tt = t*wcs; //widthChangeSpeed
const float t2 = tt-fmod(tt, 0.5);
//float dw = hash42( vec2(0.01, t2) ).x ; //on t and not on y
float w = gcos(uv, 2.0*(1.0-fract(t2)), PI-t2) * clamp( gcos(uv, fract(t2), t2) , 0.5, 1.0);
//w = clamp(w,0.,1.);
w = floor(w*mw)/mw;
w *= mw;
//get descreete line number
float ln = (1.0-fract(t*lfs + lfp)) *screenLinesNum;
ln = ln - fract(ln);
// float ln = (1.-fmod(t*lfs + lfp, 1.))*SLN;
// ln = ln - fmod(ln, 1.); //descreete line number
//ln = 10.;
//w = 4.;
//////stretching part///////
const float oy = 1.0/SLN; //TODO global
const float sh2 = 1.0 - fmod(ln, w)/w; // shift 0..1
// #if VHS_LINESFLOAT_ON
// float sh = fmod(t, 1.);
// uv.y = floor( uv.y *SLN +sh )/SLN - sh/SLN;
// #else
// uv.y = floor( uv.y *SLN )/SLN;
// #endif
// uv.y = floor( uv.y *SLN )/SLN ;
const float slb = SLN / w; //screen lines big
//TODO finish
// #if VHS_LINESFLOAT_ON
// if(uv.y<oy*ln && uv.y>oy*(ln-w)) ////if(uv.y>oy*ln && uv.y<oy*(ln+w))
// uv.y = floor( uv.y*slb +sh2 +sh )/slb - (sh2-1.)/slb - sh/slb;
// #else
if(uv.y<oy*ln && uv.y>oy*(ln-w)) ////if(uv.y>oy*ln && uv.y<oy*(ln+w))
uv.y = floor( uv.y*slb +sh2 )/slb - (sh2-1.0)/slb ;
// #endif
return uv;
}
float rnd_rd(vec2 co)
{
return fract(sin(fmod(dot(co.xy ,vec2(12.9898,78.233)),3.14)) * 43758.5453);
}
//DANG WINDOWS
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);
}
//rgb distortion
vec3 rgbDistortion(vec2 uv, float magnitude, float t)
{
magnitude *= 0.0001; // float magnitude = 0.0009;
vec3 offsetX = vec3( uv.x, uv.x, uv.x );
offsetX.r += rnd_rd(vec2(t*0.03,uv.y*0.42)) * 0.001 + sin(rnd_rd(vec2(t*0.2, uv.y)))*magnitude;
offsetX.g += rnd_rd(vec2(t*0.004,uv.y*0.002)) * 0.004 + sin(t*9.0)*magnitude;
// offsetX.b = uv.y + rnd_rd(vec2(cos(t*0.01),sin(uv.y)))*magnitude;
// offsetX.b = uv.y + rand_rd(vec2(cos(t*0.01),sin(uv.y)))*magnitude;
vec3 col = vec3(0.0, 0.0, 0.0);
//it cud be optimized / but hm
col.x = rgb2yiq( texture( SamplerColorVHS, vec2(offsetX.r, uv.y) ).rgb ).x;
col.y = rgb2yiq( texture( SamplerColorVHS, vec2(offsetX.g, uv.y) ).rgb ).y;
col.z = rgb2yiq( texture( SamplerColorVHS, vec2(offsetX.b, uv.y) ).rgb ).z;
col = yiq2rgb(col);
return col;
}
float rndln(vec2 p, float t)
{
float sample_ln = rnd_rd(vec2(1.0,2.0*cos(t))*t*8.0 + p*1.0).x;
sample_ln *= sample_ln;//*sample;
return sample_ln;
}
float lineNoise(vec2 p, float t)
{
float n = rndln(p* vec2(0.5,1.0) + vec2(1.0,3.0), t)*20.0;
float freq = abs(sin(t)); //1.
float c = n*smoothstep(fmod(p.y*4.0 + t/2.0+sin(t + sin(t*0.63)),freq), 0.0,0.95);
return c;
}
// 3d noise function (iq's)
float n( in vec3 x )
{
const vec3 p = floor(x);
vec3 f = fract(x);
f = f*f*(3.0-2.0*f);
const float n = p.x + p.y*57.0 + 113.0*p.z;
return mix(mix(mix( hash(n+0.0), hash(n+1.0),f.x),
mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y),
mix( mix( hash(n+113.0), hash(n+114.0),f.x),
mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}
float tapeNoiseLines(vec2 p, float t){
//so atm line noise is depending on hash for int values
//i gotta rewrite to for hash for 0..1 values
//then i can use normilized p for generating lines
const float y = p.y*_ScreenParams.y;
const float s = t*2.0;
return (niq( vec3(y*0.01 +s, 1.0, 1.0) ) + 0.0)
*(niq( vec3(y*0.011+1000.0+s, 1.0, 1.0) ) + 0.0)
*(niq( vec3(y*0.51+421.0+s, 1.0, 1.0) ) + 0.0)
;
}
float tapeNoise(float nl, vec2 p, float t){
//TODO custom adjustable density (Probability distribution)
// but will be expensive (atm its ok)
//atm its just contrast noise
//this generates noise mask
float nm = hash12( fract(p+t*vec2(0.234,0.637)) )
// *hash12( fract(p+t*vec2(0.123,0.867)) )
// *hash12( fract(p+t*vec2(0.441,0.23)) );
;
nm = pow(nm, 4) +0.3; //cheap and ok
//nm += 0.3 ; //just bit brighter or just more to threshold?
nl*= nm; // put mask
// nl += 0.3; //Value add .3//
if(nl<tapeNoiseTH) nl = 0.0; else nl =1.0; //threshold
return nl;
}
vec2 twitchVertical(float freq, vec2 uv, float t){
float vShift = 0.4*onOff(freq,3.0,0.9, t);
vShift*=(sin(t)*sin(t*20.0) + (0.5 + 0.1*sin(t*200.0)*cos(t)));
uv.y = fmod(uv.y + vShift, 1.0);
return uv;
}
vec2 twitchHorizonal(float freq, vec2 uv, float t){
uv.x += sin(uv.y*10.0 + t)/250.0*onOff(freq,4.0,0.3, t)*(1.0+cos(t*80.0))*(1.0/(1.0+20.0*(uv.y-fmod(t/4.0,1.0))*(uv.y-fmod(t/4.0, 1.0))));
return uv;
}
//all that shit is for postVHS"Pro"_First - end
//all that shit is for postVHS"Pro"_Second
//size 1.2, bend 2.
vec2 fishEye(vec2 uv, float size, float bend)
{
if (!VHS_FishEye_Hyperspace){
uv -= vec2(0.5,0.5);
uv *= size*(1.0/size+bend*uv.x*uv.x*uv.y*uv.y);
uv += vec2(0.5,0.5);
}
if (VHS_FishEye_Hyperspace){
//http://paulbourke.net/miscellaneous/lenscorrection/
const float prop = _ScreenParams.x / _ScreenParams.y;
const vec2 m = vec2(0.5, 0.5 / prop);
const vec2 d = (uv*_ScreenParams.xy) /_ScreenParams.x - m;
const float r = sqrt(dot(d, d));
float bind;
float power = ( 2.0 * 3.141592 / (2.0 * sqrt(dot(m, m))) ) *
(bend/50.0 - 0.5); //amount of effect
if (power > 0.0) bind = sqrt(dot(m, m));//stick to corners
else {if (prop < 1.0) bind = m.x; else bind = m.x;}//stick to borders
if (power > 0.0) //fisheye
uv = m + normalize(d) * tan(r * power) * bind / tan( bind * power);
else if (power < 0.0) //antifisheye
uv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
else uv = (uv*_ScreenParams.xy) /_ScreenParams.x;
uv.y *= prop;
}
//adjust size
// uv -= vec2(0.5,0.5);
// uv *= size;
// uv += vec2(0.5,0.5);
return uv;
}
//pulse vignette
float vignette(vec2 uv, float t)
{
const float vigAmt = 2.5+0.1*sin(t + 5.0*cos(t*5.0));
float c = (1.0-vigAmt*(uv.y-0.5)*(uv.y-0.5))*(1.0-vigAmt*(uv.x-0.5)*(uv.x-0.5));
c = pow(abs(c), vignetteAmount); //expensive!
return c;
}
vec3 t2d(vec2 p)
{
return rgb2yiq( texture (SamplerColorVHS, p ).rgb );
}
vec3 yiqDist(vec2 uv, float m, float t)
{
m *= 0.0001; // float m = 0.0009;
vec3 offsetX = vec3( uv.x, uv.x, uv.x );
offsetX.r += rnd_rd(vec2(t*0.03, uv.y*0.42)) * 0.001 + sin(rnd_rd(vec2(t*0.2, uv.y)))*m;
offsetX.g += rnd_rd(vec2(t*0.004,uv.y*0.002)) * 0.004 + sin(t*9.0)*m;
// offsetX.b = uv.y + rnd_rd(vec2(cos(t*0.01),sin(uv.y)))*m;
// offsetX.b = uv.y + rand_rd(vec2(cos(t*0.01),sin(uv.y)))*m;
vec3 signal = vec3(0.0, 0.0, 0.0);
//it cud be optimized / but hm
signal.x = rgb2yiq( texture( SamplerColorVHS, vec2(offsetX.r, uv.y) ).rgb ).x;
signal.y = rgb2yiq( texture( SamplerColorVHS, vec2(offsetX.g, uv.y) ).rgb ).y;
signal.z = rgb2yiq( texture( SamplerColorVHS, vec2(offsetX.b, uv.y) ).rgb ).z;
// signal = yiq2rgb(col);
return signal;
}
#define fixCoord (p - vec2( 0.5 * PixelSize.x, .0))
#define fetch_offset(offset, one_x) t2d(fixCoord + vec2( (offset) * (ONE_X), 0.0));
vec3 bm_screen(vec3 a, vec3 b){ return 1.0- (1.0-a)*(1.0-b); }

View file

@ -0,0 +1,246 @@
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
float screenLinesNum, VHS_Bleed_toggle, VHS_BleedMode_select, bleedAmount, VHS_FishEye_toggle,
VHS_FishEye_Hyperspace_toggle, fisheyeBend, cutoffX, cutoffY, cutoffFadeX, cutoffFadeY,
VHS_Vignette_toggle, vignetteAmount, vignetteSpeed, noiseLinesLum, noiseQuantizeX,
VHS_FilmGrain_toggle, filmGrainAmount, VHS_YIQNoise_toggle, signalNoiseType_select,
signalNoiseAmount, signalNoisePower, VHS_LineNoise_toggle, lineNoiseAmount, lineNoiseSpeed,
VHS_TapeNoise_toggle, tapeNoiseTH, tapeNoiseAmount, tapeNoiseSpeed, VHS_ScanLines_toggle,
scanLineWidth, VHS_LinesFloat_toggle, linesFloatSpeed, VHS_Stretch_toggle,VHS_Jitter_H_toggle,
jitterHAmount, VHSJitter_V_toggle, jitterVAmount, jitterVSpeed, VHS_Twitch_H_toggle,
twitchHFreq, VHS_Twitch_V_toggle, twitchVFreq, VHS_SignalTweak_toggle, signalAdjustY,
signalAdjustI, signalAdjustQ, signalShiftY, signalShiftI, signalShiftQ, gammaCorection,
VHS_Feedback_toggle, feedbackAmount, feedbackFade, feedbackThresh, feedbackColor_R,
feedbackColor_G, feedbackColor_B, feedbackDebug_toggle, noiseLinesNum;
} global;
#pragma parameter screenLinesNum "Screen Resolution [VHSPro]" 1080.0 1.0 2160.0 16.0
#define screenLinesNum global.screenLinesNum
// "Screen Resolution (in lines).\nChange screenLinesRes in Preprocessor Definitions to have the same value as this."
#pragma parameter VHS_Bleed_toggle "Toggle Bleeding [VHSPro]" 1.0 0.0 1.0 1.0
bool VHS_Bleed = bool(global.VHS_Bleed_toggle);
// "Enables beam screen bleeding (makes the image blurry)."
#pragma parameter VHS_BleedMode_select "Bleeding Mode [VHSPro]" 1.0 1.0 5.0 1.0
int VHS_BleedMode = int(global.VHS_BleedMode_select);
// "Toggles between different bleeding modes."
#pragma parameter bleedAmount "Bleed Stretch [VHSPro]" 0.5 0.0 15.0 0.1
#define bleedAmount global.bleedAmount
// "Length of the bleeding." // default value of 1.0 was too much
#pragma parameter VHS_FishEye_toggle "Toggle Fisheye [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_FishEye = bool(global.VHS_FishEye_toggle);
// "Enables a CRT Curvature." // defaulting to off
#pragma parameter VHS_FishEye_Hyperspace_toggle "Toggle Fisheye Hyperspace [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_FishEye_Hyperspace = bool(global.VHS_FishEye_Hyperspace_toggle);
// "Changes the curvature to look like some sort of hyperspace warping."
#pragma parameter fisheyeBend "Fisheye Bend [VHSPro]" 0.5 0.0 3.0 0.05
#define fisheyeBend global.fisheyeBend
// "Curvature of the CRT." // default value of 2.0 was way too high
#pragma parameter cutoffX "Fisheye Cutoff X [VHSPro]" 2.0 0.0 50.0 1.0
#define cutoffX global.cutoffX
// "Cutoff of the Horizontal Borders."
#pragma parameter cutoffY "Fisheye Cutoff Y [VHSPro]" 3.0 0.0 50.0 1.0
#define cutoffY global.cutoffY
// "Cutoff of the Vertical Borders."
#pragma parameter cutoffFadeX "Fisheye Cutoff Fade X [VHSPro]" 25.0 0.0 50.0 1.0
#define cutoffFadeX global.cutoffFadeX
// "Size of the Horizontal gradient cutoff."
#pragma parameter cutoffFadeY "Fisheye Cutoff Fade Y [VHSPro]" 25.0 0.0 50.0 1.0
#define cutoffFadeY global.cutoffFadeY
// "Size of the Vertical gradient cutoff."
#pragma parameter VHS_Vignette_toggle "Toggle Vignette [VHSPro]" 1.0 0.0 1.0 1.0
bool VHS_Vignette = bool(global.VHS_Vignette_toggle);
// "Enables screen vignetting" // default to 'on' to make up for lost fisheye
#pragma parameter vignetteAmount "Vignette Amount [VHSPro]" 0.3 0.0 5.0 0.05
#define vignetteAmount global.vignetteAmount
// "Strength of the vignette." // default value of 1.0 was way too much
#pragma parameter vignetteSpeed "Vignette Pulse Speed [VHSPro]" 1.0 0.0 5.0 0.05
#define vignetteSpeed global.vignetteSpeed
// "Speed of the vignette pulsing. (Setting it to 0 makes it stop pulsing)"
#pragma parameter noiseLinesNum "Vertical Resolution [VHSPro]" 240.0 1.0 1080.0 16.0
#define noiseLinesNum global.noiseLinesNum
// "Noise Resolution (in lines).\nChange noiseLinesRes in Preprocessor Definitions to have the same value as this."
#pragma parameter noiseQuantizeX "Quantize Noise X [VHSPro]" 0.0 0.0 1.0 0.01
#define noiseQuantizeX global.noiseQuantizeX
// "Makes the noise longer or shorter."
#pragma parameter VHS_FilmGrain_toggle "Toggle Film Grain [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_FilmGrain = bool(global.VHS_FilmGrain_toggle);
// "Enables a Film Grain on the screen."
#pragma parameter filmGrainAmount "Film Grain Alpha [VHSPro]" 0.5 0.0 1.0 0.01
float filmGrainAmount = global.filmGrainAmount * 0.1;
// "Intensity of the Film Grain." // default was too low
#pragma parameter VHS_YIQNoise_toggle "Toggle Signal Noise [VHSPro]" 1.0 0.0 1.0 1.0
bool VHS_YIQNoise = bool(global.VHS_YIQNoise_toggle);
// "Adds noise to the YIQ Signal, causing a Pink (or green) noise."
#pragma parameter signalNoiseType_select "Signal Noise Type [VHSPro]" 1.0 1.0 3.0 1.0
int signalNoiseType = int(global.signalNoiseType_select);
// "Signal Noise Type [VHS Pro]"
#pragma parameter signalNoiseAmount "Signal Noise Amount [VHSPro]" 0.10 0.0 1.0 0.01
#define signalNoiseAmount global.signalNoiseAmount
// "Amount of the signal noise."
#pragma parameter signalNoisePower "Signal Noise Power [VHSPro]" 0.75 0.0 1.0 0.01
#define signalNoisePower global.signalNoisePower
// "Power of the signal noise. Higher values will make it green, lower values will make it more pink."
#pragma parameter VHS_LineNoise_toggle "Toggle Line Noise [VHSPro]" 1.0 0.0 1.0 1.0
bool VHS_LineNoise = bool(global.VHS_LineNoise_toggle);
// "Enables blinking line noise in the image."
#pragma parameter lineNoiseAmount "Line Noise Amount [VHSPro]" 1.0 0.0 10.0 0.1
#define lineNoiseAmount global.lineNoiseAmount
// "Intensity of the line noise."
#pragma parameter lineNoiseSpeed "Line Noise Speed [VHSPro]" 5.0 0.0 10.0 0.1
#define lineNoiseSpeed global.lineNoiseSpeed
// "Speed of the line noise blinking delay."
#pragma parameter VHS_TapeNoise_toggle "Toggle Tape Noise [VHSPro]" 1.0 0.0 1.0 1.0
bool VHS_TapeNoise = bool(global.VHS_TapeNoise_toggle);
// "Adds scrolling noise like in old VHS Tapes."
#pragma parameter tapeNoiseTH "Tape Noise Amount [VHSPro]" 0.63 0.0 1.5 0.01
#define tapeNoiseTH global.tapeNoiseTH
// "Intensity of Tape Noise in the image."
#pragma parameter tapeNoiseAmount "Tape Noise Alpha [VHSPro]" 0.05 0.0 1.5 0.01
#define tapeNoiseAmount global.tapeNoiseAmount
// "Amount of Tape Noise in the image."
#pragma parameter tapeNoiseSpeed "Tape Noise Speed [VHSPro]" 1.0 -1.5 1.5 0.05
#define tapeNoiseSpeed global.tapeNoiseSpeed
// "Scrolling speed of the Tape Noise."
#pragma parameter VHS_ScanLines_toggle "Toggle Scanlines [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_ScanLines = bool(global.VHS_ScanLines_toggle);
// "Enables TV/CRT Scanlines."
#pragma parameter scanLineWidth "Scanlines Width [VHSPro]" 10.0 0.0 20.0 0.25
#define scanLineWidth global.scanLineWidth
// "Width of the Scanlines."
#pragma parameter VHS_LinesFloat_toggle "Toggle Lines Float [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_LinesFloat = bool(global.VHS_LinesFloat_toggle);
// "Makes the lines of the screen floats up or down. Works best with low Screen Lines resolutions."
#pragma parameter linesFloatSpeed "Lines Float Speed [VHSPro]" 1.0 -3.0 3.0 0.1
#define linesFloatSpeed global.linesFloatSpeed
// "Speed (and direction) of the floating lines."
#pragma parameter VHS_Stretch_toggle "Toggle Stretch Noise" 1.0 0.0 1.0 1.0
bool VHS_Stretch = bool(global.VHS_Stretch_toggle);
// "Enables a stretching noise that scrolls up and down on the Image, simulating magnetic interference of VHS tapes."
#pragma parameter VHS_Jitter_H_toggle "Toggle Interlacing [VHSPro]" 1.0 0.0 1.0 1.0
bool VHS_Jitter_H = bool(global.VHS_Jitter_H_toggle);
// "Enables interlacing."
#pragma parameter jitterHAmount "Interlacing Amount [VHSPro]" 0.15 0.0 5.0 0.05
#define jitterHAmount global.jitterHAmount
// "Strength of the Interlacing." //default 0.50 was too much
#pragma parameter VHSJitter_V_toggle "Toggle Jitter [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_Jitter_V = bool(global.VHSJitter_V_toggle);
// "Adds vertical jittering noise."
#pragma parameter jitterVAmount "Jitter Amount [VHSPro]" 7.5 0.0 15.0 0.1
#define jitterVAmount global.jitterVAmount
// "Amount of the vertical jittering noise." //default 1.0 was invisible
#pragma parameter jitterVSpeed "Jitter Speed [VHSPro]" 1.0 0.0 5.0 0.1
#define jitterVSpeed global.jitterVSpeed
// "Speed of the vertical jittering noise."
#pragma parameter VHS_Twitch_H_toggle "Toggle Horizontal Twitch [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_Twitch_H = bool(global.VHS_Twitch_H_toggle);
// "Makes the image twitches horizontally in certain timed intervals."
#pragma parameter twitchHFreq "Horizontal Twitch Frequency [VHSPro]" 1.0 0.0 5.0 0.1
#define twitchHFreq global.twitchHFreq
// "Frequency of time in which the image twitches horizontally."
#pragma parameter VHS_Twitch_V_toggle "Toggle Vertical Twitch [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_Twitch_V = bool(global.VHS_Twitch_V_toggle);
// "Makes the image twitches vertically in certain timed intervals."
#pragma parameter twitchVFreq "Vertical Twitch Frequency [VHSPro]" 1.0 0.0 5.0 0.1
#define twitchVFreq global.twitchVFreq
// "Frequency of time in which the image twitches vertically."
#pragma parameter VHS_SignalTweak_toggle "Toggle Signal Tweak [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_SignalTweak = bool(global.VHS_SignalTweak_toggle);
// "Tweak the values of the YIQ signal."
#pragma parameter signalAdjustY "Signal Shift Y [VHSPro]" 0.0 -0.25 0.25 0.01
#define signalAdjustY global.signalAdjustY
// "Shifts/Tweaks the Luma part of the signal."
#pragma parameter signalAdjustI "Signal Shift I [VHSPro]" 0.0 -0.25 0.25 0.01
#define signalAdjustI global.signalAdjustI
// "Shifts/Tweaks the Chroma part of the signal."
#pragma parameter signalAdjustQ "Signal Shift Q [VHSPro]" 0.0 -0.25 0.25 0.01
#define signalAdjustQ global.signalAdjustQ
// "Shifts/Tweaks the Chroma part of the signal."
#pragma parameter signalShiftY "Signal Adjust Y [VHSPro]" 1.0 -2.0 2.0 0.05
#define signalShiftY global.signalShiftY
// "Adjusts the Luma part of the signal."
#pragma parameter signalShiftI "Signal Adjust I [VHSPro]" 1.0 -2.0 2.0 0.05
#define signalShiftI global.signalShiftI
// "Adjusts the Chroma part of the signal."
#pragma parameter signalShiftQ "Signal Adjust Q [VHSPro]" 1.0 -2.0 2.0 0.05
#define signalShiftQ global.signalShiftQ
// "Adjusts the Chroma part of the signal."
#pragma parameter gammaCorection "Signal Gamma Correction [VHSPro]" 1.0 0.0 2.0 0.05
#define gammaCorection global.gammaCorection
// "Gamma corrects the image."
#pragma parameter VHS_Feedback_toggle "Toggle Phosphor Trails [VHSPro]" 0.0 0.0 1.0 1.0
bool VHS_Feedback = bool(global.VHS_Feedback_toggle);
// "Enables phosphor-trails from old CRT monitors."
#pragma parameter feedbackAmount "Input Amount [VHSPro]" 2.0 0.0 3.0 0.05
#define feedbackAmount global.feedbackAmount
// "Amount of Phosphor Trails."
#pragma parameter feedbackFade "Phosphor Fade [VHSPro]" 0.82 0.0 1.0 0.01
#define feedbackFade global.feedbackFade
// "Fade-time of the phosphor-trails."
#pragma parameter feedbackThresh "Input Cutoff [VHSPro]" 0.1 0.0 1.0 0.01
#define feedbackThresh global.feedbackThresh
// "Cutoff of the trail."
#pragma parameter feedbackColor_R "Red Tint of Phosphor Trail" 1.0 0.0 1.0 0.01
#pragma parameter feedbackColor_G "Green Tint of Phosphor Trail" 0.5 0.0 1.0 0.01
#pragma parameter feedbackColor_B "Blue Tint of Phosphor Trail" 0.0 0.0 1.0 0.01
vec3 feedbackColor = vec3(global.feedbackColor_R, global.feedbackColor_G, global.feedbackColor_B);
// "Color of the trail."
#pragma parameter feedbackDebug_toggle "Toggle Debug Trail [VHSPro]" 0.0 0.0 1.0 1.0
bool feedbackDebug = bool(global.feedbackDebug_toggle);
// "Enables the visualization of the phosphor-trails only."

View file

@ -0,0 +1,42 @@
#version 450
layout(push_constant) uniform Push
{
float mixfactor;
} param;
#pragma parameter mixfactor "Motionblur Fadeout" 0.75 0.0 1.0 0.01
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
} 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;
layout(set = 0, binding = 3) uniform sampler2D PassFeedback0;
void main()
{
vec4 current = pow(texture(Source, vTexCoord), vec4(2.2));
vec4 fdback = pow(texture(PassFeedback0, vTexCoord), vec4(2.2));
vec4 mixed = (1.0 - param.mixfactor) * current + param.mixfactor * fdback;
FragColor = pow(mixed, vec4(1.0 / 2.2));
}

318
vhs/shaders/VHSPro/taps.inc Normal file
View file

@ -0,0 +1,318 @@
float luma_filter[33] = {
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000
};
float chroma_filter[33] = {
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000,
0.000000000
};
if (VHS_BleedMode == 0 || VHS_BleedMode == 3){ //Three Phase and Three Phase (RetroArch)
luma_filter[0] = -0.000012020;
luma_filter[1] = -0.000022146;
luma_filter[2] = -0.000013155;
luma_filter[3] = -0.000012020;
luma_filter[4] = -0.000049979;
luma_filter[5] = -0.000113940;
luma_filter[6] = -0.000122150;
luma_filter[7] = -0.000005612;
luma_filter[8] = 0.000170516;
luma_filter[9] = 0.000237199;
luma_filter[10] = 0.000169640;
luma_filter[11] = 0.000285688;
luma_filter[12] = 0.000984574;
luma_filter[13] = 0.002018683;
luma_filter[14] = 0.002002275;
luma_filter[15] = -0.000909882;
luma_filter[16] = -0.007049081;
luma_filter[17] = -0.013222860;
luma_filter[18] = -0.012606931;
luma_filter[19] = 0.002460860;
luma_filter[20] = 0.035868225;
luma_filter[21] = 0.084016453;
luma_filter[22] = 0.135563500;
luma_filter[23] = 0.175261268;
luma_filter[24] = 0.190176552;
chroma_filter[0] = -0.000118847;
chroma_filter[1] = -0.000271306;
chroma_filter[2] = -0.000502642;
chroma_filter[3] = -0.000930833;
chroma_filter[4] = -0.001451013;
chroma_filter[5] = -0.002064744;
chroma_filter[6] = -0.002700432;
chroma_filter[7] = -0.003241276;
chroma_filter[8] = -0.003524948;
chroma_filter[9] = -0.003350284;
chroma_filter[10] = -0.002491729;
chroma_filter[11] = -0.000721149;
chroma_filter[12] = 0.002164659;
chroma_filter[13] = 0.006313635;
chroma_filter[14] = 0.011789103;
chroma_filter[15] = 0.018545660;
chroma_filter[16] = 0.026414396;
chroma_filter[17] = 0.035100710;
chroma_filter[18] = 0.044196567;
chroma_filter[19] = 0.053207202;
chroma_filter[20] = 0.061590275;
chroma_filter[21] = 0.068803602;
chroma_filter[22] = 0.074356193;
chroma_filter[23] = 0.077856564;
chroma_filter[24] = 0.079052396;
}
else if (VHS_BleedMode == 1) { //Old Three-Phase
luma_filter[0] = -0.000071070;
luma_filter[1] = -0.000032816;
luma_filter[2] = 0.000128784;
luma_filter[3] = 0.000134711;
luma_filter[4] = -0.000226705;
luma_filter[5] = -0.000777988;
luma_filter[6] = -0.000997809;
luma_filter[7] = -0.000522802;
luma_filter[8] = 0.000344691;
luma_filter[9] = 0.000768930;
luma_filter[10] = 0.000275591;
luma_filter[11] = -0.000373434;
luma_filter[12] = 0.000522796;
luma_filter[13] = 0.003813817;
luma_filter[14] = 0.007502825;
luma_filter[15] = 0.006786001;
luma_filter[16] = -0.002636726;
luma_filter[17] = -0.019461182;
luma_filter[18] = -0.033792479;
luma_filter[19] = -0.029921972;
luma_filter[20] = 0.005032552;
luma_filter[21] = 0.071226466;
luma_filter[22] = 0.151755921;
luma_filter[23] = 0.218166470;
luma_filter[24] = 0.243902439;
chroma_filter[0] = 0.001845562;
chroma_filter[1] = 0.002381606;
chroma_filter[2] = 0.003040177;
chroma_filter[3] = 0.003838976;
chroma_filter[4] = 0.004795341;
chroma_filter[5] = 0.005925312;
chroma_filter[6] = 0.007242534;
chroma_filter[7] = 0.008757043;
chroma_filter[8] = 0.010473987;
chroma_filter[9] = 0.012392365;
chroma_filter[10] = 0.014503872;
chroma_filter[11] = 0.016791957;
chroma_filter[12] = 0.019231195;
chroma_filter[13] = 0.021787070;
chroma_filter[14] = 0.024416251;
chroma_filter[15] = 0.027067414;
chroma_filter[16] = 0.029682613;
chroma_filter[17] = 0.032199202;
chroma_filter[18] = 0.034552198;
chroma_filter[19] = 0.036677005;
chroma_filter[20] = 0.038512317;
chroma_filter[21] = 0.040003044;
chroma_filter[22] = 0.041103048;
chroma_filter[23] = 0.041777517;
chroma_filter[24] = 0.042004791;
}
else if (VHS_BleedMode == 2) { //Two-Phase
luma_filter[0] = -0.000205844;
luma_filter[1] = -0.000149453;
luma_filter[2] = -0.000051693;
luma_filter[3] = 0.000000000;
luma_filter[4] = -0.000066171;
luma_filter[5] = -0.000245058;
luma_filter[6] = -0.000432928;
luma_filter[7] = -0.000472644;
luma_filter[8] = -0.000252236;
luma_filter[9] = 0.000198929;
luma_filter[10] = 0.000687058;
luma_filter[11] = 0.000944112;
luma_filter[12] = 0.000803467;
luma_filter[13] = 0.000363199;
luma_filter[14] = 0.000013422;
luma_filter[15] = 0.000253402;
luma_filter[16] = 0.001339461;
luma_filter[17] = 0.002932972;
luma_filter[18] = 0.003983485;
luma_filter[19] = 0.003026683;
luma_filter[20] = -0.001102056;
luma_filter[21] = -0.008373026;
luma_filter[22] = -0.016897700;
luma_filter[23] = -0.022914480;
luma_filter[24] = -0.021642347;
luma_filter[25] = -0.008863273;
luma_filter[26] = 0.017271957;
luma_filter[27] = 0.054921920;
luma_filter[28] = 0.098342579;
luma_filter[29] = 0.139044281;
luma_filter[30] = 0.168055832;
luma_filter[31] = 0.178571429;
chroma_filter[0] = 0.001384762;
chroma_filter[1] = 0.001678312;
chroma_filter[2] = 0.002021715;
chroma_filter[3] = 0.002420562;
chroma_filter[4] = 0.002880460;
chroma_filter[5] = 0.003406879;
chroma_filter[6] = 0.004004985;
chroma_filter[7] = 0.004679445;
chroma_filter[8] = 0.005434218;
chroma_filter[9] = 0.006272332;
chroma_filter[10] = 0.007195654;
chroma_filter[11] = 0.008204665;
chroma_filter[12] = 0.009298238;
chroma_filter[13] = 0.010473450;
chroma_filter[14] = 0.011725413;
chroma_filter[15] = 0.013047155;
chroma_filter[16] = 0.014429548;
chroma_filter[17] = 0.015861306;
chroma_filter[18] = 0.017329037;
chroma_filter[19] = 0.018817382;
chroma_filter[20] = 0.020309220;
chroma_filter[21] = 0.021785952;
chroma_filter[22] = 0.023227857;
chroma_filter[23] = 0.024614500;
chroma_filter[24] = 0.025925203;
chroma_filter[25] = 0.027139546;
chroma_filter[26] = 0.028237893;
chroma_filter[27] = 0.029201910;
chroma_filter[28] = 0.030015081;
chroma_filter[29] = 0.030663170;
chroma_filter[30] = 0.031134640;
chroma_filter[31] = 0.031420995;
chroma_filter[32] = 0.031517031;
}
else if (VHS_BleedMode == 4) { //Two-Phase (RetroArch)
luma_filter[0] = -0.000174844;
luma_filter[1] = -0.000205844;
luma_filter[2] = -0.000149453;
luma_filter[3] = -0.000051693;
luma_filter[4] = 0.000000000;
luma_filter[5] = -0.000066171;
luma_filter[6] = -0.000245058;
luma_filter[7] = -0.000432928;
luma_filter[8] = -0.000472644;
luma_filter[9] = -0.000252236;
luma_filter[10] = 0.000198929;
luma_filter[11] = 0.000687058;
luma_filter[12] = 0.000944112;
luma_filter[13] = 0.000803467;
luma_filter[14] = 0.000363199;
luma_filter[15] = 0.000013422;
luma_filter[16] = 0.000253402;
luma_filter[17] = 0.001339461;
luma_filter[18] = 0.002932972;
luma_filter[19] = 0.003983485;
luma_filter[20] = 0.003026683;
luma_filter[21] = -0.001102056;
luma_filter[22] = -0.008373026;
luma_filter[23] = -0.016897700;
luma_filter[24] = -0.022914480;
luma_filter[25] = -0.021642347;
luma_filter[26] = -0.008863273;
luma_filter[27] = 0.017271957;
luma_filter[28] = 0.054921920;
luma_filter[29] = 0.098342579;
luma_filter[30] = 0.139044281;
luma_filter[31] = 0.168055832;
luma_filter[32] = 0.178571429;
chroma_filter[0] = 0.001384762;
chroma_filter[1] = 0.001678312;
chroma_filter[2] = 0.002021715;
chroma_filter[3] = 0.002420562;
chroma_filter[4] = 0.002880460;
chroma_filter[5] = 0.003406879;
chroma_filter[6] = 0.004004985;
chroma_filter[7] = 0.004679445;
chroma_filter[8] = 0.005434218;
chroma_filter[9] = 0.006272332;
chroma_filter[10] = 0.007195654;
chroma_filter[11] = 0.008204665;
chroma_filter[12] = 0.009298238;
chroma_filter[13] = 0.010473450;
chroma_filter[14] = 0.011725413;
chroma_filter[15] = 0.013047155;
chroma_filter[16] = 0.014429548;
chroma_filter[17] = 0.015861306;
chroma_filter[18] = 0.017329037;
chroma_filter[19] = 0.018817382;
chroma_filter[20] = 0.020309220;
chroma_filter[21] = 0.021785952;
chroma_filter[22] = 0.023227857;
chroma_filter[23] = 0.024614500;
chroma_filter[24] = 0.025925203;
chroma_filter[25] = 0.027139546;
chroma_filter[26] = 0.028237893;
chroma_filter[27] = 0.029201910;
chroma_filter[28] = 0.030015081;
chroma_filter[29] = 0.030663170;
chroma_filter[30] = 0.031134640;
chroma_filter[31] = 0.031420995;
chroma_filter[32] = 0.031517031;
}