]> git.sesse.net Git - nageru/blob - futatabi/sobel.frag
Move VADisplayWithCleanup into its own header file, in shared/.
[nageru] / futatabi / sobel.frag
1 #version 450 core
2
3 in vec3 tc;
4 out uint packed_gradients;
5
6 uniform sampler2DArray tex;
7
8 uint pack_gradients(float x, float y, float v)
9 {
10         x = clamp(x, -0.5f, 0.5f);
11         y = clamp(y, -0.5f, 0.5f);
12
13         uint vi = uint(round(v * 255.0f));
14         uint xi = uint(round((x + 0.5f) * 4095.0f));
15         uint yi = uint(round((y + 0.5f) * 4095.0f));
16         return vi | (xi << 8) | (yi << 20);
17 }
18
19 void main()
20 {
21         // There are two common Sobel filters, horizontal and vertical
22         // (see e.g. Wikipedia, or the OpenCV documentation):
23         //
24         //  [1 0 -1]     [-1 -2 -1]
25         //  [2 0 -2]     [ 0  0  0]
26         //  [1 0 -1]     [ 1  2  1]
27         // Horizontal     Vertical
28         //
29         // Note that Wikipedia and OpenCV gives entirely opposite definitions
30         // with regards to sign! This appears to be an error in the OpenCV
31         // documentation, forgetting that for convolution, the filters must be
32         // flipped. We have to flip the vertical matrix again comparing to
33         // Wikipedia, though, since we have bottom-left origin (y = up)
34         // and they define y as pointing downwards.
35         //
36         // Computing both directions at once allows us to get away with eight
37         // texture samples instead of twelve.
38
39         float top_left     = textureOffset(tex, tc, ivec2(-1,  1)).x;  // Note the bottom-left coordinate system.
40         float left         = textureOffset(tex, tc, ivec2(-1,  0)).x;
41         float bottom_left  = textureOffset(tex, tc, ivec2(-1, -1)).x;
42
43         float top          = textureOffset(tex, tc, ivec2( 0,  1)).x;
44         float bottom       = textureOffset(tex, tc, ivec2( 0, -1)).x;
45
46         float top_right    = textureOffset(tex, tc, ivec2( 1,  1)).x;
47         float right        = textureOffset(tex, tc, ivec2( 1,  0)).x;
48         float bottom_right = textureOffset(tex, tc, ivec2( 1, -1)).x;
49
50         vec2 gradients;
51         gradients.x = (top_right + 2.0f * right + bottom_right) - (top_left + 2.0f * left + bottom_left);
52         gradients.y = (top_left + 2.0 * top + top_right) - (bottom_left + 2.0f * bottom + bottom_right);
53
54         // Normalize so that we have a normalized unit of intensity levels per pixel.
55         gradients.x *= 0.125;
56         gradients.y *= 0.125;
57
58         // Also store the actual pixel value, so that we get it “for free”
59         // when we sample the gradients in motion_search.frag later.
60         float center = texture(tex, tc).x;
61
62         // Pack everything into a single 32-bit value, using simple fixed-point.
63         packed_gradients = pack_gradients(gradients.x, gradients.y, center);
64 }