three.js大网格渐进式渲染
three.js progressive rendering of large mesh
我想使用 three.js 渲染任意大的静态网格物体。网格可能是 2 GB,有数千万个多边形。
我想将网格几何缓冲区流式传输到 indexedDB 中并逐步读出它们并将它们渲染到屏幕上,同时保持交互式帧速率。我将创建一个 MemoryManager class,确保我们不会通过将数据从 indexedDB 加载到固定大小的缓冲区来使浏览器崩溃。在我的动画循环中,我将在 16 毫秒内渲染尽可能多的几何体,直到用户停止交互,然后不断渲染网格直到没有更多。
这是我想采用的高级方法,当然还有很多优化需要做。 (对象池、八叉树、遮挡查询等)
我的问题是:是否有更好的方法,以前有人做过吗?(使用 WebGL1,我知道 WebGL2 遮挡查询会使这更简单)
此外,自定义 Three.js WebGLRenderer class 的最佳方法是什么?我需要访问私有闭包变量(如 WebGLState )来调整我的用例的性能。
我认为 WebGL2 遮挡查询不会在这里对您有很大帮助。或许可以使用它们,但在 cpu 上进行剔除可能是更好的选择,尤其是当您的场景主要是静态的时候。
如果您想在用户停止交互时逐步渲染几何图形,那么您只需停止清除渲染缓冲区即可。使用 THREE.js,您可以通过在渲染器上启用 preserveDrawingBuffer
并将 autoClear
设置为 false
。
如果相机移动或场景发生其他变化而您需要重新开始,您可以通过调用renderer.clear()
再次清除视图。
关于流式传输数据,我会在每一帧使用 BufferGeometry and modify the necessary BufferAttributes。听起来您已经对优化和决定需要渲染的几何体有了一些想法。
例子
场景在同一帧上一遍又一遍地重绘。单击场景以将其清除并重新开始绘制。重要的js行是NOTE
'
// 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>
希望对您有所帮助!
我想使用 three.js 渲染任意大的静态网格物体。网格可能是 2 GB,有数千万个多边形。
我想将网格几何缓冲区流式传输到 indexedDB 中并逐步读出它们并将它们渲染到屏幕上,同时保持交互式帧速率。我将创建一个 MemoryManager class,确保我们不会通过将数据从 indexedDB 加载到固定大小的缓冲区来使浏览器崩溃。在我的动画循环中,我将在 16 毫秒内渲染尽可能多的几何体,直到用户停止交互,然后不断渲染网格直到没有更多。
这是我想采用的高级方法,当然还有很多优化需要做。 (对象池、八叉树、遮挡查询等)
我的问题是:是否有更好的方法,以前有人做过吗?(使用 WebGL1,我知道 WebGL2 遮挡查询会使这更简单)
此外,自定义 Three.js WebGLRenderer class 的最佳方法是什么?我需要访问私有闭包变量(如 WebGLState )来调整我的用例的性能。
我认为 WebGL2 遮挡查询不会在这里对您有很大帮助。或许可以使用它们,但在 cpu 上进行剔除可能是更好的选择,尤其是当您的场景主要是静态的时候。
如果您想在用户停止交互时逐步渲染几何图形,那么您只需停止清除渲染缓冲区即可。使用 THREE.js,您可以通过在渲染器上启用 preserveDrawingBuffer
并将 autoClear
设置为 false
。
如果相机移动或场景发生其他变化而您需要重新开始,您可以通过调用renderer.clear()
再次清除视图。
关于流式传输数据,我会在每一帧使用 BufferGeometry and modify the necessary BufferAttributes。听起来您已经对优化和决定需要渲染的几何体有了一些想法。
例子
场景在同一帧上一遍又一遍地重绘。单击场景以将其清除并重新开始绘制。重要的js行是NOTE
'
// 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>
希望对您有所帮助!