Search code examples
openglcudaglslcufft

Applying cuFFT to OpenGL Vertex Buffer Objects


So the cufftComplex type is an array with n structs with an x and a y-field, respectively representing the real and the imaginary parts of each complex number.

On the other hand, if I want to create a vertex buffer object in OpenGL with an x- and y- field, i.e. a 2D vertex or just a vertex buffer object that also represents n complex numbers, I would have to create a 2n sized array of floats with a layout like this:

x0 y0 | x1 y1 | ... | xn yn

I then write it to the VBO by calling:

glBufferData(GL_ARRAY_BUFFER, n * sizeof(GLfloat), complex_values_array, GL_DYNAMIC_DRAW);

I would like to Fourier-transform an image with cuFFT, and display e.g. the magnitude of the complex values. How do I resolve this incompatibility between the two data types? Is there a way for cuFFT to act on VBO's?

Edit:

Perhaps I should write a CUDA-kernel that takes the cufftComplex type and maps the magnitude of each complex number to a 1D-VBO. Or a CUDA-kernel that maps the cufftComplex type to a 2D-VBO. I do not know what the overhead would be, since it's device-> device I expect it to be manageable.


Solution

  • I managed to resolve this issue by writing a kernel as follows:

    __global__ void cufftComplex2Float(float* vbo_magnitude, Complex *z, const int width, const int height){
        unsigned int i = blockIdx.x*blockDim.x + threadIdx.x;
        unsigned int j = blockIdx.y*blockDim.y + threadIdx.y;
        float magnitude = pow(z[j*height + i].x, (float)2) + pow(z[j*height + i].y, (float)2);
        vbo_magnitude[j*height + i] = (PI2 + atanf(sqrt(0.1*magnitude))) / PI;
    };
    

    It involves no host-device transfers so it's pretty quick.