Created
July 15, 2026 15:57
-
-
Save drewhamlett/d072e16dcf2fa62390780a189ee3380c to your computer and use it in GitHub Desktop.
glsl330
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #version 330 | |
| in vec2 fragTexCoord; | |
| in vec4 fragColor; | |
| uniform sampler2D texture0; | |
| uniform vec4 colDiffuse; | |
| out vec4 finalColor; | |
| // CRT effect controls (set from src/crt.c) | |
| uniform float curvature; | |
| uniform float chromaticAberrationPixels; | |
| uniform float chromaticAberrationCurve; | |
| uniform float contrast; | |
| uniform float brightness; | |
| uniform float scanlineStrength; | |
| uniform float scanlineSpacing; | |
| uniform float vignetteStrength; | |
| uniform vec2 aspectScale; | |
| uniform vec2 texelSize; | |
| uniform vec3 tiltShiftParams; // focus start, strength, blur radius in pixels | |
| uniform vec3 colorGradeParams; // purple tint, glow threshold, glow strength | |
| void main() | |
| { | |
| vec2 centered = fragTexCoord*2.0 - 1.0; | |
| vec2 aspectCentered = centered*aspectScale; | |
| float radius = dot(aspectCentered, aspectCentered); | |
| vec2 warped = centered*(1.0 + radius*curvature); | |
| vec2 uv = warped*0.5 + 0.5; | |
| if (max(abs(warped.x), abs(warped.y)) > 1.0) | |
| { | |
| finalColor = vec4(0.0); | |
| return; | |
| } | |
| vec2 halfTexel = texelSize*0.5; | |
| vec2 minimumUv = halfTexel; | |
| vec2 maximumUv = vec2(1.0) - halfTexel; | |
| float radialLength = sqrt(radius); | |
| vec2 radialDirection = aspectCentered/max(radialLength, 0.0001); | |
| float edgeAmount = pow(clamp(radius*0.5, 0.0, 1.0), chromaticAberrationCurve); | |
| vec2 aberrationOffset = radialDirection*chromaticAberrationPixels*edgeAmount*texelSize; | |
| vec2 centerUv = clamp(uv, minimumUv, maximumUv); | |
| vec3 centerColor = texture(texture0, centerUv).rgb; | |
| vec3 aberratedColor = vec3( | |
| texture(texture0, clamp(uv + aberrationOffset, minimumUv, maximumUv)).r, | |
| centerColor.g, | |
| texture(texture0, clamp(uv - aberrationOffset, minimumUv, maximumUv)).b | |
| ); | |
| vec2 blurOffset = vec2(0.0, texelSize.y*tiltShiftParams.z); | |
| vec3 softColor = centerColor*0.5; | |
| softColor += texture(texture0, clamp(uv + blurOffset, minimumUv, maximumUv)).rgb*0.25; | |
| softColor += texture(texture0, clamp(uv - blurOffset, minimumUv, maximumUv)).rgb*0.25; | |
| float defocus = smoothstep(tiltShiftParams.x, 1.0, abs(centered.y)); | |
| vec3 color = mix(aberratedColor, softColor, defocus*tiltShiftParams.y); | |
| vec3 glow = max(softColor - vec3(colorGradeParams.y), vec3(0.0)); | |
| color += glow*colorGradeParams.z; | |
| vec3 lumaWeights = vec3(0.2126, 0.7152, 0.0722); | |
| vec3 violetColor = color*vec3(1.18, 0.82, 1.28); | |
| float originalLuma = dot(color, lumaWeights); | |
| float violetLuma = max(dot(violetColor, lumaWeights), 0.0001); | |
| float shadowAmount = 1.0 - clamp(originalLuma*2.0, 0.0, 1.0); | |
| violetColor *= originalLuma/violetLuma; | |
| violetColor += vec3(0.035, 0.0, 0.06)*shadowAmount; | |
| color = mix(color, violetColor, colorGradeParams.x); | |
| // mod() keeps the sin() argument small so mediump gl_FragCoord (GLES) stays precise | |
| float phase = mod(gl_FragCoord.y, scanlineSpacing)*6.28318531/scanlineSpacing; | |
| float scanline = 1.0 - scanlineStrength*(0.5 - 0.5*sin(phase)); | |
| float vignetteEdge = smoothstep(0.25, 1.0, clamp(radius*0.5, 0.0, 1.0)); | |
| float vignette = 1.0 - vignetteStrength*vignetteEdge; | |
| color = clamp(((color - 0.5)*contrast + 0.5)*brightness, 0.0, 1.0); | |
| color *= scanline*vignette; | |
| finalColor = vec4(color, 1.0)*colDiffuse*fragColor; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment