uniform vec2 patch_size; // In 0..1 coordinates.
uniform vec2 patch_spacing; // In 0..1 coordinates.
uniform sampler2D flow_tex;
+uniform vec2 flow_size;
void main()
{
int patch_x = gl_InstanceID % width_patches;
int patch_y = gl_InstanceID / width_patches;
+ // Convert the patch index to being the full 0..1 range, to match where
+ // the motion search puts the patches. We don't bother with the locking
+ // to texel centers, though.
+ vec2 patch_center = ivec2(patch_x, patch_y) / (flow_size - 1.0);
+
// Increase the patch size a bit; since patch spacing is not necessarily
// an integer number of pixels, and we don't use conservative rasterization,
// we could be missing the outer edges of the patch. And it seemingly helps
// all directions.
vec2 grown_pos = (position * 1.5) - 0.25;
- image_pos = patch_spacing * ivec2(patch_x, patch_y) + patch_size * grown_pos;
+ image_pos = patch_center + patch_size * (grown_pos - 0.5f);
// Find the flow value for this patch, and send it on to the fragment shader.
vec3 flow_du_and_mean_diff = texelFetch(flow_tex, ivec2(patch_x, patch_y), 0).xyz;
GLuint motion_search_program;
GLuint motion_search_vao;
- GLuint uniform_image_size, uniform_inv_image_size, uniform_inv_flow_size, uniform_inv_prev_level_size;
+ GLuint uniform_image_size, uniform_inv_image_size, uniform_flow_size, uniform_inv_prev_level_size;
GLuint uniform_image0_tex, uniform_image1_tex, uniform_grad0_tex, uniform_flow_tex;
};
uniform_image_size = glGetUniformLocation(motion_search_program, "image_size");
uniform_inv_image_size = glGetUniformLocation(motion_search_program, "inv_image_size");
- uniform_inv_flow_size = glGetUniformLocation(motion_search_program, "inv_flow_size");
+ uniform_flow_size = glGetUniformLocation(motion_search_program, "flow_size");
uniform_inv_prev_level_size = glGetUniformLocation(motion_search_program, "inv_prev_level_size");
uniform_image0_tex = glGetUniformLocation(motion_search_program, "image0_tex");
uniform_image1_tex = glGetUniformLocation(motion_search_program, "image1_tex");
glProgramUniform2f(motion_search_program, uniform_image_size, level_width, level_height);
glProgramUniform2f(motion_search_program, uniform_inv_image_size, 1.0f / level_width, 1.0f / level_height);
- glProgramUniform2f(motion_search_program, uniform_inv_flow_size, 1.0f / width_patches, 1.0f / height_patches);
+ glProgramUniform2f(motion_search_program, uniform_flow_size, width_patches, height_patches);
glProgramUniform2f(motion_search_program, uniform_inv_prev_level_size, 1.0f / prev_level_width, 1.0f / prev_level_height);
glViewport(0, 0, width_patches, height_patches);
GLuint uniform_width_patches, uniform_patch_size, uniform_patch_spacing;
GLuint uniform_image0_tex, uniform_image1_tex, uniform_flow_tex;
+ GLuint uniform_flow_size;
};
Densify::Densify()
uniform_image0_tex = glGetUniformLocation(densify_program, "image0_tex");
uniform_image1_tex = glGetUniformLocation(densify_program, "image1_tex");
uniform_flow_tex = glGetUniformLocation(densify_program, "flow_tex");
+ uniform_flow_size = glGetUniformLocation(densify_program, "flow_size");
}
void Densify::exec(GLuint tex0_view, GLuint tex1_view, GLuint flow_tex, GLuint dense_flow_tex, int level_width, int level_height, int width_patches, int height_patches)
glProgramUniform2f(densify_program, uniform_patch_size,
float(patch_size_pixels) / level_width,
float(patch_size_pixels) / level_height);
+ glProgramUniform2f(densify_program, uniform_flow_size,
+ width_patches,
+ height_patches);
float patch_spacing_x = float(level_width - patch_size_pixels) / (width_patches - 1);
float patch_spacing_y = float(level_height - patch_size_pixels) / (height_patches - 1);
int level_width = width >> level;
int level_height = height >> level;
float patch_spacing_pixels = patch_size_pixels * (1.0f - patch_overlap_ratio);
- int width_patches = 1 + lrintf((level_width - patch_size_pixels) / patch_spacing_pixels);
- int height_patches = 1 + lrintf((level_height - patch_size_pixels) / patch_spacing_pixels);
+
+ // Make sure we have patches at least every Nth pixel, e.g. for width=9
+ // and patch_spacing=3 (the default), we put out patch centers in
+ // x=0, x=3, x=6, x=9, which is four patches. The fragment shader will
+ // lock all the centers to integer coordinates if needed.
+ int width_patches = 1 + ceil(level_width / patch_spacing_pixels);
+ int height_patches = 1 + ceil(level_height / patch_spacing_pixels);
// Make sure we always read from the correct level; the chosen
// mipmapping could otherwise be rather unpredictable, especially
const uint num_iterations = 16;
in vec2 flow_tc;
-in vec2 patch_bottom_left_texel; // Center of bottom-left texel of patch.
+in vec2 patch_center;
out vec3 out_flow;
uniform sampler2D flow_tex, grad0_tex, image0_tex, image1_tex;
void main()
{
- // Lock patch_bottom_left_texel to an integer, so that we never get
- // any bilinear artifacts for the gradient.
- vec2 base = (round(patch_bottom_left_texel * image_size - vec2(0.5, 0.5)) + vec2(0.5, 0.5))
+ // Lock the patch center to an integer, so that we never get
+ // any bilinear artifacts for the gradient. (NOTE: This assumes an
+ // even patch size.) Then calculate the bottom-left texel of the patch.
+ vec2 base = (round(patch_center * image_size) - (0.5f * patch_size - 0.5f))
* inv_image_size;
// First, precompute the pseudo-Hessian for the template patch.
in vec2 position;
out vec2 flow_tc;
-out vec2 patch_bottom_left_texel; // Center of bottom-left texel of patch.
+out vec2 patch_center;
-uniform vec2 inv_flow_size, inv_image_size;
+uniform vec2 flow_size;
void main()
{
+ // Patch placement: We want the outermost patches to have centers exactly in the
+ // image corners, so that the bottom-left patch has centre (0,0) and the
+ // upper-right patch has center (1,1). The position we get in is _almost_ there;
+ // since the quad's corners are in (0,0) and (1,1), the fragment shader will get
+ // centers in x=0.5/w, x=1.5/w and so on (and similar for y).
+ //
+ // In other words, find some f(x) = ax + b so that
+ //
+ // a 0.5 / w + b = 0
+ // a (1.0 - 0.5 / w) + b = 1
+ //
+ // which gives
+ //
+ // a = 1 / (w - 1)
+ // b = w / 2 (w - 1)
+ vec2 a = flow_size / (flow_size - 1);
+ vec2 b = -1.0 / (2 * (flow_size - 1.0));
+ patch_center = a * position + b;
+
// The result of glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0) is:
//
// 2.000 0.000 0.000 -1.000
// 0.000 0.000 0.000 1.000
gl_Position = vec4(2.0 * position.x - 1.0, 2.0 * position.y - 1.0, -1.0, 1.0);
flow_tc = position;
-
- vec2 patch_bottom_left = position - vec2(0.5, 0.5) * inv_flow_size;
- patch_bottom_left_texel = patch_bottom_left + vec2(0.5, 0.5) * inv_image_size;
}