【问题标题】:three.js progressive rendering of large mesh三.js大网格渐进式渲染
【发布时间】:2018-11-02 18:11:18
【问题描述】:

我想使用 three.js 渲染一个任意大的静态网格。网格可能为 2 GB,包含数千万个多边形。

我想将网格几何缓冲区流式传输到 indexedDB 中,并逐步将它们读出并将它们渲染到屏幕上,同时保持交互式帧速率。我将创建一个 MemoryManager 类,通过将数据从 indexedDB 加载到固定大小的缓冲区,确保我们不会使浏览器崩溃。在我的动画循环中,我将在 16 毫秒内渲染尽可能多的几何图形,直到用户停止交互,然后继续渲染网格,直到不再有。

这是我想采用的高级方法,当然还有许多优化需要完成。 (对象池、八叉树、遮挡查询等)

我的问题是:有没有更好的方法来做到这一点,以前有没有做过?(使用 WebGL1,我知道 WebGL2 遮挡查询可以做到这一点更简单)

另外,自定义 Three.js WebGLRenderer 类的最佳方式是什么?我需要访问一些私有闭包变量(如 WebGLState )来调整我的用例的性能。

【问题讨论】:

  • Re: WebGLRenderer 没有分叉,没有真正的好方法。几个版本之前,很多内部结构都暴露出来了,所以你可以在一定程度上对其进行修补。现在有更多的封装,但好消息是它“相当”模块化。

标签: javascript performance graphics three.js webgl


【解决方案1】:

我认为 WebGL2 遮挡查询不会对您有很大帮助。或许可以使用它们,但在 cpu 上进行剔除可能是更好的选择,尤其是当您的场景大部分是静态的时。

如果您想在用户停止交互时逐步渲染几何图形,那么您可以停止清除渲染缓冲区。使用 THREE.js,您可以通过在渲染器上启用 preserveDrawingBuffer 并将 autoClear 设置为 false 来做到这一点。

如果相机移动或场景发生其他变化,您需要重新开始,您可以通过调用renderer.clear()再次清除视图。

关于流数据,我会使用BufferGeometry 并修改必要的BufferAttributes 每帧。听起来您已经对优化和决定需要渲染哪些几何图形有了一些想法。

示例

场景在同一帧上一遍又一遍地重绘。单击场景将其清除并重新开始绘制。重要的js行是NOTE'd

// NOT: enabling preserveDrawingBuffer
const renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });
renderer.setClearColor(0x263238);
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.clear();
document.body.appendChild( renderer.domElement );

// NOTE: disabling autoclear
renderer.autoClear = false;

// Scene setup
const scene = new THREE.Scene();
const dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(.4, 1, .1);
scene.add(dirLight);

// Camera setup
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000)
camera.position.z = 10;

const geom = new THREE.TorusKnotGeometry(.5, .2, 200, 100);
const mesh = new THREE.Mesh(geom, new THREE.MeshPhongMaterial({ color: 0xE91E63 }));
scene.add(mesh);


// NOTE: Clearing on user interaction
renderer.domElement.addEventListener('click', () => renderer.clear());

(function renderLoop() {
    mesh.position.y = Math.sin(performance.now() * 0.001);
    renderer.render( scene, camera );
    requestAnimationFrame( renderLoop );
})();
<script type="text/javascript" src="https://rawgit.com/mrdoob/three.js/r92/build/three.js"></script>

<style>
  canvas {
    width: 100%;
    height: 100%;
  }

  * {
    margin: 0;
    padding: 0;
    font-family: sans-serif;
  }

  div {
    color: white;
    position: absolute;
    text-align: center;
    width: 100%;
  }
</style>

<div>Click to clear</div>

希望有帮助!

【讨论】:

  • 谢谢,这是一个很好的答案。我同意 BufferGeometry 方法,我会尝试一下。
猜你喜欢
  • 2019-01-28
  • 1970-01-01
  • 2019-09-27
  • 2020-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
  • 2013-10-17
相关资源
最近更新 更多