THREE.TextureLoader()は、予期しない誤った方法で動作します。 クラスのload()関数は、同じアセットを複数回(つまり、20回以上)試行/ロードします。
以下の図は、ブラウザコンソールを使用したこの動作を示しています。
テクスチャのロードと使用に使用されるコードは次のとおりです。
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 :
[x] r80
[x]それらすべて
[ ] インターネットエクスプローラ
[x]それらすべて
ローダーは意図したとおりに機能していると思います。 あなたがそれを求めているので、その流星テクスチャを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.enabled
はfalse
です。
three.js
ロードした直後にTHREE.Cache.enabled = true;
を設定した場合
それはうまくいくでしょう。
最も参考になるコメント
XHRLoader
TextureLoader
からImageLoader
を介して呼び出されるXHRLoader
ImageLoader
は、グローバルオブジェクトCache
ただし、デフォルトの
Cache.enabled
はfalse
です。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