#version 450 #pragma shader_stage(fragment) #extension GL_EXT_samplerless_texture_functions : require layout (location = 0) in vec2 inUv; layout (location = 1) flat in uint inPass; layout (location = 0) out vec4 outColor; layout (binding = 0) uniform sampler2D samplerColor; layout (binding = 1) uniform UBO { float curTime; float gamma; float exposure; uint padding; } ubo; #define TONE_MAP 1 #define GAMMA_CORRECT 1 #define TEXTURES 1 #include "../../common/macros.h" #include "../../common/structs.h" #include "../../common/functions.h" #define M_PI 3.1415926535897932384626433832795 const float u_imgx = 0; const float u_imgy = 0; const float u_imgw = 1; const float u_imgh = 1; const float u_img_gain = 2; const float u_img_bias = 0; const float u_beam_bias = 0.185; const float u_beam_gain = 0.25; const float u_corner = 0.05; const float u_zoom = 1.0; const float u_shape = 2; const float u_round = -0.02; const float u_grain = 0.4; const float u_vpitch = 936.1; const float u_hpitch = 1024.6; const float u_top = 1; const float u_bot = 1; void main() { const vec2 screenResolution = textureSize( samplerColor, 0 ); const float u_lines = screenResolution.y * 0.75; vec2 uv_orig = (inUv.xy * 2.0 - 1.0); vec2 uv_mod = uv_orig * pow(1.0-abs(uv_orig),vec2(u_round)) * (u_zoom + u_corner * pow( abs(uv_orig.yx), vec2(u_shape)) ); vec2 uv = uv_mod / 2.0 + 0.5; if ( abs(uv_mod).x > 1.0 || abs(uv_mod.y) > 1.0 ) { outColor = vec4(0.0, 0.0, 0.0, 1.0); return; } float spacing = 1.0/u_lines; uv+=spacing*0.5; float line_top = ( ceil(uv.y*u_lines)) / u_lines; float line_bot = line_top - spacing; vec2 scale = vec2(u_imgw, u_imgh); vec2 offset = vec2(u_imgx, u_imgy); vec2 uv_top = (vec2(uv.x, line_top)+offset) * scale - (scale-1.0)*0.5 ; vec2 uv_bot = (vec2(uv.x, line_bot)+offset) * scale - (scale-1.0)*0.5 ; uv_top -= spacing * 0.5; uv_bot -= spacing * 0.5; vec4 sampled_top = texture(samplerColor, uv_top); vec4 sampled_bot = texture(samplerColor, uv_bot); vec3 color_top = sampled_top.xyz * u_img_gain + u_img_bias; vec3 color_bot = sampled_bot.xyz * u_img_gain + u_img_bias; float dist_top = pow(abs(uv.y - line_top), 1.0); float dist_bot = pow(abs(uv.y - line_bot), 1.0); vec3 beam_top = 1.0 - (dist_top / (spacing * (color_top * u_beam_gain + u_beam_bias))); vec3 beam_bot = 1.0 - (dist_bot / (spacing * (color_bot * u_beam_gain + u_beam_bias))); beam_top = clamp(beam_top, 0.0, 1.0) ; beam_bot = clamp(beam_bot, 0.0, 1.0) ; vec3 color = (color_top*beam_top)*u_top + (color_bot*beam_bot)*u_bot; vec2 dot; dot.y = floor(uv.y * u_vpitch) ; dot.x = uv.x; if (mod(dot.y, 2.0) > 0.5) dot.x += (4.5/3.0) / u_hpitch; dot.x = (floor(dot.x*u_hpitch)) ; int fil = int(mod(dot.x, 3.0)); vec3 out_color = color * (1.0-u_grain); vec3 passthru = vec3( float(fil == 0), float(fil == 1), float(fil == 2) ) * (u_grain); out_color += color * passthru; outColor = vec4(out_color, (sampled_top.a + sampled_bot.a) * 0.5 ); #if TONE_MAP toneMap(outColor, ubo.exposure); #endif #if GAMMA_CORRECT gammaCorrect(outColor, ubo.gamma); #endif } #if 0 float iTime = 0; float noise(vec2 p) { float s = (fract(sin(dot(p * sin( iTime * 0.5 ), vec2(12.9898,78.233)*2.0)) * 43758.5453)); // texture(iChannel1,vec2(1.,2.*cos(iTime))*iTime*8. + p*1.).x; s *= s; return s; } float onOff(float a, float b, float c) { return step(c, sin(iTime + a*cos(iTime*b))); } float ramp(float y, float start, float end) { float inside = step(start,y) - step(end,y); float fact = (y-start)/(end-start)*inside; return (1.-fact) * inside; } float stripes(vec2 uv) { float noi = noise(uv*vec2(0.5,1.) + vec2(1.,3.)); return ramp(mod(uv.y*4. + iTime/2.+sin(iTime + sin(iTime*0.63)),1.),0.5,0.6)*noi; } vec4 getVideo(vec2 uv) { vec2 look = uv; float window = 1./(1.+20.*(look.y-mod(iTime/4.,1.))*(look.y-mod(iTime/4.,1.))); look.x = look.x + sin(look.y*10. + iTime)/50.*onOff(4.,4.,.3)*(1.+cos(iTime*80.))*window; float vShift = 0.4*onOff(2.,3.,.9)*(sin(iTime)*sin(iTime*20.) + (0.5 + 0.1*sin(iTime*200.)*cos(iTime))); look.y = mod(look.y + vShift, 1.); return texture(samplerColor,look); } vec2 screenDistort(vec2 uv) { uv -= vec2(.5,.5); uv = uv*1.2*(1./1.2+2.*uv.x*uv.x*uv.y*uv.y); uv += vec2(.5,.5); return uv; } void main() { vec2 uv = inUv.xy; // fragCoord.xy / iResolution.xy; iTime = ubo.curTime; uv = screenDistort(uv); vec4 video = getVideo(uv); float vigAmt = 3.+.3*sin(iTime + 5.*cos(iTime*5.)); float vignette = (1.-vigAmt*(uv.y-.5)*(uv.y-.5))*(1.-vigAmt*(uv.x-.5)*(uv.x-.5)); video.rgb += stripes(uv); video.rgb += noise(uv*2.)/4.; video.rgb *= vignette; video.rgb *= (12.+mod(uv.y*30.+iTime,1.))/13.; outColor = video; #if TONE_MAP toneMap(outColor, ubo.exposure); #endif #if GAMMA_CORRECT gammaCorrect(outColor, ubo.gamma); #endif } #endif #if 0 vec2 curveRemapUV(vec2 uv, vec2 curvature) { uv = uv * 2.0 - 1.0; vec2 offset = abs(uv.yx) / vec2(curvature.x, curvature.y); uv = uv + uv * offset * offset; uv = uv * 0.5 + 0.5; return uv; } vec4 scanLineIntensity(float uv, float resolution, float opacity) { float intensity = sin(uv * resolution * PI * 2.0); intensity = ((0.5 * intensity) + 0.5) * 0.9 + 0.1; return vec4(vec3(pow(intensity, opacity)), 1.0); } vec4 vignetteIntensity(vec2 uv, vec2 resolution, float opacity, float roundness) { float intensity = uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y); return vec4(vec3(clamp(pow((resolution.x / roundness) * intensity, opacity), 0.0, 1.0)), 1.0); } void main(void) { const vec2 screenResolution = textureSize( samplerColor, 0 ); const vec2 scanLineOpacity = vec2(0.5); const float brightness = 2; const float vignetteOpacity = 0.5; const float vignetteRoundness = 0.5; const vec2 curvature = vec2(8); const vec2 remappedUV = curveRemapUV(vec2(inUv.x, inUv.y), curvature); vec4 baseColor = texture(samplerColor, remappedUV); baseColor *= vignetteIntensity(remappedUV, screenResolution, vignetteOpacity, vignetteRoundness); baseColor *= scanLineIntensity(remappedUV.x, screenResolution.y, scanLineOpacity.x); baseColor *= scanLineIntensity(remappedUV.y, screenResolution.x, scanLineOpacity.y); baseColor *= vec4(vec3(brightness), 1.0); if (remappedUV.x < 0.0 || remappedUV.y < 0.0 || remappedUV.x > 1.0 || remappedUV.y > 1.0){ outColor = vec4(0.0, 0.0, 0.0, 1.0); } else { outColor = baseColor; } #if TONE_MAP toneMap(outColor, ubo.exposure); #endif #if GAMMA_CORRECT gammaCorrect(outColor, ubo.gamma); #endif } #endif #if 0 vec2 fragCoord = vec2(0,0); vec2 iResolution = vec2(640,480); // Emulated input resolution. #if 0 // Fix resolution to set amount. #define res (vec2(320.0/1.0,160.0/1.0)) #else // Optimize for resize. #define res (iResolution.xy/6.0) #endif // Hardness of scanline. // -8.0 = soft // -16.0 = medium float hardScan=-8.0; // Hardness of pixels in scanline. // -2.0 = soft // -4.0 = hard float hardPix=-3.0; // Display warp. // 0.0 = none // 1.0/8.0 = extreme vec2 warp=vec2(1.0/32.0,1.0/24.0); // Amount of shadow mask. float maskDark=0.5; float maskLight=1.5; //------------------------------------------------------------------------ // sRGB to Linear. // Assuing using sRGB typed textures this should not be needed. float ToLinear1(float c){return(c<=0.04045)?c/12.92:pow((c+0.055)/1.055,2.4);} vec3 ToLinear(vec3 c){return vec3(ToLinear1(c.r),ToLinear1(c.g),ToLinear1(c.b));} // Linear to sRGB. // Assuing using sRGB typed textures this should not be needed. float ToSrgb1(float c){return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);} vec3 ToSrgb(vec3 c){return vec3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));} // Nearest emulated sample given floating point position and texel offset. // Also zero's off screen. vec3 Fetch(vec2 pos,vec2 off){ pos=floor(pos*res+off)/res; if(max(abs(pos.x-0.5),abs(pos.y-0.5))>0.5)return vec3(0.0,0.0,0.0); return ToLinear(texture(samplerColor,pos.xy,-16.0).rgb);} // Distance in emulated pixels to nearest texel. vec2 Dist(vec2 pos){pos=pos*res;return -((pos-floor(pos))-vec2(0.5));} // 1D Gaussian. float Gaus(float pos,float scale){return exp2(scale*pos*pos);} // 3-tap Gaussian filter along horz line. vec3 Horz3(vec2 pos,float off){ vec3 b=Fetch(pos,vec2(-1.0,off)); vec3 c=Fetch(pos,vec2( 0.0,off)); vec3 d=Fetch(pos,vec2( 1.0,off)); float dst=Dist(pos).x; // Convert distance to weight. float scale=hardPix; float wb=Gaus(dst-1.0,scale); float wc=Gaus(dst+0.0,scale); float wd=Gaus(dst+1.0,scale); // Return filtered sample. return (b*wb+c*wc+d*wd)/(wb+wc+wd);} // 5-tap Gaussian filter along horz line. vec3 Horz5(vec2 pos,float off){ vec3 a=Fetch(pos,vec2(-2.0,off)); vec3 b=Fetch(pos,vec2(-1.0,off)); vec3 c=Fetch(pos,vec2( 0.0,off)); vec3 d=Fetch(pos,vec2( 1.0,off)); vec3 e=Fetch(pos,vec2( 2.0,off)); float dst=Dist(pos).x; // Convert distance to weight. float scale=hardPix; float wa=Gaus(dst-2.0,scale); float wb=Gaus(dst-1.0,scale); float wc=Gaus(dst+0.0,scale); float wd=Gaus(dst+1.0,scale); float we=Gaus(dst+2.0,scale); // Return filtered sample. return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);} // Return scanline weight. float Scan(vec2 pos,float off){ float dst=Dist(pos).y; return Gaus(dst+off,hardScan);} // Allow nearest three lines to effect pixel. vec3 Tri(vec2 pos){ vec3 a=Horz3(pos,-1.0); vec3 b=Horz5(pos, 0.0); vec3 c=Horz3(pos, 1.0); float wa=Scan(pos,-1.0); float wb=Scan(pos, 0.0); float wc=Scan(pos, 1.0); return a*wa+b*wb+c*wc;} // Distortion of scanlines, and end of screen alpha. vec2 Warp(vec2 pos){ pos=pos*2.0-1.0; pos*=vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y); return pos*0.5+0.5;} // Shadow mask. vec3 Mask(vec2 pos){ pos.x+=pos.y*3.0; vec3 mask=vec3(maskDark,maskDark,maskDark); pos.x=fract(pos.x/6.0); if(pos.x<0.333)mask.r=maskLight; else if(pos.x<0.666)mask.g=maskLight; else mask.b=maskLight; return mask;} void main() { iResolution = textureSize( samplerColor, 0 ); fragCoord = inUv * iResolution; vec2 pos = Warp(fragCoord.xy / iResolution.xy); hardScan = -12.0; maskDark = maskLight = 1.0; outColor.rgb = Tri(pos) * Mask(fragCoord.xy); outColor.rgb = ToSrgb(outColor.rgb); outColor.a = 1.0; #if TONE_MAP toneMap(outColor, ubo.exposure); #endif #if GAMMA_CORRECT gammaCorrect(outColor, ubo.gamma); #endif } #endif #if 0 void main() { const vec2 uv = 0.025 * sin( ubo.curTime ) * inUv.xy; const float mdf = 0.5; const float noise = (fract(sin(dot(uv, vec2(12.9898,78.233)*2.0)) * 43758.5453)); const vec4 sampled = texture( samplerColor, inUv ); outColor = sampled - noise * mdf; toneMap(outColor, ubo.exposure); gammaCorrect(outColor, ubo.gamma); } #endif