8

我正在尝试在 WebGL 中进行一些图像处理。但是,如果我尝试在移动设备上以 GLSL 纹理加载大图片(来自相机 - 8 MP),浏览器就会崩溃。小图片工作正常。所以我认为它的内存不足。

我用谷歌搜索了很多,但没有找到解决方案。我认为最好的方法是实现“基于图块”的渲染。将 8 MP 图片分割成更小的部分,渲染它们并将它们粘在一起。但是会有一些问题,比如应用模糊效果。您将看到“子渲染”的边缘。所以我必须渲染重叠的像素并将它们“淡化”在一起。没那么好听。

有没有我没有想到的解决方案?如何在移动设备上处理真正巨大的纹理?

4

2 回答 2

4

一张 8mp 图像不太可能超过可用内存。在 RGB(字节)下,它将占用 24mb 的内存。即使是半浮点精度,它也是 50mb 的内存。ARM 系统使用统一的内存架构,其中 GPU 和 CPU 共享内存。例如,iPhone 有 1gb 的可用内存。

纹理支持应该达到所需的大小(例如 3264x2248),这在高端手机上似乎没有问题(81% 的手机支持 4096x4096 )。

最大绘图缓冲区大小可能小于支持的最大纹理大小(您可以查询)。

除此之外,您可能只是遇到了一个令人讨厌的错误。因此,处理这个问题的方法是将图像细分为更小的图块,并一次处理每个图块。

如果您有过滤器内核,有两种方法可以处理边界。

  • 您可以传入 9 个纹理并在纹理查找上进行分支以解决正确的问题(这可能很慢,某些 GPU 不支持分支并将执行所有代码路径)。边框纹理只有 2x2,因此内存占用空间很小。请注意,纹理之间不会有插值,所以不要依赖它,或者替换你自己的。
  • 您可以在预处理步骤中从相邻图块中获取像素的每个图块周围添加一个半内核大小的边框。
于 2013-02-23T10:48:53.150 回答
3

您需要做的就是在边界处提供足够的输入来覆盖图像处理效果的非局部性——例如模糊内核的半径。我能想到的最简单的事情是:

对于输出图像的每个图块,加载相应的输入图块及其 8 个相邻图块。然后使用所有 9 个作为输入运行模糊过滤器:您通常会调用的地方texture2D,而不是使用(自定义)函数获取坐标并在 9 个纹理中的适当一个中查找它们。

要使用更少的纹理,请将输出图块与输入图块相比,在两个维度上偏移其边长的一半;那么您只需要为每个图块计算使用 4 个输入图块,但如果您使用足够的图块来覆盖所有输入,则输出图块中将有一个额外的边框。(另一方面,如果您以后修剪很聪明,那可能是一件好事;例如,如果我将阴影应用于输入图像,我希望阴影放大输出而不是截断在原始边界。)

如果您正确执行此操作,则图块边界处不应有伪影。

(免责声明:虽然这个解决方案对我来说似乎简单、明显和正确,但我不是图像处理或 GPU 资源节约方面的专家。这可能有原因导致这实际上不起作用,或者有更好的想法。)

于 2013-02-20T03:13:18.040 回答