在Three.js中从Web Worker加载纹理 [英] Loading texture from Web Worker in Three.js

查看:610
本文介绍了在Three.js中从Web Worker加载纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将较大的纹理图像应用到Mesh明显的时间段时,Three.js锁定浏览器的主线程.让我们考虑以下示例:

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

我还注意到以下几点:

  • 如果没有将新对象 添加到场景中,则不会发生线程锁定
  • 更改对象的几何形状不会导致锁定
  • 如果使用从现有对象(已经存在于场景中)借来的材料创建新对象,则不会造成锁定
  • 将新材料分配给现有对象(已经存在于场景中)将导致锁定
  • 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

我的结论是Three.js在将材料添加到场景的那一点上做了一些工作.结果是已缓存,以后可以重新使用.

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

可以这样做吗?

推荐答案

在尝试与工作程序并行加载纹理时遇到了这个问题.主要障碍似乎是三.Texture引用了< img> (DOM元素),它又保存实际的图像数据.不知道序列化< img>的方法,也

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.

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

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.

这篇关于在Three.js中从Web Worker加载纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆