circle_radius(2.0f),
gaussian_radius(0.0f),
correlation(0.95f),
- noise(0.01f)
+ noise(0.01f),
+ last_R(-1),
+ last_circle_radius(-1.0f),
+ last_gaussian_radius(-1.0f),
+ last_correlation(-1.0f),
+ last_noise(-1.0f)
{
register_int("matrix_size", &R);
register_float("circle_radius", &circle_radius);
{
char buf[256];
sprintf(buf, "#define R %u\n", R);
+
+ assert(R >= 1);
+ assert(R <= 25); // Same limit as Refocus.
+
+ last_R = R;
return buf + read_file("deconvolution_sharpen_effect.frag");
}
} // namespace
-void DeconvolutionSharpenEffect::set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num)
+void DeconvolutionSharpenEffect::update_deconvolution_kernel()
{
- Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
-
- assert(R >= 1);
- assert(R <= 25); // Same limit as Refocus.
-
- printf("circular blur radius: %5.3f\n", circle_radius);
- printf("gaussian blur radius: %5.3f\n", gaussian_radius);
- printf("correlation: %5.3f\n", correlation);
- printf("noise factor: %5.3f\n", noise);
- printf("\n");
-
// Figure out the impulse response for the circular part of the blur.
MatrixXf circ_h(2 * R + 1, 2 * R + 1);
for (int y = -R; y <= R; ++y) {
assert(r_vv.cols() == 4 * R + 1);
// Similarly, r_uv = u ⊙ v = u ⊙ (h ⊙ u) = h ⊙ r_uu.
- //MatrixXf r_uv = central_convolve(r_uu, h).block(2 * R, 2 * R, 2 * R + 1, 2 * R + 1);
MatrixXf r_uu_center = r_uu.block(2 * R, 2 * R, 4 * R + 1, 4 * R + 1);
MatrixXf r_uv = central_convolve(r_uu_center, h);
assert(r_uv.rows() == 2 * R + 1);
// (G+H) x0 + I x2 = y2
//
// This both increases accuracy and provides us with a very nice speed
- // boost. We could have gone even further and went for 8-way symmetry
- // like the shader does, but this is good enough right now.
+ // boost.
MatrixXf M(MatrixXf::Zero((R + 1) * (R + 1), (R + 1) * (R + 1)));
MatrixXf r_uv_flattened(MatrixXf::Zero((R + 1) * (R + 1), 1));
for (int outer_i = 0; outer_i < 2 * R + 1; ++outer_i) {
assert(g_flattened.cols() == 1);
// Normalize and de-flatten the deconvolution matrix.
- MatrixXf g(R + 1, R + 1);
+ g = MatrixXf(R + 1, R + 1);
sum = 0.0f;
for (int i = 0; i < g_flattened.rows(); ++i) {
int y = i / (R + 1);
g(y, x) = g_flattened(i) / sum;
}
+ last_circle_radius = circle_radius;
+ last_gaussian_radius = gaussian_radius;
+ last_correlation = correlation;
+ last_noise = noise;
+}
+
+void DeconvolutionSharpenEffect::set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num)
+{
+ Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
+
+ assert(R == last_R);
+
+ if (fabs(circle_radius - last_circle_radius) > 1e-3 ||
+ fabs(gaussian_radius - last_gaussian_radius) > 1e-3 ||
+ fabs(correlation - last_correlation) > 1e-3 ||
+ fabs(noise - last_noise) > 1e-3) {
+ update_deconvolution_kernel();
+ }
// Now encode it as uniforms, and pass it on to the shader.
- // (Actually the shader only uses about half of the elements.)
float samples[4 * (R + 1) * (R + 1)];
for (int y = 0; y <= R; ++y) {
for (int x = 0; x <= R; ++x) {
}
}
- set_uniform_vec4_array(glsl_program_num, prefix, "samples", samples, R * R);
+ set_uniform_vec4_array(glsl_program_num, prefix, "samples", samples, (R + 1) * (R + 1));
}