threejs優化與GPU加速


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 Render() {
    	// 更新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 的獨立顯卡進行渲染任務了。

tips:用threejs做大分辨率下的顯示應用時,需要考慮3D渲染的顯卡性能以及顯卡最大分辨率與顯示屏分辨率的對比情況,如果在做了相關優化之后GPU的占用率仍然偏高,頁面動效卡頓,三維效果不理想,甚至出現有時候因GPU超負荷而是電腦卡死的情況,這時候就需要考慮升級顯卡配置了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM