Three.js: THREE.TextureLoader() 多次加载相同的纹理(即 20 次或更多)

创建于 2016-10-05  ·  3评论  ·  资料来源: mrdoob/three.js

问题描述

THREE.TextureLoader() 以一种意外和错误的方式运行。 类的 load() 函数多次尝试/加载相同的资产(即 20 次或更多)。

下图中使用浏览器控制台说明了这种行为:
bdhg9

用于加载和使用纹理的代码如下:

var Element = function (texture) {
    this.texture = texture;
};
Element.prototype.createShaderMaterial = function (uniforms, vertexShader, fragmentShader) {
    var loader = new THREE.TextureLoader();
    uniforms.texture.value = loader.load(this.texture);

    return new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: vertexShader,
        fragmentShader: fragmentShader,
        wireframe: true
    });
};

出于调试目的,您还可以在此处找到实时预览: https : https :

三.js版本
  • [ ] 开发
  • [ ] r81
  • [x] r80

    浏览器
  • [x] 全部

  • [ ] 铬合金
  • [ ] 火狐
  • [ ] IE浏览器

    操作系统
  • [x] 全部

  • [ ] 窗户
  • [ ] Linux
  • [ ] 安卓
  • [ ] IOS
    硬件要求(显卡、VR 设备……)
Help (please use the forum)

最有用的评论

XHRLoader这是从称为TextureLoader经由ImageLoader用途全局对象Cache
但默认Cache.enabledfalse

如果您在加载three.js后立即设置THREE.Cache.enabled = true; three.js
它会工作。

https://github.com/mrdoob/three.js/blob/2f469f327a10c7780c9bc69f876f9ed5049587f2/src/loaders/XHRLoader.js#L22

https://github.com/mrdoob/three.js/blob/f65e669af99feb518e31756d793a9688a2578fbd/src/loaders/Cache.js#L9

6834

所有3条评论

我相信装载机正在以预期的方式工作。 它加载流星纹理 200 次,因为你要求它。 加载器可以修改为自动缓存和返回您要求它加载多次的资产,但这可能不是在所有情况下都需要的。 浏览器将管理缓存,因此如果图像文件上的所有标题都正确,则浏览器每次都会返回图像的缓存版本。

在您的代码中:

this.maxMeteorietes = config.maxMeteorietes || 200;

Game.prototype.createMeteorites = function (numMeteorites) {
    var meteorites = new THREE.Object3D();
    for (var i = 0; i < numMeteorites; i++) {
        var meteorite = new Meteorite().create(
            this.createUniforms(),
            this.createVertexShader(),
            this.createFragmentShader()
        );

    ....

}

Meteorite.prototype.create = function (uniforms, vertexShader, fragmentShader) {
    return new THREE.Mesh(
        new THREE.SphereGeometry(5, 5, 5),
//This line is called 200 times, and as such your loader.load() function will be called 200 times.
        this.createShaderMaterial(uniforms, vertexShader, fragmentShader)
    );
};

我会考虑添加如下内容:

var cache = [];
var loader = new THREE.TextureLoader();  //don't need a local version of this object

Element.prototype.createShaderMaterial = function (uniforms, vertexShader, fragmentShader) {
    if(cache[this.texture]){
        return cache[this.texture]; //cache[this.texture].clone();
    }
    uniforms.texture.value = loader.load(this.texture);

    var shader = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: vertexShader,
        fragmentShader: fragmentShader,
        wireframe: true
    });

    cache[this.texture] = shader;

    return shader;
};

因此,您可以管理从数组加载而不是每次都重新生成的材料缓存。 如果所有小行星都具有相同的材料,这将很有效,或者如果您希望材料不同,则使用 .clone() 方法。

看看这是否有帮助。

@calrk谢谢它解决了这个问题。

我仍然相信THREE.TextureLoader()行为方式出乎意料,它应该询问您是否要缓存纹理,例如:

var loader = THREE.TextureLoader();
loader(texture, cache = false);

我认为默认情况下,加载器应该出于性能原因缓存纹理(如果我错了,请告诉我原因)。


下面是一个简单的解决方案(单例模式/模块模式)缓存​​模块:

var TextureLoader = (function () {
    var _instance = null;

    var Loader = function () {
        var _loader = new THREE.TextureLoader();
        var _cache = [];

        function _cachePush(elem, val) {
            _cache.push({
                element: elem,
                value: val
            });
        }

        function _cacheSearch(elem) {
            for (var i = 0; i < _cache.length; i++) {
                if (_cache[i].element === elem) {
                    return _cache[i].value;
                }
            }

            return false;
        }

        function load(texture) {
            var match = _cacheSearch(texture);

            if (match) {
                return match;
            }

            var val = _loader.load(texture);
            _cachePush(texture, val);

            return val;
        }

        return {
            load: load
        }
    };

    function getInstance() {
        return (_instance) ? _instance : _instance = Loader();
    }

    return {
        getInstance: getInstance
    }
})();

要使用和缓存您需要调用的纹理:

TextureLoader.getInstance().load(texture);

XHRLoader这是从称为TextureLoader经由ImageLoader用途全局对象Cache
但默认Cache.enabledfalse

如果您在加载three.js后立即设置THREE.Cache.enabled = true; three.js
它会工作。

https://github.com/mrdoob/three.js/blob/2f469f327a10c7780c9bc69f876f9ed5049587f2/src/loaders/XHRLoader.js#L22

https://github.com/mrdoob/three.js/blob/f65e669af99feb518e31756d793a9688a2578fbd/src/loaders/Cache.js#L9

6834

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

clawconduce picture clawconduce  ·  3评论

donmccurdy picture donmccurdy  ·  3评论

seep picture seep  ·  3评论

konijn picture konijn  ·  3评论

yqrashawn picture yqrashawn  ·  3评论