three.js大型网格渐进式渲染

时间:2018-05-23 16:54:51

标签: javascript performance graphics three.js webgl

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

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

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

我的问题是: 有没有更好的方法来实现这一点,并且之前已经完成了吗? (使用WebGL1,我知道WebGL2遮挡查询会使这个更简单)

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

1 个答案:

答案 0 :(得分:2)

我不相信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>

希望有所帮助!