使用图像快速更新 material 的纹理贴图(每 50 毫秒左右)会导致严重的卡顿

Updating a material's texture map with images rapidly (every 50ms or so) causes huge stuttering

问题:我应该如何使用图像(存储在 HTML5 canvas 中)非常快速地(50ms ~ 200ms 间隔)更新球体的 material 纹理贴图,而不会使浏览器阻塞?

我有一系列全景图像要映射到球体上。这些图像每 50ms ~ 200ms 更新一次。该代码似乎有效,但实际上它非常糟糕 - 导致一些重新绘制被跳过或等待 2s ~ 3s 出现。

这是网格代码和纹理(第一个纹理贴图是占位符):

var geometry = new THREE.SphereGeometry(100.0, 64, 64);
var material = new THREE.MeshBasicMaterial({
  map: THREE.ImageUtils.loadTexture(image_path), // placeholder
  side: THREE.DoubleSide,
});

当触发 playPanos(0) 时,它会尝试使用 HTML5 [=30= 中绘制的图像更新 material 纹理贴图], 存储在数组“loaded_canvas”:

function playPanos(curr_id) {
  if (curr_id >= loaded_canvas.length) return;

  paintPanos(curr_id);

  setTimeout(function() {
    playPanos(curr_id + 1);
  }, 100); // update every 100ms
}

function paintPanos(curr_id) {
  material.map = new THREE.Texture(loaded_canvas[curr_id]);
  material.map.needsUpdate = true;
}

谢谢。请原谅原型样式代码。

一些提示:

  • 您不需要在每次更新球体纹理时都创建 new THREE.Texture()。创建一次纹理,然后使用以下方法更新它:每次在 canvas 上下文中绘制新内容时 material.map.needsUpdate = true;
  • 我想,因为您将 canvases 存储在数组中,所以您没有动态动画,只有循环动画。在这种情况下,您可以存储完成的纹理并仅更新 material.map 而不是使用存储在数组中的 canvases 更新纹理。
  • 如果您的 canvas 分辨率太高,请尽量减小像素尺寸。我想你已经做到了。
  • 你真的需要:side: THREE.DoubleSide?如果您将球体用作天空盒,请尝试使用 THREE.BackSide

通过这些优化,您应该能够 运行 以 60 fps 的速度更新纹理。