//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.yoy*(ln-w)) ////if(uv.y>oy*ln && uv.yoy*(ln-w)) ////if(uv.y>oy*ln && uv.y 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); }