【问题标题】:How to efficiently draw lots of objects using Three.js如何使用 Three.js 高效地绘制大量对象
【发布时间】:2016-12-13 05:09:50
【问题描述】:

我是 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>

【问题讨论】:

    标签: three.js webgl


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      维护一组网格并更新它们的属性会更快,而不是每次单击鼠标都创建一组新的几何图形、材料和网格。

      【讨论】:

        【解决方案3】:

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

        为了纯粹的速度,我建议你通过手工编写 OpenGL/WebGL 而不是更高级别的抽象库 Three.js 来学习图形......易用性的代价往往是更高的不必要逻辑的计算负载,可以减少手写的话就出来了

        这是我构建的一个 WebGL 玩具,它没有 Three.js ...它可以实时更新成千上万个对象的几何图形,并使用 Web Audio API 渲染音频
        https://github.com/scottstensland/webgl-3d-animation

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-08-11
          • 1970-01-01
          • 2017-03-21
          • 2012-11-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多