OSG開發筆記(三十四): OsgUtil::Simplifier:簡化幾何體,提升顯示效能和渲染效率

长沙红胖子Qt创微智科發表於2024-11-25

前言

  對於一些較大的圖形,會出現顯示卡頓和渲染緩慢的問題,這時候就要使用到osgUtil::Simplifier簡化器,來對其進行簡化。

Demo

  在這裡插入圖片描述

  在這裡插入圖片描述

  在這裡插入圖片描述

osgUtil

  osgUtil庫是osg的四大核心庫之一,OSG 核心庫提供了用於場景圖形操作的核心場景圖形功能、類和方法;開發3D圖形程式所需的某些特定功能函式和程式設計介面,以及2D和3D檔案I/O的OSG 外掛入口。
  在這裡插入圖片描述
  osgUtil(OSG Utilities)模組提供了場景更新、裁剪、繪製、資料統計等公用工具。

osgUtil::Simplifier:簡化幾何體類

  在這裡插入圖片描述

  OsgUtil::Simplifier 是 OpenSceneGraph (OSG) 庫中的一個工具類,用於簡化幾何圖形。OpenSceneGraph 是一個高效能的場景圖渲染引擎,用於圖形應用程式的開發,比如視覺化、模擬、虛擬現實和遊戲等。OsgUtil::Simplifier 類提供了一種方法來減少場景中的多邊形數量,這在需要最佳化渲染效能或減小場景檔案大小時非常有用。

功能概述

  OsgUtil::Simplifier 的主要功能是簡化幾何體,比如網格(mesh)。它透過移除一些不太重要的頂點或邊來實現這一點,從而減少多邊形的數量。簡化的程度可以透過引數設定來控制,以達到在保持視覺質量的同時減少渲染負載的目的。

使用場景

  • 效能最佳化:在需要渲染大量幾何體時,透過簡化幾何體可以減少GPU的負擔,提高渲染速度。
  • 檔案大小最佳化:簡化後的幾何體可以生成較小的場景檔案,這對於網路傳輸或資源儲存都是有益的。
  • 實時應用:在實時渲染應用中,如虛擬現實或擴增實境,簡化可以幫助保持幀率穩定,提供流暢的使用者體驗。

基本用法

  使用 OsgUtil::Simplifier 通常涉及以下幾個步驟:

  • 建立簡化器例項:建立一個 OsgUtil::Simplifier 的例項。
  • 設定簡化引數:透過配置簡化器的引數(如目標多邊形數量、誤差容限等)來控制簡化的程度。
  • 應用簡化:將需要簡化的幾何體(如 osg::Geometry 或 osg::Node)傳遞給簡化器進行處理。
  • 獲取結果:簡化器處理後會返回簡化後的幾何體,可以將其用於渲染。
      注意事項
  • 視覺質量:雖然簡化可以提高效能,但過度簡化可能會導致視覺質量的顯著下降。因此,需要仔細調整簡化引數以找到效能和質量的平衡點。
  • 資料完整性:簡化過程中可能會修改原始資料,因此在使用前最好保留原始資料的備份。
  • 資源消耗:簡化操作可能需要一定的計算資源,特別是在處理複雜的幾何體時。因此,在實時應用中需要謹慎使用,以避免引入額外的延遲。
      OsgUtil::Simplifier 是 OpenSceneGraph 提供的一個強大工具,可以幫助開發者在不影響視覺體驗的前提下,最佳化渲染效能和資源使用。

osgUtil::Simplifier使用步驟

步驟一:引入標頭檔案

   在這裡插入圖片描述

#include <osgUtil/Simplifier>

步驟二:建立例項,同步設定簡化引數

  在這裡插入圖片描述

// 步驟二:建立例項
double sampleRatio = 0.5f;
double maximumError = 4.0f;
double maximumLength = 0.0f;
osgUtil::Simplifier simplifier = osgUtil::Simplifier(sampleRatio, maximumError, maximumLength); 

步驟三:應用簡化到幾何體

  在這裡插入圖片描述

// 步驟三:設定簡化引數
osg::ref_ptr<osg::Node> pNode2 = (osg::Node*)pNode->clone(osg::CopyOp::DEEP_COPY_ALL);
// 接收報錯:terminate called after throwing an instance of 'std::bad_alloc' what():  std::bad_alloc
//          模型太大,簡化型別時出現記憶體分配錯誤
pNode2->accept(simplifier);

步驟四:使用簡化後的幾何體

  在這裡插入圖片描述

// 移動下,方便對比
osg::ref_ptr<osg::MatrixTransform> pMatrixTransform = new osg::MatrixTransform();
pMatrixTransform->addChild(pNode2);
osg::Matrix matrix = pMatrixTransform->getMatrix();
matrix = matrix * osg::Matrix::translate(0, 3.5, 0);
pMatrixTransform->setMatrix(matrix);
pGroup->addChild(pMatrixTransform);

Demo原始碼

osg::ref_ptr<osg::Node> OsgWidget::getSimplifierNode()
{
    // 其他demo的控制元件
    updateControlVisible(false);

    osg::ref_ptr<osg::Group> pGroup = new osg::Group();

    // 載入支援stl格式外掛
//    osgDB::Registry::instance()->addFileExtensionAlias(".stl", "stl");

    // 載入模型
    {
        osg::ref_ptr<osg::Node> pNode;
        QString filePath = "T:/CVN76.STL";

//        QString filePath = "cow.osg";
        pNode = osgDB::readNodeFile(filePath.toStdString());
        if(!pNode.get())
        {
            LOG << "Failed to openFile:" << filePath;
        }

        pGroup->addChild(pNode);

#if 1
        // 對模型進行簡化
        // 步驟一:新增標頭檔案
//        #include <osgUtil/Simplifier>
        // 步驟二:建立例項
//        double sampleRatio = 0.5f;
//        double sampleRatio = 0.3f;
        double sampleRatio = 0.1f;
        double maximumError = 4.0f;
        double maximumLength = 0.0f;
        osgUtil::Simplifier simplifier = osgUtil::Simplifier(sampleRatio, maximumError, maximumLength);
        // 步驟三:設定簡化引數
        osg::ref_ptr<osg::Node> pNode2 = (osg::Node*)pNode->clone(osg::CopyOp::DEEP_COPY_ALL);
        // 接收報錯:terminate called after throwing an instance of 'std::bad_alloc' what():  std::bad_alloc
        //          模型太大,簡化型別時出現記憶體分配錯誤
        pNode2->accept(simplifier);

        // 移動下,方便對比
        osg::ref_ptr<osg::MatrixTransform> pMatrixTransform = new osg::MatrixTransform();
        pMatrixTransform->addChild(pNode2);
        osg::Matrix matrix = pMatrixTransform->getMatrix();
        matrix = matrix * osg::Matrix::translate(0, 3.5, 0);
        pMatrixTransform->setMatrix(matrix);

        pGroup->addChild(pMatrixTransform);
#endif
    }

    return pGroup.get();
}

工程模板v1.37.0

  在這裡插入圖片描述

入坑

入坑一:應用簡化器的時候崩潰

問題

  應用簡化器的時候崩潰
  在這裡插入圖片描述

原因

  是模型太大,簡化失敗, 因為測試了其他圖形是可以的:
  在這裡插入圖片描述

  崩潰時的cpu、記憶體和gpu佔用率:
  在這裡插入圖片描述

  看到其儲存的檔案達到300MB:
  在這裡插入圖片描述

解決

  可嘗試加大記憶體,因為筆者是mingw32版本的,沒有進行研究了,具體參照文章《關於 Qt執行載入記憶體較大崩潰新增擴大執行記憶體 的解決方法》

相關文章