1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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;
}
|