Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Three.js:使用大量纹理时管理内存_Javascript_Three.js - Fatal编程技术网

Javascript Three.js:使用大量纹理时管理内存

Javascript Three.js:使用大量纹理时管理内存,javascript,three.js,Javascript,Three.js,我正在构建一个相对简单的Three.js应用程序 轮廓:你带着相机沿着一条穿过“世界”的路径移动。世界是由简单的精灵组成的,精灵材质上有透明的纹理。纹理基本上是具有alpha透明度的GIF图像 整个应用程序运行良好,性能也很好。我将摄影机的深度降低到尽可能低的程度,以便只渲染非常接近的对象 我的问题是:我有许多不同的“对象”(所有精灵)具有不同的纹理。我对场景中多次使用的相同类型的元素(如树木和岩石)重复使用纹理/材质参考 尽管如此,由于使用了所有的纹理,我的内存使用量还是增加了很多(超过2GB

我正在构建一个相对简单的Three.js应用程序

轮廓:你带着相机沿着一条穿过“世界”的路径移动。世界是由简单的精灵组成的,精灵材质上有透明的纹理。纹理基本上是具有alpha透明度的GIF图像

整个应用程序运行良好,性能也很好。我将摄影机的深度降低到尽可能低的程度,以便只渲染非常接近的对象

我的问题是:我有许多不同的“对象”(所有精灵)具有不同的纹理。我对场景中多次使用的相同类型的元素(如树木和岩石)重复使用纹理/材质参考

尽管如此,由于使用了所有的纹理,我的内存使用量还是增加了很多(超过2GB)

现在,在世界中移动时,并非所有对象从一开始就可见/显示,即使我从一开始就将所有精灵添加到场景中。检查控制台,不可见的对象及其纹理仅在“移动”到世界的更深处时加载,而新元素实际上在平截头体中可见。随着时间的推移,内存使用率也逐渐上升

我真的无法使用“对象池”来构建世界,因为它的“布局”让我们这么说

为了测试,我添加了一个函数,该函数可以从场景中移除对象,并在摄影机经过时立即处理其material.map。类似

this.env_sprites[i].material.map.dispose();
this.env_sprites[i].material.dispose();
this.env_sprites[i].geometry.dispose();
this.scene.remove(this.env_sprites[i]);
this.env_sprites.splice(i,1);
这适用于垃圾收集并再次释放内存。我的问题是,当使用相机向后移动时,需要将精灵重新读取到场景中,并再次加载材质/纹理,这对性能来说是相当沉重的,对我来说似乎不是正确的方法

在内存管理和“删除”以及再次添加对象和纹理(在同一位置)方面,是否有一种已知的技术来处理这种设置

我希望我能充分解释这个问题

这就是“世界”给你的印象:


每个精灵单独浪费大量内存,因为您的精灵图像可能很少是方形的,因此每个精灵中都会浪费空间,加上每个精灵也需要的mipmap占用大量空间。此外,在低端设备上,您可能会达到可使用纹理总数的限制,但这对您来说可能是问题,也可能不是问题

在任何情况下,限制使用如此多不同精灵的GPU内存的最佳方法是使用纹理图集。这意味着您最多可能有几个纹理,每个纹理包含许多精灵,并且在每个精灵的纹理中使用不同的UV坐标。即使这样,由于精灵的分配和解除分配中的碎片整理,您可能仍然会随着时间的推移而浪费内存,但您的内存耗尽速度要慢得多。如果使用纹理地图集,您甚至可以同时加载所有精灵,而不必取消分配它们

如果您想尝试以编程方式解决这个问题,有一个解决方案。我自己使用它来渲染文本,但您可以使用任何画布函数来创建图像。它目前使用一个基本的背包算法(可替换)来管理纹理中精灵的分配。在我的例子中,这意味着我只需要2个1024x1024纹理,而不是130个左右大小千差万别的单个精灵纹理,这确实节省了大量GPU内存

请注意,对于脱机使用,可能有更好的工具可以生成纹理图集并为每个精灵生成UV坐标,不过应该可以使用node.js和我的库脱机创建纹理和UV数据,然后可以在线在three.js场景中使用。不过,这将是留给读者的练习


你也可以尝试将所有最常见的精灵集中在你的“主”纹理图集中,这些贴图总是被加载的;动态加载和卸载不太常用的图像。

“基本上是GIF图像…”在内存问题上,图像类型很重要。GIF、JPEG等使用大段ram,因为webGL使用图像作为分配的数组。一篇有用的文章:检查这个stackoverflow:…具有透明度的Dds图像是非常重要的,例如alpha通道的TGA。测试看看这是否是一条可行的路线。我会在一个平截头体经理面前看这里。您需要测试用户的浏览器dds图像支持。嘿,收音机,谢谢。这是非常有用的输入。我不知道像DDS这样的压缩格式。现在,我将把这些资源转换成DDS,看看内存使用是否达到可接受的水平。@Radio:hi Radio,所以我将所有资源转换成DDS文件。结果真的很惊人。内存使用率下降了约60-70%。此外,总体性能也有了很大提高。当然,文件大小增加了近10倍。但是服务器上的gzip压缩使这一点大大降低。对于其他用户来说:创建DDS文件非常痛苦,在OS X上基本上是不可能的。有一些工具可以创建DDS,但它们都使用WebGL不支持的压缩算法(pvrtc)。WebGL似乎只支持S3算法——S3算法仍然是专利,因此不能通过开源工具实现,甚至不能通过GraphicConverter等付费工具实现。我必须通过多次测试和失败来解决这个问题。最后,英伟达Windows命令行工具工作得很好。有很多选择,我在转换文件时没有问题。你好,谢谢,这是非常有用的输入!谢谢分享图书馆。我将测试使用DDS作为收音机时对内存的影响。然后,我将讨论如何将多个资源合并到纹理地图集中。我会向你汇报这一切。