three.js是目前国内开发Web3D应用最多的第三方库,它提供了非常多的3D显示功能。在使用的时候,虽然three.js 本身做了优化,但是在较大分辨率下,加载较大或者较多模型时会出现,帧率会越低,给人感觉就越卡,因此性能方面的优化对提高视觉体验有着积极影响。以下是我在项目(vue+threejs)开发结合度娘总结的一些思路

  1. 合理执行渲染方法

    因为默认情况下requestAnimationFrame()每秒执行60次,如果在里面加个for循环,代码效率就会严重影响,同时还要减少浮点计算,系统对浮点计算开支比较大,尽量写成小数乘法。

    在一些特定的应用中没有必要保持Threejs渲染频率为60FPS,那么可以通过Threejs渲染时间判断来控制Threejs渲染频率,比如设置为30FPS。

    下面代码通过时钟对象.Clock.getDelta()方法获得threejs两帧渲染时间间隔,然后通过时间判断来控制渲染器渲染方法.render()每秒执行次数:

    // 创建一个时钟对象Clock
    var clock = new THREE.Clock();
    // 设置渲染频率为30FBS,也就是每秒调用渲染器render方法大约30次
    var FPS = 30;
    var renderT = 1 / FPS; //单位秒  间隔多长时间渲染渲染一次
    // 声明一个变量表示render()函数被多次调用累积时间
    // 如果执行一次renderer.render,timeS重新置0
    var timeS = 0;
    function render() {
      requestAnimationFrame(render);
      //.getDelta()方法获得两帧的时间间隔
      var T = clock.getDelta();
      timeS = timeS + T;
      // requestAnimationFrame默认调用render函数60次,通过时间判断,降低renderer.render执行频率
      if (timeS > renderT) {
        // 控制台查看渲染器渲染方法的调用周期,也就是间隔时间是多少
        console.log(`调用.render时间间隔`,timeS*1000+'毫秒');
        renderer.render(scene, camera); //执行渲染操作
        ...
        //renderer.render每执行一次,timeS置0
        timeS = 0;
      }
    }
    render();

  2. 共享几何体和材质

    不同的网格模型如果可以共享几何体或材质,最好采用共享的方式,如果两个网格模型无法共享几何体或材质,自然不需要共享,比如两个网格模型的材质颜色不同,这种情况下,一般要分别为网格模型创建一个材质对象

    相同或者相似类型的对象生成时多使用clone()方法,例如生成多个类似的立方体,推荐使用group,结合clone()方法,代码如下

    const group = new THREE.Group()
    const bar = new THREE.Mesh(barGeo, material)
    bar.scale.set(0.3, 0.3, 0.3)
    for (let i = 0; i < 80; i++) {
        const cBar = bar.clone()
        group.add(cBar)
    }

  3. 使用性能检测插件(stats.js)监测页面性能
    // 引入stats.js
    import Stats from 'three/examples/js/libs/stats.min.js'
    const stats = new Stats()
    // 设置stats样式
    stats.dom.style.position = 'absolute';
    stats.dom.style.top = '0px';
    document.body.appendChild(stats.dom);

    在渲染函数中需要添加如下代码:

    function Animate() {
        requestAnimationFrame(Animate);
        Render();
    }
    function 4() {
      // 更新stats
        stats.update();
        render.render(scene,camera);
    }

  4. 对粒子群进行转换,而不是每个粒子

    使用THREE.Sprite时,可以更好地控制单个粒子,但是当使用大量的粒子的时候,这个方法的性能会降低,并且会更复杂。此时可以使用THREE.SpriteCloud,可以轻松地管理大量的粒子,进行整体操作,此时对单个粒子的控制能力会减弱。

  5. 模型的面越少越好,模型过于细致会增加渲染开销

    three场景导入模型时,可以在保证最低清晰度的时候,降低模型的复杂度,面越多,模型越大,加载所需开销就越大

  6. 分时加载

    调查显示100ms内的响应能让用户感觉非常流畅。50ms是 Nicholas 针对 JavaScript 得出的最佳经验值,setTimeout 延时25ms,25ms 保证主流浏览器都顺畅,可以使用类似的方法来优化three.js程序。

    初始化方法以及渲染方法可以适当添加延时以分散同时渲染的压力。

    当存在多个模型动画时,根据实际情况可以将多个动画拆分,再可以对每个动画requestAnimationFrame分别设置渲染频率。

  7. 页面销毁时手动调用dispose方法,清除延时
    beforeDestroy () {
      clearTimeout()
      try {
        this.scene.clear()
        this.renderer.dispose()
        this.renderer.forceContextLoss()
        this.renderer.content = null
        // cancelAnimationFrame(animationID) // 去除animationFrame
        const gl = this.renderer.domElement.getContext('webgl')
        gl && gl.getExtension('WEBGL_lose_context').loseContext()
      } catch (e) {
        console.log(e)
      }
    }

    一个网格模型Mesh是包含几何体geometry和材质对象Material的,几何体geometry本质上就是顶点数据,Three.js通过WebGL渲染器解析几何体的时候会调用WebGL API创建顶点缓冲区来存储顶点数据。

    如果仅仅执行scene.remove(Mesh)只是把网格模型从场景对象的.children属性中删除,解析网格模型Mesh几何体的顶点数据通过WebGL API创建的顶点缓冲区占用的内存并不会释放。

    从内存中删除对象或者删除几何体时不要忘记调用以下方法,因为可能导致内存泄漏

    geometry.dispose() // 删除几何体

    material.dispose() // 删除材质

  8. 加载/渲染时间长的添加loading效果

    当加载较大模型或者渲染比较复杂的模型时,页面会有较长时间卡顿,影响用户体验。可以添加loading效果,降低用户等待焦虑。

  9. 渲染3D的显卡建议设置为独立显卡

    在性能和功耗方面,集成显卡具有一般性能的特点,但基本可以满足一些日常应用,与独立显卡相比,热功耗低。虽然独立显卡的性能很强,但其热量和功耗都比较高。独立显卡在三维性能上优于集成显卡。

  10. 修改浏览器GUP加速相关设置
    Chrome浏览器:
    chrome://flags/#enable-gpu-rasterization   GPU rasterization  设置为Enabled
    
    chrome://flags/#ignore-gpu-blocklist  Override software rendering list 设置为Enabled
    
    chrome://flags/#enable-zero-copy    Zero-copy rasterizer   设置为Enabled
    
    Firefox浏览器:

    要想GPU加速文本的功能,不仅仅要下载最新的nightlyBuild火狐(Minefield)之外,还要通过以下方法操作才能开启该功能:

    1. 进入about:config配置页面并搜索gfx.font

    2. 双击gfx.font_rendering.directwrite.enabled打开这项功能;

    3. 点右键新建一个integer,命名为mozilla.widget.render-mode;

    4. 为该integer赋值为6;

    5. 重启浏览器。

    Edge(win10)浏览器:
    1. 使用 Windows + I 快捷键打开「Windows 设置」——导航到「系统」——「显示」选项页

    2. 点击「多显示器设置」下的「图形设置」链接,打开「图形设置」专属配置页面

    3. 在「图形性能首选项」的下拉列表中选择「通用应用」——再在「选择应用」下拉列表中添加 Microsoft Edge 浏览器。

    4. 添加好之后点击已添加的 Microsoft Edge,再点击「选项」按钮

    5. 在弹出的「图形规格」选项卡中可以看到当前系统中的所有显卡,选择「高性能」并「保存」即可指定 Microsoft Edge 永久使用使用性能最高的 GPU。

    6. 完成上述操作步骤后,再重新启动下 Microsoft Edge,它现在就应该会使用 PC 的独立显卡进行渲染任务了。

three.js
JavaScript 3D Library.

推荐内容
阅读全文
AI总结
GitHub 加速计划 / th / three.js
6
1
下载
JavaScript 3D Library.
最近提交(Master分支:21 天前 )
4e3db421 see https://github.com/mrdoob/three.js/pull/30862#discussion_r2034041690 1 天前
075e1c9a * WebGPU: Make material.transparent behave as in WebGL * cleanup --------- Co-authored-by: sunag <sunagbrasil@gmail.com> 2 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐