From 1cc08c51eb4b0f95c30c0a98ad1fc5ad3459b2df Mon Sep 17 00:00:00 2001 From: Nicolas James Date: Wed, 12 Feb 2025 18:05:18 +1100 Subject: initial commit --- res/shaders/postprocess.fs | 105 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 res/shaders/postprocess.fs (limited to 'res/shaders/postprocess.fs') 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; +} -- cgit v1.2.3