如何在OpenGL中将多个纹理/缓冲区混合成一个纹理/缓冲区?

hof1towb  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(438)

我有一个包含MNIST数据集的大缓冲区(对象):许多(数万)小(28 x28)灰度图像,按行顺序逐个存储为float s,表示像素强度。我希望有效地(即交互式地)将这些图像混合为一个“平均”图像,其中混合图像中的每个像素都是同一位置上所有像素的平均值。这可能吗?
我考虑的选项包括:
1.直接在buffer对象上使用计算着色器。我会生成imgWidth * imgHeight计算着色器调用/线程,每个调用都在所有图像上循环。这看起来不是很有效,因为每个调用都必须在所有图像上循环,但用另一种方式(即生成numImages调用并遍历像素)仍然会有调用在彼此等待。
1.使用图形管道将纹理一个接一个地绘制到帧缓冲区,将它们彼此混合。这仍然会导致线性时间,因为每个图像都必须依次渲染到帧缓冲区。尽管我对帧缓冲区不是很熟悉。
1.在CPU中线性地完成所有这些操作,这看起来比在GPU上完成这些操作更容易,也不会慢多少。我只会错过像素的并行处理。
有没有其他的可能性?有没有最佳的方法?如果没有,你认为最简单的方法是什么?

yrefmtwq

yrefmtwq1#

我就是这么做的。
将所有纹理渲染到帧缓冲区,该缓冲区也可以是默认帧缓冲区。
一旦渲染完成。
从帧缓冲区读取数据。

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);
r6vfmomb

r6vfmomb2#

大多数情况下,我们希望在像素级别进行并行化,因为像素级别很多。
但是,在您的情况下,没有那么多像素(28x28)。
你拥有的最大数字似乎是图像的数量(数千张图像)。所以我们想利用这一点。
使用计算着色器,而不是迭代通过所有的图像,你可以混合图像对。在每一个通道后,你会减半的图像数量。一旦图像数量变得非常少,你可能会想改变策略,但这是你需要实验,看看什么工作最好。
你知道计算着色器可以有3个维度。你可以用XY来索引图像的像素。Z可以用来在纹理数组中索引图像对。所以对于索引Z,你可以混合纹理2*Z2*Z+1

  • 您需要考虑的一些实施细节:*
  • 最有可能的情况是,图像的数量不是2的幂,所以在某个点上,图像的数量将是奇数。
  • 因为你要处理大量的图像,你可能会遇到浮点精度的问题。你可能需要使用浮点纹理,或者添加适当的策略,这样就不会有问题了。
  • 通常,当线程处理2x2像素的拼贴而不是单个像素时,计算着色器的工作效果最佳。

相关问题