From: Steinar H. Gunderson Date: Thu, 26 Jul 2018 10:19:15 +0000 (+0200) Subject: Rework patch placement. Finally inches our EPE just below the reference code, it... X-Git-Tag: 1.8.0~76^2~174 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=200cfe3a0b9633d785a4ca5fb51147f937278448;p=nageru Rework patch placement. Finally inches our EPE just below the reference code, it seems. --- diff --git a/densify.vert b/densify.vert index 0572afb..b7f78d7 100644 --- a/densify.vert +++ b/densify.vert @@ -9,12 +9,18 @@ uniform int width_patches; 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 @@ -26,7 +32,7 @@ void main() // 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; diff --git a/flow.cpp b/flow.cpp index 3cbbb71..b7f6d9c 100644 --- a/flow.cpp +++ b/flow.cpp @@ -368,7 +368,7 @@ private: 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; }; @@ -389,7 +389,7 @@ MotionSearch::MotionSearch() 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"); @@ -408,7 +408,7 @@ void MotionSearch::exec(GLuint tex0_view, GLuint tex1_view, GLuint grad0_tex, GL 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); @@ -441,6 +441,7 @@ private: 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() @@ -464,6 +465,7 @@ 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) @@ -478,6 +480,9 @@ void Densify::exec(GLuint tex0_view, GLuint tex1_view, GLuint flow_tex, GLuint d 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); @@ -1101,8 +1106,13 @@ GLuint DISComputeFlow::exec(GLuint tex0, GLuint tex1) 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 diff --git a/motion_search.frag b/motion_search.frag index a32868b..f67cbba 100644 --- a/motion_search.frag +++ b/motion_search.frag @@ -39,7 +39,7 @@ const uint patch_size = 12; 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; @@ -47,9 +47,10 @@ uniform vec2 image_size, inv_image_size, inv_prev_level_size; 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. diff --git a/motion_search.vert b/motion_search.vert index dbb2795..9e25e7a 100644 --- a/motion_search.vert +++ b/motion_search.vert @@ -2,12 +2,31 @@ 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 @@ -16,7 +35,4 @@ void main() // 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; }