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] 全部
[ ] IE浏览器
[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
用途全局对象Cache
但默认Cache.enabled
是false
。
如果您在加载three.js
后立即设置THREE.Cache.enabled = true;
three.js
它会工作。
最有用的评论
XHRLoader
这是从称为TextureLoader
经由ImageLoader
用途全局对象Cache
但默认
Cache.enabled
是false
。如果您在加载
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