]> git.sesse.net Git - nageru/blobdiff - sobel.frag
Fix a problem with visualizing flow that goes exactly left.
[nageru] / sobel.frag
index 4fd12a37d40025241bd7bf8f5dab80eb63146fa2..518b6f8abcdadb4491b8e1187f6cea3e696fa477 100644 (file)
@@ -11,33 +11,36 @@ void main()
        // There are two common Sobel filters, horizontal and vertical
        // (see e.g. Wikipedia, or the OpenCV documentation):
        //
-       //  [-1 0 1]     [ 1  2  1]
-       //  [-2 0 2]     [ 0  0  0]
-       //  [-1 0 1]     [-1 -2 -1]
+       //  [1 0 -1]     [-1 -2 -1]
+       //  [2 0 -2]     [ 0  0  0]
+       //  [1 0 -1]     [ 1  2  1]
        // Horizontal     Vertical
        //
-       // Computing both at once allows us to get away with eight
+       // Note that Wikipedia and OpenCV gives entirely opposite definitions
+       // with regards to sign! This appears to be an error in the OpenCV
+       // documentation, forgetting that for convolution, the filters must be
+       // flipped. We have to flip the vertical matrix again comparing to
+       // Wikipedia, though, since we have bottom-left origin (y = up)
+       // and they define y as pointing downwards.
+       //
+       // Computing both directions at once allows us to get away with eight
        // texture samples instead of twelve.
 
-       float x_left   = tc.x - inv_image_size.x;
-       float x_mid    = tc.x; 
-       float x_right  = tc.x + inv_image_size.x;
-
-       float y_top    = tc.y + inv_image_size.y;  // Note the bottom-left coordinate system.
-       float y_mid    = tc.y;
-       float y_bottom = tc.y - inv_image_size.y;
-       float top_left     = texture(tex, vec2(x_left,  y_top)).x;
-       float left         = texture(tex, vec2(x_left,  y_mid)).x;
-       float bottom_left  = texture(tex, vec2(x_left,  y_bottom)).x;
+       float top_left     = textureOffset(tex, tc, ivec2(-1,  1)).x;  // Note the bottom-left coordinate system.
+       float left         = textureOffset(tex, tc, ivec2(-1,  0)).x;
+       float bottom_left  = textureOffset(tex, tc, ivec2(-1, -1)).x;
 
-       float top          = texture(tex, vec2(x_mid,   y_top)).x;
-       float bottom       = texture(tex, vec2(x_mid,   y_bottom)).x;
+       float top          = textureOffset(tex, tc, ivec2( 0,  1)).x;
+       float bottom       = textureOffset(tex, tc, ivec2( 0, -1)).x;
 
-       float top_right    = texture(tex, vec2(x_right, y_top)).x;
-       float right        = texture(tex, vec2(x_right, y_mid)).x;
-       float bottom_right = texture(tex, vec2(x_right, y_bottom)).x;
+       float top_right    = textureOffset(tex, tc, ivec2( 1,  1)).x;
+       float right        = textureOffset(tex, tc, ivec2( 1,  0)).x;
+       float bottom_right = textureOffset(tex, tc, ivec2( 1, -1)).x;
 
        gradients.x = (top_right + 2.0f * right + bottom_right) - (top_left + 2.0f * left + bottom_left);
        gradients.y = (top_left + 2.0 * top + top_right) - (bottom_left + 2.0f * bottom + bottom_right);
+
+       // Normalize so that we have a normalized unit of intensity levels per pixel.
+       gradients.x *= 0.125;
+       gradients.y *= 0.125;
 }