繁体   English   中英

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

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

我有一个包含MNIST数据集的大缓冲区(对象):许多(数万)小(28x28)灰度图像,按行顺序逐一存储为表示像素强度的float 我想有效地(即有点交互地)将这些许多图像混合成一个“平均”图像,其中混合图像中的每个像素都是同一位置的所有像素的平均值。 这可能吗?

我考虑的选项是:

  1. 直接在缓冲区对象上使用计算着色器。 我会生成imgWidth * imgHeight计算着色器调用/线程,每个调用循环遍历所有图像。 这似乎不是很有效,因为每次调用都必须遍历所有图像,但是以另一种方式(即产生numImages调用并遍历像素)仍然有调用彼此等待。

  2. 使用图形管道将纹理一个接一个地绘制到帧缓冲区,将它们相互混合。 这仍然会导致线性时间,因为每个图像都必须依次渲染到帧缓冲区。 不过,我对帧缓冲区不是很熟悉。

  3. 在 CPU 中线性地完成这一切,这似乎比在 GPU 上更容易,而且速度也不慢。 我只会错过像素的并行处理。

我错过了他们的其他可能性。 有没有最优的方法? 如果不是,您认为最简单的方法是什么?

我就是这样做的。

将所有纹理渲染到 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);

大多数时候,我们希望在像素级别进行并行化,因为有很多。

但是,在您的情况下,像素(28x28)并不多。

您拥有的最大数量似乎是图像的数量(数千张图像)。 所以我们想利用这一点。

使用计算着色器,您可以成对混合图像,而不是遍历所有图像。 每次通过后,您将图像数量减半。 一旦图像的数量变得非常少,您可能想要更改策略,但您需要进行试验以查看最有效的方法。

你知道计算着色器可以有 3 个维度。 您可以让XY索引图像的像素。 Z可用于将这对图像嵌入纹理数组中。 因此,对于索引Z ,您将混合纹理2*Z2*Z+1

您需要考虑的一些实现细节:

  • 最有可能的是,图像的数量不会是 2 的幂。 所以在某些时候,图像的数量会是奇数。
  • 由于您正在处理大量图像,因此您可能会遇到浮点精度问题。 您可能需要使用浮动纹理,或添加策略,所以这不是问题。
  • 通常,当线程处理 2x2 像素而不是单个像素的图块时,计算着色器工作得最好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM