ТРИ.TextureLoader () загружает одну и ту же текстуру несколько раз (т.Е. 20 или более раз)

#javascript #three.js

#javascript #three.js

Вопрос:

ТРИ.TextureLoader() ведет себя неожиданным и ошибочным образом. Функция load() класса пытается / загружает одни и те же ресурсы несколько раз (т.Е. 20 или более раз).

Ниже на рисунке показано это поведение с использованием консоли браузера:

введите описание изображения здесь

Далее следует код, используемый для загрузки и использования текстур:

 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://alexprut.github.io/earth-defender /
и код игры здесь: https://github.com/alexprut/earth-defender/tree/master/client/js

Что сделано неправильно? Почему одно и то же изображение загружается несколько раз?

Ответ №1:

Дело в том, что THREE.TextureLoader() по умолчанию текстуры не кэшируются, но я думаю, что это необходимо, или, по крайней мере, попросить вас не делать этого. Это означает, что если у вас есть 400 объектов с одинаковой текстурой, библиотека сделает 400 HTTP-запросов для одних и тех же ресурсов.

Ниже приведено простое решение (одноэлементный шаблон / шаблон модуля) модуль кэша:

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