mirror of
https://github.com/Swordfish90/cool-retro-term.git
synced 2026-02-08 00:32:27 +00:00
182 lines
5.7 KiB
GLSL
182 lines
5.7 KiB
GLSL
#version 440
|
|
|
|
#ifndef CRT_RASTER_MODE
|
|
#define CRT_RASTER_MODE 0
|
|
#endif
|
|
#ifndef CRT_BURN_IN
|
|
#define CRT_BURN_IN 1
|
|
#endif
|
|
#ifndef CRT_DISPLAY_FRAME
|
|
#define CRT_DISPLAY_FRAME 1
|
|
#endif
|
|
#ifndef CRT_CHROMA
|
|
#define CRT_CHROMA 1
|
|
#endif
|
|
|
|
layout(location = 0) in vec2 qt_TexCoord0;
|
|
layout(location = 1) in float vBrightness;
|
|
layout(location = 2) in float vDistortionScale;
|
|
layout(location = 3) in float vDistortionFreq;
|
|
|
|
layout(location = 0) out vec4 fragColor;
|
|
|
|
layout(std140, binding = 0) uniform ubuf {
|
|
mat4 qt_Matrix;
|
|
float qt_Opacity;
|
|
float time;
|
|
vec4 fontColor;
|
|
vec4 backgroundColor;
|
|
vec2 virtualResolution;
|
|
float rasterizationIntensity;
|
|
float burnInLastUpdate;
|
|
float burnInTime;
|
|
float burnIn;
|
|
float staticNoise;
|
|
float screenCurvature;
|
|
float glowingLine;
|
|
float chromaColor;
|
|
vec2 jitterDisplacement;
|
|
float ambientLight;
|
|
float jitter;
|
|
float horizontalSync;
|
|
float horizontalSyncStrength;
|
|
float flickering;
|
|
float displayTerminalFrame;
|
|
vec2 scaleNoiseSize;
|
|
float frameShininess;
|
|
float frameSize;
|
|
float bloom;
|
|
};
|
|
|
|
layout(binding = 0) uniform sampler2D noiseSource;
|
|
layout(binding = 1) uniform sampler2D screenBuffer;
|
|
layout(binding = 2) uniform sampler2D burnInSource;
|
|
layout(binding = 3) uniform sampler2D frameSource;
|
|
|
|
float min2(vec2 v) { return min(v.x, v.y); }
|
|
float prod2(vec2 v) { return v.x * v.y; }
|
|
float sum2(vec2 v) { return v.x + v.y; }
|
|
float rgb2grey(vec3 v) { return dot(v, vec3(0.21, 0.72, 0.04)); }
|
|
|
|
vec2 distortCoordinates(vec2 coords){
|
|
vec2 paddedCoords = coords * (vec2(1.0) + frameSize * 2.0) - frameSize;
|
|
vec2 cc = (paddedCoords - vec2(0.5));
|
|
float dist = dot(cc, cc) * screenCurvature;
|
|
return (paddedCoords + cc * (1.0 + dist) * dist);
|
|
}
|
|
|
|
vec3 applyRasterization(vec2 screenCoords, vec3 texel, vec2 virtualRes, float intensity) {
|
|
#if CRT_RASTER_MODE == 0
|
|
return texel;
|
|
#else
|
|
if (intensity <= 0.0) {
|
|
return texel;
|
|
}
|
|
|
|
const float INTENSITY = 0.30;
|
|
const float BRIGHTBOOST = 0.30;
|
|
|
|
#if CRT_RASTER_MODE == 1
|
|
vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel;
|
|
vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel;
|
|
|
|
vec2 coords = fract(screenCoords * virtualRes) * 2.0 - vec2(1.0);
|
|
float mask = 1.0 - abs(coords.y);
|
|
|
|
vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask);
|
|
return mix(texel, rasterizationColor, intensity);
|
|
#elif CRT_RASTER_MODE == 2
|
|
vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel;
|
|
vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel;
|
|
|
|
vec2 coords = fract(screenCoords * virtualRes) * 2.0 - vec2(1.0);
|
|
coords = coords * coords;
|
|
float mask = 1.0 - coords.x - coords.y;
|
|
|
|
vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask);
|
|
return mix(texel, rasterizationColor, intensity);
|
|
#elif CRT_RASTER_MODE == 3
|
|
const float SUBPIXELS = 3.0;
|
|
vec3 offsets = vec3(3.141592654) * vec3(0.5, 0.5 - 2.0 / 3.0, 0.5 - 4.0 / 3.0);
|
|
|
|
vec2 omega = vec2(3.141592654) * vec2(2.0) * virtualRes;
|
|
vec2 angle = screenCoords * omega;
|
|
vec3 xfactors = (SUBPIXELS + sin(angle.x + offsets)) / (SUBPIXELS + 1.0);
|
|
|
|
vec3 result = texel * xfactors;
|
|
vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * result)) * result;
|
|
vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * result)) * result;
|
|
|
|
vec2 coords = fract(screenCoords * virtualRes) * 2.0 - vec2(1.0);
|
|
float mask = 1.0 - abs(coords.y);
|
|
|
|
vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask);
|
|
return mix(texel, rasterizationColor, intensity);
|
|
#else
|
|
return texel;
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
float randomPass(vec2 coords){
|
|
return fract(smoothstep(-120.0, 0.0, coords.y - (virtualResolution.y + 120.0) * fract(time * 0.15)));
|
|
}
|
|
|
|
vec3 convertWithChroma(vec3 inColor) {
|
|
#if CRT_CHROMA == 1
|
|
float grey = rgb2grey(inColor);
|
|
float denom = max(grey, 0.0001);
|
|
vec3 foregroundColor = mix(fontColor.rgb, inColor * fontColor.rgb / denom, chromaColor);
|
|
return mix(backgroundColor.rgb, foregroundColor, grey);
|
|
#else
|
|
return mix(backgroundColor.rgb, fontColor.rgb, rgb2grey(inColor));
|
|
#endif
|
|
}
|
|
|
|
void main() {
|
|
vec2 cc = vec2(0.5) - qt_TexCoord0;
|
|
float distance = length(cc);
|
|
|
|
vec2 staticCoords = distortCoordinates(qt_TexCoord0);
|
|
vec2 coords = qt_TexCoord0;
|
|
|
|
float dst = sin((coords.y + time) * vDistortionFreq);
|
|
coords.x += dst * vDistortionScale;
|
|
|
|
vec4 noiseTexel = texture(noiseSource, scaleNoiseSize * coords + vec2(fract(time / 0.051), fract(time / 0.237)));
|
|
|
|
vec2 txt_coords = coords + (noiseTexel.ba - vec2(0.5)) * jitterDisplacement * jitter;
|
|
|
|
float color = 0.0001;
|
|
color += noiseTexel.a * staticNoise * (1.0 - distance * 1.3);
|
|
color += randomPass(coords * virtualResolution) * glowingLine;
|
|
|
|
vec3 txt_color = texture(screenBuffer, txt_coords).rgb;
|
|
float bloomScale = 1.0 + max(bloom, 0.0);
|
|
txt_color *= bloomScale;
|
|
|
|
#if CRT_BURN_IN == 1
|
|
vec4 txt_blur = texture(burnInSource, staticCoords);
|
|
float blurDecay = clamp((time - burnInLastUpdate) * burnInTime, 0.0, 1.0);
|
|
vec3 burnInColor = 0.65 * (txt_blur.rgb - vec3(blurDecay));
|
|
txt_color = max(txt_color, burnInColor);
|
|
#endif
|
|
|
|
txt_color += vec3(color);
|
|
txt_color = applyRasterization(staticCoords, txt_color, virtualResolution, rasterizationIntensity);
|
|
|
|
vec3 finalColor = convertWithChroma(txt_color);
|
|
float brightness = mix(1.0, vBrightness, step(0.0, flickering));
|
|
finalColor *= brightness;
|
|
|
|
finalColor += vec3(ambientLight) * (1.0 - distance) * (1.0 - distance);
|
|
|
|
#if CRT_DISPLAY_FRAME == 1
|
|
vec4 frameColor = texture(frameSource, qt_TexCoord0);
|
|
vec3 reflection = max(finalColor - backgroundColor.rgb, vec3(0.0)) * frameShininess;
|
|
finalColor = mix(finalColor, frameColor.rgb + reflection, frameColor.a);
|
|
#endif
|
|
|
|
fragColor = vec4(finalColor, qt_Opacity);
|
|
}
|