#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 fragColor; layout (binding = 0) uniform sampler2D samplerAlbedo; layout (binding = 1) uniform UBO { float curTime; } ubo; #define PI 3.14159265358 #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; } vec3 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.); vec3 video = vec3(texture(samplerAlbedo,look)); return video; } 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); vec3 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 += stripes(uv); video += noise(uv*2.)/2.; video *= vignette; video *= (12.+mod(uv.y*30.+iTime,1.))/13.; fragColor = vec4(video,1.0); } #endif #if 1 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( samplerAlbedo, 0 ) * 0.75; const vec2 scanLineOpacity = vec2(1,1); const float brightness = 1; const float vignetteOpacity = 1; const float vignetteRoundness = 1; const vec2 curvature = vec2(3.0, 3.0); const vec2 remappedUV = curveRemapUV(vec2(inUv.x, inUv.y), curvature); vec4 baseColor = texture(samplerAlbedo, 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){ fragColor = vec4(0.0, 0.0, 0.0, 1.0); } else { fragColor = baseColor; } } #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(samplerAlbedo,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( samplerAlbedo, 0 ); fragCoord = inUv * iResolution; vec2 pos = Warp(fragCoord.xy / iResolution.xy); hardScan = -12.0; maskDark = maskLight = 1.0; fragColor.rgb = Tri(pos) * Mask(fragCoord.xy); fragColor.rgb = ToSrgb(fragColor.rgb); fragColor.a = 1.0; } #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( samplerAlbedo, inUv ); fragColor = sampled - noise * mdf; } #endif