WebGL - 如何渲染大纹理?

时间:2013-02-19 07:43:38

标签: image memory-management webgl textures

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

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

我有没有想到的解决方案?如何在移动设备上使用非常大的纹理?

2 个答案:

答案 0 :(得分:4)

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

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

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

除此之外,你可能只是遇到了一个很烦人的bug。因此,处理这种情况的方法是将图像细分为较小的图块并一次处理一个图块。

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

  • 您可以传递9个纹理并在纹理查找上进行分支以寻找正确的纹理(可能很慢,某些GPU不支持分支并将执行所有代码路径)。边框纹理只是2x2所以会有很少的ram足迹。请注意,在纹理之间不会有插值,所以不要依赖它,或者替换它自己。
  • 您可以在每个图块周围添加一个半内核大小的边框,在预处理步骤中从相邻图块中获取像素。

答案 1 :(得分:3)

让瓷砖工作所需要做的是在边界处提供足够的输入以覆盖图像处理效果的非局部性 - 例如模糊内核的半径。我能想到的最简单的事情是:

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

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

如果你这样做的话,瓷砖边界应该有 no 工件。

(免责声明:虽然这个解决方案对我来说似乎简单,明显和正确,但我不是图像处理或GPU资源保护方面的专家。可能有理由说明为什么它实际上不起作用,或者更好的想法那里。)