在 Three.js 中从 Web Worker 加载纹理

kne*_*ola 5 javascript multithreading textures web-worker three.js

当将大纹理图像应用到网格上一段明显的时间时,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);
});
Run Code Online (Sandbox Code Playgroud)

我还注意到以下几点:

  • 如果新对象没有添加到场景中,则不会发生线程锁定
  • 改变对象的几何形状不会导致锁定
  • 如果使用从现有对象(已存在于场景中)借用的材质创建新对象将不会导致锁定
  • 将新材质分配给现有对象(已存在于场景中)将导致锁定

我的结论是,Three.js 在材质添加到场景时对其进行了一些处理。结果被缓存并稍后重新使用。

问题是这项工作是否可以以某种方式卸载给 Web 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
    });
});
Run Code Online (Sandbox Code Playgroud)

然后在主线程中我们可以这样做:

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);
});
Run Code Online (Sandbox Code Playgroud)

这样的事情可以做吗?

Tor*_*ker 2

只是在尝试与工作人员并行加载纹理时遇到这个问题。主要障碍似乎是三个。Texture 保存对 <img> (DOM 元素)的引用,而 <img> 又保存实际的图像数据。不知道如何序列化 <img>,webgl 也接受 <img> 作为纹理数据。所以三人没必要碰它。

解决方案可能是使用 THREE.DataTexture,但这涉及将可能压缩的图像转换为未压缩的 RGB。不幸的是,通过 <canvas> drawImage() + getImageData() 绕道是不可能的,因为工作人员无法处理 DOM 元素。

最终我决定并行纹理加载必须等待-offscreen-canvas-interface