aboutsummaryrefslogtreecommitdiff
path: root/res/shaders/postprocess.fs
diff options
context:
space:
mode:
Diffstat (limited to 'res/shaders/postprocess.fs')
-rw-r--r--res/shaders/postprocess.fs105
1 files changed, 105 insertions, 0 deletions
diff --git a/res/shaders/postprocess.fs b/res/shaders/postprocess.fs
new file mode 100644
index 0000000..af09c2c
--- /dev/null
+++ b/res/shaders/postprocess.fs
@@ -0,0 +1,105 @@
+#version 420 core
+
+in vec2 _f_texture;
+
+layout(binding = 2) uniform sampler2D main_colour;
+
+layout(std140, binding = 0) uniform _u_globals {
+ mat4 proj;
+ mat4 view;
+ vec4 frustum[6];
+ float znear;
+ float zfar;
+ float xfov;
+ float yfov;
+ uint time;
+};
+
+const float u_lumaThreshold = 0.125f;
+const float u_mulReduce = 1.0f / 8.0f;
+const float u_minReduce = 1.0f / 128.0f;
+const float u_maxSpan = 8.0f;
+
+out vec4 _o_colour;
+
+void main() {
+ const vec2 coords =
+ vec2((_f_texture.x + 1.0f) / 2.0f, (_f_texture.y + 1.0f) / 2.0f);
+
+ vec3 rgbM = texture(main_colour, coords).rgb;
+ vec2 size = textureSize(main_colour, 0);
+ vec2 u_texelStep = vec2(1.0f / size.x, 1.0f / size.y);
+
+ // Sampling neighbour texels. Offsets are adapted to OpenGL texture coordinates.
+ vec3 rgbNW = textureOffset(main_colour, coords, ivec2(-1, 1)).rgb;
+ vec3 rgbNE = textureOffset(main_colour, coords, ivec2(1, 1)).rgb;
+ vec3 rgbSW = textureOffset(main_colour, coords, ivec2(-1, -1)).rgb;
+ vec3 rgbSE = textureOffset(main_colour, coords, ivec2(1, -1)).rgb;
+
+ // see http://en.wikipedia.org/wiki/Grayscale
+ const vec3 toLuma = vec3(0.299, 0.587, 0.114);
+
+ // Convert from RGB to luma.
+ float lumaNW = dot(rgbNW, toLuma);
+ float lumaNE = dot(rgbNE, toLuma);
+ float lumaSW = dot(rgbSW, toLuma);
+ float lumaSE = dot(rgbSE, toLuma);
+ float lumaM = dot(rgbM, toLuma);
+
+ // Gather minimum and maximum luma.
+ float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
+ float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
+
+ // If contrast is lower than a maximum threshold ...
+ if (lumaMax - lumaMin <= lumaMax * u_lumaThreshold)
+ {
+ // ... do no AA and return.
+ _o_colour = vec4(rgbM, 1.0);
+
+ return;
+ }
+
+ // Sampling is done along the gradient.
+ vec2 samplingDirection;
+ samplingDirection.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
+ samplingDirection.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
+
+ // Sampling step distance depends on the luma: The brighter the sampled texels, the smaller the final sampling step direction.
+ // This results, that brighter areas are less blurred/more sharper than dark areas.
+ float samplingDirectionReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * 0.25 * u_mulReduce, u_minReduce);
+
+ // Factor for norming the sampling direction plus adding the brightness influence.
+ float minSamplingDirectionFactor = 1.0 / (min(abs(samplingDirection.x), abs(samplingDirection.y)) + samplingDirectionReduce);
+
+ // Calculate final sampling direction vector by reducing, clamping to a range and finally adapting to the texture size.
+ samplingDirection = clamp(samplingDirection * minSamplingDirectionFactor, vec2(-u_maxSpan), vec2(u_maxSpan)) * u_texelStep;
+
+ // Inner samples on the tab.
+ vec3 rgbSampleNeg = texture(main_colour, coords + samplingDirection * (1.0/3.0 - 0.5)).rgb;
+ vec3 rgbSamplePos = texture(main_colour, coords + samplingDirection * (2.0/3.0 - 0.5)).rgb;
+
+ vec3 rgbTwoTab = (rgbSamplePos + rgbSampleNeg) * 0.5;
+
+ // Outer samples on the tab.
+ vec3 rgbSampleNegOuter = texture(main_colour, coords + samplingDirection * (0.0/3.0 - 0.5)).rgb;
+ vec3 rgbSamplePosOuter = texture(main_colour, coords + samplingDirection * (3.0/3.0 - 0.5)).rgb;
+
+ vec3 rgbFourTab = (rgbSamplePosOuter + rgbSampleNegOuter) * 0.25 + rgbTwoTab * 0.5;
+
+ // Calculate luma for checking against the minimum and maximum value.
+ float lumaFourTab = dot(rgbFourTab, toLuma);
+
+ // Are outer samples of the tab beyond the edge ...
+ if (lumaFourTab < lumaMin || lumaFourTab > lumaMax)
+ {
+ // ... yes, so use only two samples.
+ _o_colour = vec4(rgbTwoTab, 1.0);
+ }
+ else
+ {
+ // ... no, so use four samples.
+ _o_colour = vec4(rgbFourTab, 1.0);
+ }
+
+ //_o_colour.r = 1.0f;
+}