加载纹理从Web工作在three.js所
当施加较大的纹理图像的网格的时间three.js所锁式浏览器的主线程显着的时期。让我们看看下面的例子:加载纹理从Web工作在three.js所
var texLoader = new THREE.TextureLoader();
texLoader.load('someLargeTexture.jpg', function(texture) {
var geometry = new THREE.SphereGeometry(10, 32, 32);
var material = new THREE.MeshBasicMaterial({map: texture});
var sphere = new THREE.Mesh(geometry, material);
// adding the object to the scene will lock up the browser's main thread
scene.add(sphere);
});
我也注意到以下几点:
- 如果新对象不添加到场景
- 变化的几何形状不会发生线程锁定对象不会导致锁定
- 如果一个新的对象与从现有对象借来的材料(这已是在场景中)创建将不会造成锁定
- 现有对象分配一个新的材料(这已经是在现场)会导致锁定
我的结论是,three.js所做一些工作,在材料的指向它添加到场景的点。其结果是缓存并稍后重新使用。
的问题是,如果这项工作能以某种方式被卸载到网络工作者,使主线程不会被锁定呢?
工人看起来是这样的:
var texLoader = new THREE.TextureLoader();
texLoader.load('someLargeTexture.jpg', function(texture) {
var material = new THREE.MeshBasicMaterial({map: texture});
// ... long-running work goes here ...
// adding the object to the scene will lock up the browser's main thread
self.postMessage({
msg: 'objectCreated',
material: material.toJson(), // converting material to JSON
});
});
然后在主线程中,我们可以这样做:
var worker = new Worker('worker.js');
worker.addEventListener('message', function(ev) {
var geometry = new THREE.SphereGeometry(10, 32, 32);
// converting JSON back to material object
var material = MaterialLoader.prototype.parse(ev.data.material);
// this should't lock-up the main thread
var sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
});
能像这样做呢?
正好碰上这个问题,尝试加载在平行的纹理与工人。主要的障碍似乎是THREE.Texture持有一个参考<img>(DOM元素),它反过来保存实际的图像数据。不知道如何序列化一个<img>,也webgl accepts <img> as texture data。所以没有必要用三条来触摸它。
一个解决办法可能是使用一个THREE.DataTexture,但涉及到转向可能压缩图像为无压缩RGB。不幸的是,通过canvas > drawImage()+ getImageData()是不可能的,因为工作人员无法处理DOM元素。
最后我决定平行的纹理加载必须等待the-offscreen-canvas-interface。
也许https://github.com/spite/THREE.UpdatableTexture和https://github.com/mrdoob/three.js/pull/11846会有趣? – WestLangley
@WestLangley,的确不能等待r87。 – noiv
您可以使用浏览器调试工具获取此加载操作的时间线快照。例如在Chrome中,您将看到方法X需要Y秒。这应该告诉你瓶颈在哪里。如果是THREE.js将纹理发送到GPU的地方,那么除了使用较小的纹理,或者将其分割为多个材质之外,您可能无法做任何事情。 – TheJim01