When a large texture image is applied to a Mesh in Three.js for a substantial amount of time, it causes the browser's main thread to freeze. Consider the following scenario:
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 results in main thread lock-up
scene.add(sphere);
});
Upon observation, I found 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
- Creating a new object with a material borrowed from an existing object (already in the scene) does not lead to lock-up
- Assigning a new material to an existing object (already in the scene) causes lock-up
My deduction is that Three.js performs some operations on a material when it's added to the scene. The result is cached for later reuse.
The question arises: can this processing be offloaded to a web worker to prevent main thread lock-up?
The worker setup could be like this:
var texLoader = new THREE.TextureLoader();
texLoader.load('someLargeTexture.jpg', function(texture) {
var material = new THREE.MeshBasicMaterial({map: texture});
// ... lengthy operations go here ...
// adding the object to the scene still locks up the main thread
self.postMessage({
msg: 'objectCreated',
material: material.toJson(), // converting material to JSON
});
});
Then in the main thread, we could implement:
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 operation should not lock up the main thread
var sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
});
Is it possible to achieve something like this?