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
    });
};

デバッグの目的で、ライブプレビューもここにあります: httpshttps

Three.jsバージョン
  • []開発者
  • [] r81
  • [x] r80

    ブラウザ
  • [x]それらすべて

  • []クローム
  • [] Firefox
  • [ ] インターネットエクスプローラ

    OS
  • [x]それらすべて

  • [ ] ウィンドウズ
  • [] Linux
  • [] Android
  • [] IOS
    ハードウェア要件(グラフィックカード、VRデバイス、...)
Help (please use the forum)

最も参考になるコメント

XHRLoader TextureLoaderからImageLoaderを介して呼び出されるXHRLoader ImageLoaderは、グローバルオブジェクトCache
ただし、デフォルトのCache.enabledfalseです。

three.jsロードした直後にTHREE.Cache.enabled = true;を設定した場合
それはうまくいくでしょう。

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を介して呼び出されるXHRLoader ImageLoaderは、グローバルオブジェクトCache
ただし、デフォルトのCache.enabledfalseです。

three.jsロードした直後にTHREE.Cache.enabled = true;を設定した場合
それはうまくいくでしょう。

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 評価