当将大纹理图像应用到 Mesh 一段明显的时间时,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);
});
我还注意到以下几点:
- 如果新对象未添加到场景中,则不会发生线程锁定
- 改变物体的几何形状不会导致锁定
- 如果使用从现有对象(已经在场景中)借来的 Material 创建新对象,将不会导致锁定
- 将新 Material 分配给现有对象(已经在场景中)会导致锁定
我的结论是,Three.js 会在 Material 添加到场景时对其进行处理。结果被缓存并在以后重新使用。
问题是这项工作是否可以以某种方式卸载给 web worker,这样主线程就不会被锁定?
worker 可能看起来像这样:
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);
});
这样的事能做吗?
最佳答案
只是在尝试与 worker 并行加载纹理时遇到这个问题。主要障碍似乎是三个。Texture 持有对 (DOM 元素)的引用,后者又持有实际图像数据。不知道序列化 的方法,还有 webgl accepts <img> as texture data .所以没有必要让三个人去碰它。
一种解决方案可能是使用 THREE.DataTexture,但这涉及将可能压缩的图像转换为未压缩的 RGB。不幸的是,绕道通过
最终我决定并行纹理加载必须等待 the-offscreen-canvas-interface .
关于javascript - 在 Three.js 中从 Web Worker 加载纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43341757/