#version 330 in vec2 fragTexCoord; uniform sampler2D texture0; uniform vec4 resolution; // Horizonal scan blur // 0.50 := blurry // 0.75 := default // 1.00 := blocky #define INPUT_BLUR 0.5 //-------------------------------------------------------------- // Setup the function which returns gather4 results // Have to emulate gather4 as ShaderToy doesn't support it // Gather 4 ordering // W Z // X Y vec4 RvmR4F(sampler2D tex, vec2 uv){ vec2 px = vec2(1.0) / vec2(textureSize(tex, 0)); px *= 0.5; vec4 sample; sample.w = texture(tex, uv.xy + vec2(-px.x,-px.y)).r; sample.z = texture(tex, uv.xy + vec2( px.x,-px.y)).r; sample.x = texture(tex, uv.xy + vec2(-px.x, px.y)).r; sample.y = texture(tex, uv.xy + vec2( px.x, px.y)).r; return sample; } // vec4 RvmG4F(sampler2D tex, vec2 uv){ vec2 px = vec2(1.0) / vec2(textureSize(tex, 0)); px *= 0.5; vec4 sample; sample.w = texture(tex, uv.xy + vec2(-px.x,-px.y)).g; sample.z = texture(tex, uv.xy + vec2( px.x,-px.y)).g; sample.x = texture(tex, uv.xy + vec2(-px.x, px.y)).g; sample.y = texture(tex, uv.xy + vec2( px.x, px.y)).g; return sample; } // vec4 RvmB4F(sampler2D tex, vec2 uv){ vec2 px = vec2(1.0) / vec2(textureSize(tex, 0)); px *= 0.5; vec4 sample; sample.w = texture(tex, uv.xy + vec2(-px.x,-px.y)).b; sample.z = texture(tex, uv.xy + vec2( px.x,-px.y)).b; sample.x = texture(tex, uv.xy + vec2(-px.x, px.y)).b; sample.y = texture(tex, uv.xy + vec2( px.x, px.y)).b; return sample; } #define RVM_DARK 1 #define RVM_SCAN_DIV 3.0 #define RVM_SCAN_MAX (8.0/15.0) #define RVM_SCAN_MIN (RVM_SCAN_DIV*RVM_SCAN_MAX) #define RVM_SCAN_SIZ (RVM_SCAN_MAX-RVM_SCAN_MIN) vec2 RvmPolyF2(vec2 x){ x=clamp(-x*x+vec2(1.0,1.0), 0.0, 1.0); return x*x; } vec3 rvm_func( sampler2D tex, //-------------------------------------------------------------- // SV_POSITION, fragCoord.xy, etc vec2 ipos, //-------------------------------------------------------------- // inputSize / outputSize (in pixels) vec2 inputSizeDivOutputSize, //-------------------------------------------------------------- // 0.5 * inputSize (in pixels) vec2 halfInputSize, //-------------------------------------------------------------- // 1.0 / inputSize (in pixels) vec2 rcpInputSize, //-------------------------------------------------------------- // 2.0 / outputSize (in pixels) vec2 twoDivOutputSize, //-------------------------------------------------------------- // inputSize.y float inputHeight, //-------------------------------------------------------------- // Warp scanlines // 0.0 = no warp // 1.0/64.0 = light warping // 1.0/32.0 = more warping // Want x and y warping to be different (based on aspect) vec2 warp, //-------------------------------------------------------------- // Control horizontal blur // 0.50 := blurry // 0.75 := default // 1.00 := blocky float blur, // Derived constant {0.5*blur,-0.5*blur,-1.5*blur,-2.5*blur} vec4 blur4){ // Optional apply warp vec2 pos; pos=ipos*inputSizeDivOutputSize; pos -= (halfInputSize * 2.0) / (resolution.zw / resolution.xy); // Get to center for first gather 4 // W Z // X Y // W Z // X Y vec2 g=floor(pos+vec2(-0.5,-1.5))+vec2(1.0); vec2 gp=g*rcpInputSize; g.x-=float(0.5); // 2x4 sampled footprint // W Z |s // X Y |s // W Z :t // X Y :t vec4 colRS=RvmR4F(tex, gp); vec4 colGS=RvmG4F(tex, gp); vec4 colBS=RvmB4F(tex, gp); gp.y+=float(2.0*rcpInputSize.y); vec4 colRT=RvmR4F(tex, gp); vec4 colGT=RvmG4F(tex, gp); vec4 colBT=RvmB4F(tex, gp); // Vertical float offB=float(pos.y-g.y); vec2 offS=vec2(offB,offB)*vec2(blur)+blur4.xy; vec2 offT=vec2(offB,offB)*vec2(blur)+blur4.zw; vec2 horS=RvmPolyF2(offS); vec2 horT=RvmPolyF2(offT); // Get kernel totals and then rcp vec2 hor0=horS+horT; float horD=1.0 / (hor0.x+hor0.y); //horD*=float(vin); // Apply vertical filter vec2 colRL=colRS.wz*horS.xx+colRS.xy*horS.yy+ colRT.wz*horT.xx+colRT.xy*horT.yy; vec2 colGL=colGS.wz*horS.xx+colGS.xy*horS.yy+ colGT.wz*horT.xx+colGT.xy*horT.yy; vec2 colBL=colBS.wz*horS.xx+colBS.xy*horS.yy+ colBT.wz*horT.xx+colBT.xy*horT.yy; // Normalize by kernel total colRL*=vec2(horD); colGL*=vec2(horD); colBL*=vec2(horD); float offX=float(pos.x-g.x); vec2 scnL=vec2(float(1.0)-offX,offX); // Apply scan colRL*=scnL; colGL*=scnL; colBL*=scnL; // Merge contribution from both nearest lines vec3 col; col.r=colRL.x+colRL.y; col.g=colGL.x+colGL.y; col.b=colBL.x+colBL.y; // Slot mask float lim=float(1.0/((3.0/12.0)+(9.0/12.0)*RVM_DARK)); if(fract(ipos.x*float(1.0/6.0))>float(0.5)) ipos.y+=float(2.0); ipos.y=fract(ipos.y*float(1.0/4.0)); vec3 colD=col*col; colD*=RVM_DARK; vec3 amp= vec3(1.0) / vec3( vec3(lim*3.0/12.0)+vec3(lim*9.0/12.0)*col); ipos.x=fract(ipos.x*float(1.0/3.0)); col*=amp;colD*=amp; if(ipos.y>float(1.0/4.0)){ if( ipos.x