是否可以在 THREE.js 中启用无限数量的渲染器?

IT技术 javascript three.js
2021-02-14 20:50:37

为了避免XY问题,让我解释一下我来自哪里。我想使用 THREE.js 绘制大量堆叠在一起的波形,使用相同的时间轴。波形只是三个.Line,我正在通过修改正交相机的视图边界来实现这些波形的缩放/平移/缩放。

我最初的尝试导致我创建了多个具有固定高度的画布元素,相互堆叠,并将一个 THREE.WebGLRenderer 附加到每个画布。这工作得很好,直到我尝试将其缩放超过 15 个左右的波形,其中 THREE.js 给了我一个警告“活动的 webgl 上下文过多”,并开始删除旧的上下文。

我觉得这是一个不错的做法,考虑到它在这里应用的技术相同:http : //threejs.org/examples/#webgl_multiple_canvases_grid

在此示例中,创建了 4 个 WebGLRenderer,每个画布一个。

那么,是否有可能以某种方式覆盖此警告,并创建无限数量的画布元素,每个元素都有自己的渲染器?

在旁边:

我已经考虑使用一个场景并在其中相应地定位波形,并使用类似于http://threejs.org/examples/#webgl_multiple_views的方法使用多个摄像头

问题有两方面:

(1) 我失去了对每个波形进行 dom 操作和轻松附加键和鼠标侦听器的能力。

(2) 此解决方案似乎也无法扩展。一旦渲染器的高度超过 6000 像素的高度,它就会开始进入某种类型的损坏状态,部分场景不会出现,其余的内容会被拉伸以进行补偿。

感谢任何能提供帮助的人!

1个回答

您可以使用一个非滚动的全窗口大小画布,并为您的波形使用占位符 DIV。然后用1个渲染器中每个波形和呼叫1级的场景renderer.setViewportrenderer.setScissor每个div的位置呈现每个现场。

像这样有效

renderer.setScissorTest( true );
scenes.forEach( function( scene ) {

  // get the element that is a place holder for where we want to
  // draw the scene
  var viewElement = scene.viewElement;

  // get its position relative to the page's viewport
  var rect = viewElement.getBoundingClientRect();

  // check if it's offscreen. If so skip it
  if ( rect.bottom < 0 || rect.top  > renderer.domElement.clientHeight ||
     rect.right  < 0 || rect.left > renderer.domElement.clientWidth ) {
    return;  // it's off screen
  }

  // set the viewport
  var width  = rect.right - rect.left;
  var height = rect.bottom - rect.top;
  var left   = rect.left;
  var top    = rect.top;

  renderer.setViewport( left, top, width, height );
  renderer.setScissor( left, top, width, height );

  camera.aspect = width / height;
  camera.updateProjectionMatrix();

  renderer.render( scene, camera );
} );
renderer.setScissorTest( false );

例子:

更新:

这里的原始解决方案使用了一个画布,position: fixed意思是画布没有滚动。下面的新解决方案将其更改为position: absolute; top: 0,然后每帧设置画布的变换

  canvas.style.transform = `translateY(${window.scrollY}px`;

这样做的好处是,即使我们不能在每一帧都更新画布,画布也会随着页面滚动,直到我们有机会更新它。这使得滚动保持同步。

您可以将旧解决方案新解决方案进行比较两者都设置为仅每 4 帧渲染一次以夸大问题。上下滚动它们,区别应该很明显。

很好的答案!我正在尝试做类似的事情,但我正在使用typescript。编译器有一个问题scene.element,说element该类型不存在该属性scene知道如何解决这个问题吗?
2021-04-23 20:50:37
惊人!我真的很感动。这正是我所希望的巧妙解决方案类型。作为这些领域的菜鸟,我非常感谢你。
2021-05-02 20:50:37
您如何将哪个场景与哪个元素关联完全取决于您。它不是three.js的一部分。使用场景属性和元素属性创建自己的类
2021-05-10 20:50:37