如何使用Three.js有效地绘制大量对象

时间:2014-04-05 09:44:12

标签: three.js webgl

我是WebGL和Three.js的新手。我试图想象一下大的圆网格一次改变颜色。

当我增加实例数时,它会明显变慢,更新需要几秒钟。有什么改进我的代码的建议?我可以一次更新4000个圈子吗?

这是我现有的实施:

<html>
    <head>
        <title>My first Three.js app</title>
        <style></style>
    </head>
    <body>
        <script src="./three.js"></script>
        <script>
        var ROWS = 40
        var COLS = 100
        var SEGMENTS = 10;

        var windowWidth = window.innerWidth, windowHeight = window.innerHeight;

        var camera, scene, renderer;
        var group, text, plane;

        function init() {
            // create and append container/canvas
            container = document.createElement( 'div' );
            document.body.appendChild( container );

            // create camera    
            camera = new THREE.PerspectiveCamera(100, windowWidth / windowHeight, 0.1, 1000 );
            // set position of camera
            camera.position.z = 500;
            camera.position.x = windowWidth/2
            camera.position.y = windowHeight/2

            // Create a scene
            scene = new THREE.Scene();


            renderer = new THREE.CanvasRenderer();
            renderer.setClearColor( 0xf0f0f0 );
            renderer.setSize( windowWidth, windowHeight );
            renderer.sortElements = false;
            container.appendChild( renderer.domElement );

            document.addEventListener( 'mousedown', onDocumentMouseDown, false );
        }

        function addCircle(color, x, y, z, s , radius) {    
            var geometry = new THREE.CircleGeometry(radius, SEGMENTS, SEGMENTS)
            var material = new THREE.MeshBasicMaterial( { color: color, overdraw: true } );

            var mesh = new THREE.Mesh( geometry, material );
            mesh.position.set( x, y, z );
            mesh.scale.set( s, s, s );
            scene.add( mesh );
        }

        function toHex(d) {
            var valueStr = d.toString(16); 
            valueStr = valueStr.length < 2 ? "0"+valueStr : valueStr; 
            var fillColor = "0x00" + valueStr + "00"; 
            return parseInt(fillColor);
        }

        function drawData(data) {
            var rows = data.length;
            var cols = data[0].length;

            distanceBetweenCircles = Math.min(windowWidth/(cols), windowHeight/(rows));
            var radius = distanceBetweenCircles/2.0

            for(var i = 0; i < data.length; i++) {
                for (var j = 0; j < data[0].length; j++) {
                    var color = toHex(data[i][j])
                    var x = distanceBetweenCircles*j - radius
                    var y = distanceBetweenCircles*i - radius
                    addCircle( color, x, y, 0, 1 , radius-3);
                }
            }
        }

        function newData(){
            var newData = []
            for (var i = 0; i < ROWS; i++) {
                var row = [];
                for (var j = 0; j < COLS; j ++) {
                    row.push(Math.floor(Math.random()*255));
                }
                newData.push(row);
            }
            return newData;
        }

        function onDocumentMouseDown ( event ) {
            event.preventDefault();

            // Update circles 
            var randomData = newData()
            drawData(randomData);
        }

        var render = function() {
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

        init(); 
        render();
        </script>
    </body>
</html>

3 个答案:

答案 0 :(得分:0)

要将CircleGeometry对象添加到场景,需要将圆圈绘制。将圆形图像/纹理添加到场景中需要将圆圈打印,可以这么说。

乘以4000,绘图变得相当昂贵。

答案 1 :(得分:0)

维护网格数组并更新其属性会更快,而不是每次鼠标点击都会创建一组新的几何,材质和网格。

答案 2 :(得分:-1)

内存管理在软件设计中非常重要。您引入的每个变量都有成本,特别是那些实例化会在某些API调用后调用一系列分配的变量。这是使用像THREE这样的分层的缺点,它隐藏了复杂性,但也隐藏了使用他们的呼叫的后果。没有避免THREE并且自己完成所有WebGL管道(在忽略管道并且只使用像THREE这样的垫片之前总是很好的第一步),做一些功课来确定在调用任何API时创建的内容,例如三。撕掉内部循环变量创建对象,这些对象应该在调用之间重用。对于您的问题,是的,一旦您的架构经过仔细考虑,您可以轻松地在每个动画事件循环时间片上更新4000个圆圈,尤其是如果您使用着色器来制作对象并避免在CPU中进行此类计算

对于纯粹的速度,我建议您通过手工编写OpenGL / WebGL而不是更高级别的抽象库Three.js来学习图形...易于使用的价格往往是更高的计算负荷,可以减少不必要的逻辑如果用手写的话

这是我制作的一个没有Three.js的WebGL玩具......它可以实时更新数十个对象的10个几何体,并使用Web Audio API渲染音频 https://github.com/scottstensland/webgl-3d-animation