Search code examples
opengltexturesframebufferblendingcompute-shader

How to blend many textures/buffers into one texture/buffer in OpenGL?


I have one big buffer (object) containing the MNIST dataset: many (tens of thousands) small (28x28) grayscale images, stored one-by-one in row-wise order as floats indicating pixel intensity. I would like to efficiently (i.e. somewhat interactively) blend these many images into one "average" image, where each pixel in the blended image is the average of all the pixels at that same position. Is this possible?

The options I considered are:

  1. Using a compute shader directly on the buffer object. I would spawn imgWidth * imgHeight compute shader invocations/threads, with each invocation looping over all images. This doesn't seem very efficient, as each invocation has to loop over all images, but doing it the other way (i.e. spawning numImages invocations and walking over the pixels) still has invocations waiting on each other.

  2. Using the graphics pipeline to draw the textures one-by-one to a framebuffer, blending them all over each other. This would still result in linear time, as each image has to be rendered to the framebuffer in turn. I'm not very familiar with framebuffers, though.

  3. Doing it all linearly in the CPU, which seems easier and not much slower than doing it on the GPU. I would only be missing out on the parallel processing of the pixels.

Are their other possibilities I'm missing. Is there an optimal way? And if not, what do you think would be the easiest?


Solution

  • This is how i do it.

    Render all the textures to the framebuffer , which can also be the default frame buffer.

    Once rendering in completed.

    Read the data from the Framebuffer.

    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glBindBuffer(GL_PIXEL_PACK_BUFFER, w_pbo[w_writeIndex]);
    // copy from framebuffer to PBO asynchronously. it will be ready in the NEXT frame
    glReadPixels(0, 0, SCR_WIDTH, SCR_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    // now read other PBO which should be already in CPU memory
    glBindBuffer(GL_PIXEL_PACK_BUFFER, w_pbo[w_readIndex]);
    unsigned char* Data = (unsigned char*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);