6 #include "effect_util.h"
9 #include "resource_pool.h"
16 FFTInput::FFTInput(unsigned width, unsigned height)
20 convolve_width(width),
21 convolve_height(height),
24 register_int("fft_width", &fft_width);
25 register_int("fft_height", &fft_height);
30 if (texture_num != 0) {
31 resource_pool->release_2d_texture(texture_num);
35 void FFTInput::set_gl_state(GLuint glsl_program_num, const string& prefix, unsigned *sampler_num)
37 glActiveTexture(GL_TEXTURE0 + *sampler_num);
40 if (texture_num == 0) {
41 assert(pixel_data != NULL);
43 // Do the FFT. Our FFTs should typically be small enough and
44 // the data changed often enough that FFTW_ESTIMATE should be
45 // quite OK. Otherwise, we'd need to worry about caching these
46 // plans (possibly including FFTW wisdom).
47 fftw_complex *in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * fft_width * fft_height);
48 fftw_complex *out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * fft_width * fft_height);
49 fftw_plan p = fftw_plan_dft_2d(fft_height, fft_width, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
52 for (int i = 0; i < fft_height * fft_width; ++i) {
56 for (unsigned y = 0; y < convolve_height; ++y) {
57 for (unsigned x = 0; x < convolve_width; ++x) {
58 int i = y * fft_width + x;
59 in[i][0] = pixel_data[y * convolve_width + x];
67 fp16_int_t *kernel = new fp16_int_t[fft_width * fft_height * 2];
68 for (int i = 0; i < fft_width * fft_height; ++i) {
69 kernel[i * 2 + 0] = fp64_to_fp16(out[i][0]);
70 kernel[i * 2 + 1] = fp64_to_fp16(out[i][1]);
73 // (Re-)upload the texture.
74 texture_num = resource_pool->create_2d_texture(GL_RG16F, fft_width, fft_height);
75 glBindTexture(GL_TEXTURE_2D, texture_num);
77 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
79 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
81 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
83 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fft_width, fft_height, GL_RG, GL_HALF_FLOAT, kernel);
85 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
87 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
89 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
96 glBindTexture(GL_TEXTURE_2D, texture_num);
100 // Bind it to a sampler.
101 set_uniform_int(glsl_program_num, prefix, "tex", *sampler_num);
105 string FFTInput::output_fragment_shader()
107 return read_file("flat_input.frag");
110 void FFTInput::invalidate_pixel_data()
112 if (texture_num != 0) {
113 resource_pool->release_2d_texture(texture_num);
118 bool FFTInput::set_int(const std::string& key, int value)
120 if (key == "needs_mipmaps") {
121 // We cannot supply mipmaps; it would not make any sense for FFT data.
124 if (key == "fft_width") {
125 if (value < int(convolve_width)) {
128 invalidate_pixel_data();
130 if (key == "fft_height") {
131 if (value < int(convolve_height)) {
134 invalidate_pixel_data();
136 return Effect::set_int(key, value);