#version 300 es precision highp float; out vec4 outColor; uniform sampler2D uScene; uniform vec2 uInverseResolution; const float EDGE_THRESHOLD_MINIMUM = 0.0312; const float EDGE_THRESHOLD = 0.125; const float DIRECTION_REDUCE_MINIMUM = 1.0 / 128.0; const float DIRECTION_REDUCE_MULTIPLIER = 1.0 / 8.0; const float MAXIMUM_SPAN = 8.0; float luminance(vec3 color) { return dot(color, vec3(0.299, 0.587, 0.114)); } void main() { vec2 uv = gl_FragCoord.xy * uInverseResolution; vec3 center = texture(uScene, uv).rgb; vec3 northwest = texture(uScene, uv + vec2(-1.0, 1.0) * uInverseResolution).rgb; vec3 northeast = texture(uScene, uv + vec2(1.0, 1.0) * uInverseResolution).rgb; vec3 southwest = texture(uScene, uv + vec2(-1.0, -1.0) * uInverseResolution).rgb; vec3 southeast = texture(uScene, uv + vec2(1.0, -1.0) * uInverseResolution).rgb; float lumaCenter = luminance(center); float lumaNorthwest = luminance(northwest); float lumaNortheast = luminance(northeast); float lumaSouthwest = luminance(southwest); float lumaSoutheast = luminance(southeast); float lumaMinimum = min( lumaCenter, min(min(lumaNorthwest, lumaNortheast), min(lumaSouthwest, lumaSoutheast)) ); float lumaMaximum = max( lumaCenter, max(max(lumaNorthwest, lumaNortheast), max(lumaSouthwest, lumaSoutheast)) ); float lumaRange = lumaMaximum - lumaMinimum; if (lumaRange < max(EDGE_THRESHOLD_MINIMUM, lumaMaximum * EDGE_THRESHOLD)) { outColor = vec4(center, 1.0); return; } vec2 direction; direction.x = -( (lumaNorthwest + lumaNortheast) - (lumaSouthwest + lumaSoutheast) ); direction.y = ( (lumaNorthwest + lumaSouthwest) - (lumaNortheast + lumaSoutheast) ); float directionReduce = max( (lumaNorthwest + lumaNortheast + lumaSouthwest + lumaSoutheast) * (0.25 * DIRECTION_REDUCE_MULTIPLIER), DIRECTION_REDUCE_MINIMUM ); float reciprocalMinimum = 1.0 / ( min(abs(direction.x), abs(direction.y)) + directionReduce ); direction = clamp( direction * reciprocalMinimum, vec2(-MAXIMUM_SPAN), vec2(MAXIMUM_SPAN) ) * uInverseResolution; vec3 filteredNarrow = 0.5 * ( texture(uScene, uv + direction * (1.0 / 3.0 - 0.5)).rgb + texture(uScene, uv + direction * (2.0 / 3.0 - 0.5)).rgb ); vec3 filteredWide = filteredNarrow * 0.5 + 0.25 * ( texture(uScene, uv - direction * 0.5).rgb + texture(uScene, uv + direction * 0.5).rgb ); float wideLuminance = luminance(filteredWide); vec3 filtered = wideLuminance < lumaMinimum || wideLuminance > lumaMaximum ? filteredNarrow : filteredWide; outColor = vec4(filtered, 1.0); }