Loading texture from Web Worker in Three.js

为君一笑 提交于 2019-12-23 16:36:50

问题


When applying a large texture image to a Mesh for a noticeable period of time Three.js locks-up browser's main thread. Let's consider the following example:

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);
});

I also noticed the following:

  • no thread lock-up occurs if the new object is not added to the scene
  • changing the geometry of an object doesn't cause lock-up
  • if a new object is created with a material borrowed from an existing object (which already is in the scene) will will not cause lock-up
  • assigning a new material to an existing object (which already is in the scene) will causes lock-up

My conclusion is that Three.js does some work on a material at point at which it's added to the scene. The result is the cached and later re-used.

The question is if this work can somehow be offloaded to web worker, so that the main thread doesn't get locked-up?

The worker could look like this:

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
    });
});

Then in the main thread we could do:

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);
});

Can something like this be done?


回答1:


Just run into this issue while trying to load textures in parallel with workers. Main roadblock seems to be THREE.Texture holds a reference to the <img> (DOM element) which in turn holds the actual image data. Don't know of a way to serialize an <img>, also webgl accepts <img> as texture data. So there is no need for THREE to touch it.

A solution might be to use a THREE.DataTexture, but that involves turning possibly compressed images into uncompressed RGB. Unfortunately a detour via a <canvas> drawImage() + getImageData() is not possible, because workers can't deal with DOM elements.

Eventually I've decided parallel texture loading has to wait for the-offscreen-canvas-interface.



来源:https://stackoverflow.com/questions/43341757/loading-texture-from-web-worker-in-three-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!