#version 450 core
-in vec2 tc;
-out vec2 gradients;
+in vec3 tc;
+out uint packed_gradients;
-uniform sampler2D tex;
-uniform vec2 inv_image_size;
+uniform sampler2DArray tex;
+
+uint pack_gradients(float x, float y, float v)
+{
+ x = clamp(x, -0.5f, 0.5f);
+ y = clamp(y, -0.5f, 0.5f);
+
+ uint vi = uint(round(v * 255.0f));
+ uint xi = uint(round((x + 0.5f) * 4095.0f));
+ uint yi = uint(round((y + 0.5f) * 4095.0f));
+ return vi | (xi << 8) | (yi << 20);
+}
void main()
{
// 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 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 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 = textureOffset(tex, tc, ivec2( 0, 1)).x;
+ float bottom = textureOffset(tex, tc, ivec2( 0, -1)).x;
- float top = texture(tex, vec2(x_mid, y_top)).x;
- float bottom = texture(tex, vec2(x_mid, y_bottom)).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;
+ vec2 gradients;
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;
+
+ // Also store the actual pixel value, so that we get it “for free”
+ // when we sample the gradients in motion_search.frag later.
+ float center = texture(tex, tc).x;
+
+ // Pack everything into a single 32-bit value, using simple fixed-point.
+ packed_gradients = pack_gradients(gradients.x, gradients.y, center);
}