zoukankan      html  css  js  c++  java
  • three.js 性能优化的几种方法

    本篇介绍three.js性能优化的若干方法。(个人拙见)

    three.js性能优化

    尽量重用Material和Geometry

    这里以Material和Geometry为例(使用比较频繁)

    
    
        for (var i = 0; i < 100; i++) {
            var material = new THREE.MeshBasicMaterial();
            var geometry = new THREE.BoxGeometry(10, 10, 10);
    
            var mesh = new THREE.Mesh(geometry, material);
            scene.add(mesh);
        }
    
    
    

    改为

    
        var material = new THREE.MeshBasicMaterial();
        var geometry = new THREE.BoxGeometry(10, 10, 10);
    
        for (var i = 0; i < 100; i++) {
            var mesh = new THREE.Mesh(geometry, material);
            scene.add(mesh);
        }
    
    
    
    

    谨慎的在render()中操作

    一般FPS为60也就意味着一秒会执行60次如果render()中有有实例化或是赋值操作很容易会崩溃。

    如下:

    
    function render() {
        
        material.map = canvasMap;
        material.map.needsUpdate = true;
        
    }
    
    
    

    选择合适的对象

    • THREE.ParticleSystem(粒子系统)代替THREE.Particle(粒子)
    
        for (var x = -5; x < 5; i++) {
            for (var y = -5; y < 5; y++) {
                var particle = new THREE.Particle(material);
                particle.position.set(x * 10, y * 10, 0);
                scene.add(particle);
            }
        }
    
    
    

    代替

    
        var geometry = new THREE.Geometry();
        var material = new THREE.ParticleBasicMaterial();
    
        for (var x = -5; x < 5; i++) {
            for (var y = -5; y < 5; y++) {
                var particle = new THREE.Vector3(x * 10, y * 10, 0);
                geometry.vertices.push(particle);
            }
        }
    
        var system = new THREE.ParticleSystem(geometry,material);
    
        scene.add(system);
        
    
    • 要操作一组对象时使用 THREE.Object3D
        
        var contain = new THREE.Object3D(); 
    
        var material = new THREE.MeshBasicMaterial();
        var geometry = new THREE.BoxGeometry(10, 10, 10);
    
        for (var i = 0; i < 100; i++) {
            var mesh = new THREE.Mesh(geometry, material);
            contain.add(mesh);
        }
        
        contain.rotation.x = Math.PI/3;
    
    
    
    • 网格合并 THREE.GeometryUtils.merge

    R60

            var geometry = new THREE.BoxGeometry(5, 5, 5);
            var material = new THREE.MeshBasicMaterial({color: 0xff0000});
    
            for (var i = 0; i < 100; i++) {
    
                THREE.GeometryUtils.merge(geometry, new THREE.BoxGeometry(5, 5, 5));
            }
    
            var mesh = new THREE.Mesh(geometry, material);
    
            scene.add(mesh);
    
    
    

    或是一下方式(geometry有位置信息)

            var geometry = new THREE.BoxGeometry(5, 5, 5);
            var material = new THREE.MeshBasicMaterial({color: 0xff0000});
            
            var mesh = new THREE.Mesh(geometry,material);
            mesh.position.set(10,10,10);
            
            var mGeo = new THREE.BoxGeometry(10, 2, 10);
            
            THREE.GeometryUtils.merge(mGeo, mesh);
       
    
            scene.add(new THREE.Mesh(mGeo, material));
    
    
    

    R80 THREE.GeometryUtils.merge() change to geometry.merge()

                var geometry = new THREE.BoxGeometry(2, 4, 2);
                
                var mGeo = new THREE.BoxGeometry(5, 5, 5);
        
                var matrix = new THREE.Matrix4();
        
                for(var i=0;i<100;i++){
        
                    matrix.setPosition(new THREE.Vector3(Math.random()*10,0,Math.random()*10));
                    geometry.merge(mGeo, matrix);
                }
       
        
                var mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({color: 0xff0000}));
                scene.add(mesh);
    
    
    

    使用Web Workers

    web worker 是运行在后台的 JavaScript,它独立于其他脚本,不会影响页面的性能
    我们会发现Physijs物理库就是使用这种方式来保证页面的性能。

    使用之前你可能需要是否支持web worker

    
    if(typeof(Worker)!=="undefined"){}else { }
    
    
    

    我们将web worker运行脚本放在一个js文件中。

    three_workers.js:

        
        // 添加监听事件,从主线程接收数据
        self.addEventListener('message', function(event) {
            
            // 向主线程发送数据
            self.postMessage({
                some_data: '',
                more_data: ''
              })
            })
    
    

    主线程.js:

        
        //新建一个 `Web Workers`
        
        var worker = new Worker('three_workers.js'); 
        
        // 添加监听事件,获取`Web Workers`传回数据 
        worker.addEventListener('message', function (event) { 
        
          var data = event.data;
          
        });
        
        // 向`Web Workers`发送数据
        worker.postMessage({  
          some_data: '',
          more_data: ''
        });
        
        
       
    
    

    可以参照:

    https://threejs.org/examples/?q=sand#raytracing_sandbox

    function timedChunk(items, process, context, callback){
    var todo = items.concat(); //create a clone of the original

    setTimeout(function(){
    
        var start = +new Date();
    
        do {
             process.call(context, todo.shift());
        } while (todo.length > 0 && (+new Date() - start < 50));
    
        if (todo.length > 0){
            setTimeout(arguments.callee, 25);
        } else {
            callback(items);
        }
    }, 25);
    

    }

    分时加载

    可以参照:

    https://www.nczonline.net/blog/2009/08/11/timed-array-processing-in-javascript/

    分时加载算法(大数组)

    调查显示100ms内的响应能让用户感觉非常流畅。50ms是 Nicholas 针对 JavaScript 得出的最佳经验值。

    setTimeout 延时25ms,25ms 保证主流浏览器都顺畅。

    可以使用类似的方法来优化three.js程序。

    
    //Copyright 2009 Nicholas C. Zakas. All rights reserved.
    //MIT Licensed
    
    function timedChunk(items, process, context, callback){
        
        
        var todo = items.concat();   
        
        setTimeout(function(){
            
            var start = +new Date();
            
            
            do {
                 process.call(context, todo.shift());
            } while (todo.length > 0 && (+new Date() - start < 50));
    
            if (todo.length > 0){
                setTimeout(arguments.callee, 25);
            } else {
                callback(items);
            }
        }, 25);
    };
    
    
    

    程序分析见

    使用自定义着色器

    以后会有一篇专门讲着色器

  • 相关阅读:
    BZOJ 3343 教主的魔法 分块
    HDU 3118 Arbiter 判定奇圈
    Atitit. Attilax企业框架 AEF的发展里程总结
    HDU 2009 整除的尾数 题解
    多态的应用《植物大战僵尸》
    Unity3D调用摄像头显示当前拍摄画面
    oracle下session的查询与删除
    为easyUI的dataGrid加入自己的查询框
    JQuery EasyUI Combobox 实现省市二级联动菜单
    hadoop 2.4.1 集群安装二
  • 原文地址:https://www.cnblogs.com/chenjy1225/p/9640562.html
Copyright © 2011-2022 走看看