Three.js: THREE.TextureLoader() lädt dieselbe Textur mehrmals (dh 20 Mal oder mehr)

Erstellt am 5. Okt. 2016  ·  3Kommentare  ·  Quelle: mrdoob/three.js

Beschreibung des Problems

Der THREE.TextureLoader() verhält sich unerwartet und fehlerhaft. Die Funktion load() der Klasse versucht/lädt dieselben Assets mehrmals (dh 20 Mal oder mehr).

Unten in der Abbildung wird dieses Verhalten mithilfe der Browserkonsole veranschaulicht:
bdhg9

Als nächstes folgt der Code zum Laden und Verwenden von Texturen:

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

Zu Debugging-Zwecken finden Sie auch eine Live-Vorschau hier: https://alexprut.github.io/earth-defender/ und den Spielcode hier: https://github.com/alexprut/earth-defender/tree/master/ client/js

Three.js-Version
  • [ ] Dev
  • [ ] r81
  • [x] r80

    Browser
  • [x] Alle

  • [ ] Chrom
  • [ ] Feuerfuchs
  • [ ] Internet Explorer

    Betriebssystem
  • [x] Alle

  • [ ] Fenster
  • [ ] Linux
  • [ ] Android
  • [ ] iOS
    Hardwarevoraussetzungen (Grafikkarte, VR-Gerät, ...)
Help (please use the forum)

Hilfreichster Kommentar

XHRLoader das von TextureLoader über ImageLoader aufgerufen wird, verwendet das globale Objekt Cache
aber standardmäßig ist Cache.enabled false .

Wenn Sie THREE.Cache.enabled = true; direkt nach dem Laden von three.js einstellen
es würde funktionieren.

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

Alle 3 Kommentare

Ich glaube, der Lader funktioniert wie vorgesehen. Es lädt die Meteortexturen 200 Mal, weil Sie es verlangen. Der Loader könnte so modifiziert werden, dass er automatisch Assets zwischenspeichert und zurückgibt, die Sie mehrmals laden möchten, dies ist jedoch möglicherweise nicht in allen Fällen erwünscht. Der Browser verwaltet den Cache. Wenn alle Header der Bilddatei korrekt sind, gibt der Browser jedes Mal zwischengespeicherte Versionen des Bildes zurück.

In deinem Code:

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

Ich würde in Erwägung ziehen, etwas wie das Folgende hinzuzufügen:

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

Sie verwalten also einen Cache mit Materialien, die aus einem Array geladen und nicht jedes Mal neu generiert werden. Dies funktioniert gut, wenn alle Asteroiden das gleiche Material haben, oder verwenden Sie die Methode .clone(), wenn die Materialien unterschiedlich sein sollen.

Mal sehen, ob das hilft.

@calrk danke es löst das Problem.

Ich glaube immer noch, dass sich THREE.TextureLoader() unerwartet verhält, es sollte Sie fragen, ob Sie die Texturen zwischenspeichern möchten oder nicht, zB:

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

Ich denke, standardmäßig sollte der Loader die Texturen aus Performancegründen zwischenspeichern (wenn ich mich irre, lass es mich bitte wissen warum).


Unten ist ein Cache-Modul mit einfacher Lösung (Singleton-Muster / Modulmuster):

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

Um die Textur zu verwenden und zwischenzuspeichern, müssen Sie Folgendes aufrufen:

TextureLoader.getInstance().load(texture);

XHRLoader das von TextureLoader über ImageLoader aufgerufen wird, verwendet das globale Objekt Cache
aber standardmäßig ist Cache.enabled false .

Wenn Sie THREE.Cache.enabled = true; direkt nach dem Laden von three.js einstellen
es würde funktionieren.

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

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen