76#if defined(WITH_FFTW3)
82 const int2 frequency_size =
int2(spatial_size.x / 2 + 1, spatial_size.y);
84 float *kernel_spatial_domain = fftwf_alloc_real(spatial_size.x * spatial_size.y);
85 frequencies_ =
reinterpret_cast<std::complex<float> *
>(
86 fftwf_alloc_complex(frequency_size.x * frequency_size.y));
89 fftwf_plan forward_plan = fftwf_plan_dft_r2c_2d(spatial_size.y,
91 kernel_spatial_domain,
92 reinterpret_cast<fftwf_complex *
>(frequencies_),
100 double &sum = sum_by_thread.local();
101 for (const int64_t y : sub_y_range) {
102 for (const int64_t x : IndexRange(spatial_size.x)) {
103 const int2 texel = int2(x, y);
104 const int2 center_texel = spatial_size / 2;
105 const int2 kernel_texel = texel - center_texel;
106 const math::AngleRadian field_of_view_per_pixel = field_of_view / kernel_size;
108 const float kernel_value = compute_fog_glow_kernel_value(kernel_texel,
109 field_of_view_per_pixel);
115 int64_t output_x = mod_i(kernel_texel.x, spatial_size.x);
116 int64_t output_y = mod_i(kernel_texel.y, spatial_size.y);
117 kernel_spatial_domain[output_x + output_y * spatial_size.x] = kernel_value;
122 fftwf_execute_dft_r2c(
123 forward_plan, kernel_spatial_domain,
reinterpret_cast<fftwf_complex *
>(frequencies_));
124 fftwf_destroy_plan(forward_plan);
125 fftwf_free(kernel_spatial_domain);
131 normalization_factor_ =
float(std::accumulate(sum_by_thread.begin(), sum_by_thread.end(), 0.0));
133 UNUSED_VARS(kernel_size, spatial_size, field_of_view);