engine/bin/data/shaders/display/renderTarget/postProcess.crt.frag.glsl

392 lines
11 KiB
GLSL

#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