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

标签 javascript multithreading three.js textures web-worker

当将大纹理图像应用到 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。不幸的是,绕道通过 drawImage() + getImageData() 是不可能的,因为工作人员无法处理 DOM 元素。

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

关于javascript - 在 Three.js 中从 Web Worker 加载纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43341757/

相关文章:

javascript - 如何使用 javascript 对输入元素进行排名

javascript - 在 Javascript 中注释全局变量的常规方法是什么?

c++ - for循环中的多线程错误

javascript - 在 DeviceOrientationControls 中设置相机运动

javascript - 使用设备的方向围绕原点运行

javascript - 复制 radio 组中的值

javascript - 重复有效负载(数据)如何减少网络套接字中的延迟?

java - Java VM 可以支持多少个线程?

ios - 获取当前显示的 View Controller 的线程安全方式

javascript - 三个jslensflare渲染在外面