|
| 1 | +#version 150 |
| 2 | + |
| 3 | +//precision mediump float; |
| 4 | + |
| 5 | +uniform vec2 resolution; |
| 6 | +uniform sampler2D tex; |
| 7 | +uniform int enabled; |
| 8 | + |
| 9 | +in vec2 v_tex_coords; |
| 10 | + |
| 11 | +out vec4 color; |
| 12 | + |
| 13 | +#define FXAA_REDUCE_MIN (1.0/ 128.0) |
| 14 | +#define FXAA_REDUCE_MUL (1.0 / 8.0) |
| 15 | +#define FXAA_SPAN_MAX 8.0 |
| 16 | + |
| 17 | +vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, |
| 18 | + vec2 v_rgbNW, vec2 v_rgbNE, |
| 19 | + vec2 v_rgbSW, vec2 v_rgbSE, |
| 20 | + vec2 v_rgbM) { |
| 21 | + vec4 color; |
| 22 | + |
| 23 | + // Sample adjascent pixels |
| 24 | + vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); |
| 25 | + vec3 rgbNW = texture(tex, v_rgbNW).xyz; |
| 26 | + vec3 rgbNE = texture(tex, v_rgbNE).xyz; |
| 27 | + vec3 rgbSW = texture(tex, v_rgbSW).xyz; |
| 28 | + vec3 rgbSE = texture(tex, v_rgbSE).xyz; |
| 29 | + vec4 texColor = texture(tex, v_rgbM); |
| 30 | + vec3 rgbM = texColor.xyz; |
| 31 | + |
| 32 | + // Calculate luminance |
| 33 | + vec3 luma = vec3(0.299, 0.587, 0.114); |
| 34 | + vec4 luma4 = vec4(0.299, 0.587, 0.114, 0.0); |
| 35 | + |
| 36 | + float lumaNW = dot(rgbNW, luma); |
| 37 | + float lumaNE = dot(rgbNE, luma); |
| 38 | + float lumaSW = dot(rgbSW, luma); |
| 39 | + float lumaSE = dot(rgbSE, luma); |
| 40 | + float lumaM = dot(rgbM, luma); |
| 41 | + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); |
| 42 | + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); |
| 43 | + |
| 44 | + // Determining blend direction |
| 45 | + vec2 dir; |
| 46 | + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); |
| 47 | + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); |
| 48 | + |
| 49 | + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * |
| 50 | + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); |
| 51 | + |
| 52 | + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); |
| 53 | + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), |
| 54 | + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), |
| 55 | + dir * rcpDirMin)) * inverseVP; |
| 56 | + |
| 57 | + // Blending |
| 58 | + // A lot of stuff here is my attempt to incorporate the alpha channel into the blending. I don't think I did it right. ¯\_(ツ)_/¯ |
| 59 | + // A bit of the background color still bleeds through around the edges of the image. It's hardly noticable, though. |
| 60 | + vec2 coordAA = fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5); |
| 61 | + vec2 coordAB = fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5); |
| 62 | + float alphaAA = texture(tex, coordAA).a; |
| 63 | + float alphaAB = texture(tex, coordAB).a; |
| 64 | + float alphaATotal = alphaAA + alphaAB; |
| 65 | + float weightAA = alphaAA / alphaATotal; |
| 66 | + float weightAB = alphaAB / alphaATotal; |
| 67 | + vec4 rgbA = vec4( // Multiply by 2 |
| 68 | + texture(tex, coordAA).rgb*weightAA + texture(tex, coordAB).rgb*weightAB, |
| 69 | + 0.5 * (alphaAA + alphaAB) |
| 70 | + ); |
| 71 | + |
| 72 | + vec2 coordBC = fragCoord * inverseVP + dir * -0.5; |
| 73 | + vec2 coordBD = fragCoord * inverseVP + dir * 0.5; |
| 74 | + float alphaBC = texture(tex, coordBC).a; |
| 75 | + float alphaBD = texture(tex, coordBD).a; |
| 76 | + float alphaBTotal = alphaAA + alphaAB + alphaBC + alphaBD; |
| 77 | + float weightBA = alphaAA / alphaBTotal; |
| 78 | + float weightBB = alphaAB / alphaBTotal; |
| 79 | + float weightBC = alphaBC / alphaBTotal; |
| 80 | + float weightBD = alphaBD / alphaBTotal; |
| 81 | + vec4 rgbB = vec4( |
| 82 | + texture(tex, coordAA).rgb*weightBA + texture(tex, coordAB).rgb*weightBB + texture(tex, coordBC).rgb*weightBC + texture(tex, coordBD).rgb*weightBD, |
| 83 | + 0.25 * (alphaAA + alphaAB + alphaBC + alphaBD) |
| 84 | + ); |
| 85 | + |
| 86 | + float lumaB = dot(rgbB, luma4); |
| 87 | + if ((lumaB < lumaMin) || (lumaB > lumaMax)) |
| 88 | + color = rgbA; |
| 89 | + else |
| 90 | + color = rgbB; |
| 91 | + return color; |
| 92 | +} |
| 93 | + |
| 94 | +void main() { |
| 95 | + vec2 fragCoord = v_tex_coords * resolution; |
| 96 | + if (enabled != 0) { |
| 97 | + vec2 inverseVP = 1.0 / resolution.xy; |
| 98 | + vec2 v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; |
| 99 | + vec2 v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; |
| 100 | + vec2 v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; |
| 101 | + vec2 v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; |
| 102 | + vec2 v_rgbM = vec2(fragCoord * inverseVP); |
| 103 | + color = fxaa(tex, fragCoord, resolution, v_rgbNW, v_rgbNE, v_rgbSW, |
| 104 | + v_rgbSE, v_rgbM); |
| 105 | + } else { |
| 106 | + color = texture(tex, v_tex_coords); |
| 107 | + } |
| 108 | +} |
0 commit comments