]> git.sesse.net Git - nageru/blob - sobel.frag
90c6d8a93c895368b45cbb18480148cd5583559c
[nageru] / sobel.frag
1 #version 450 core
2
3 in vec2 tc;
4 out vec2 gradients;
5
6 uniform sampler2D tex;
7
8 void main()
9 {
10         // There are two common Sobel filters, horizontal and vertical
11         // (see e.g. Wikipedia, or the OpenCV documentation):
12         //
13         //  [1 0 -1]     [-1 -2 -1]
14         //  [2 0 -2]     [ 0  0  0]
15         //  [1 0 -1]     [ 1  2  1]
16         // Horizontal     Vertical
17         //
18         // Note that Wikipedia and OpenCV gives entirely opposite definitions
19         // with regards to sign! This appears to be an error in the OpenCV
20         // documentation, forgetting that for convolution, the filters must be
21         // flipped. We have to flip the vertical matrix again comparing to
22         // Wikipedia, though, since we have bottom-left origin (y = up)
23         // and they define y as pointing downwards.
24         //
25         // Computing both directions at once allows us to get away with eight
26         // texture samples instead of twelve.
27
28         float top_left     = textureOffset(tex, tc, ivec2(-1,  1)).x;  // Note the bottom-left coordinate system.
29         float left         = textureOffset(tex, tc, ivec2(-1,  0)).x;
30         float bottom_left  = textureOffset(tex, tc, ivec2(-1, -1)).x;
31
32         float top          = textureOffset(tex, tc, ivec2( 0,  1)).x;
33         float bottom       = textureOffset(tex, tc, ivec2( 0, -1)).x;
34
35         float top_right    = textureOffset(tex, tc, ivec2( 1,  1)).x;
36         float right        = textureOffset(tex, tc, ivec2( 1,  0)).x;
37         float bottom_right = textureOffset(tex, tc, ivec2( 1, -1)).x;
38
39         gradients.x = (top_right + 2.0f * right + bottom_right) - (top_left + 2.0f * left + bottom_left);
40         gradients.y = (top_left + 2.0 * top + top_right) - (bottom_left + 2.0f * bottom + bottom_right);
41
42         // Normalize so that we have a normalized unit of intensity levels per pixel.
43         gradients.x *= 0.125;
44         gradients.y *= 0.125;
45 }