OSG開發筆記(十一):OSG渲染狀態與2D紋理映射

若該文爲原創文章,未經容許不得轉載
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:http://www.javashuo.com/article/p-wxwjppoc-mo.html
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/95938112
各位讀者,知識無窮而人力有窮,要麼改需求,要麼找專業人士,要麼本身研究數組

紅胖子(紅模仿)的博文大全:開發技術集合(包含Qt實用技術、樹莓派、三維、OpenCV、OpenGL、ffmpeg、OSG、單片機、軟硬結合等等)持續更新中...(點擊傳送門)oop

OSG開發專欄(點擊傳送門)

上一篇:OSG開發筆記(十):OSG模型的變換之平移、旋轉和縮放學習

下一篇:OSG開發筆記(十二):OSG基本幾何圖形、內置幾何類型測試

 

前言

       復現OpenGL紋理貼圖的效果。spa

 

OpenGL代碼示例

傳送門

       《OpenGL學習筆記(十二):紋理的使用》:.net

          https://blog.csdn.net/qq21497936/article/details/79184344插件

核心代碼

        

OpenGL效果

        

 

OSG渲染樹

       OSG中存在兩棵樹,分別爲場景樹和渲染樹,渲染樹是一顆以StateSet和RenderLeaf爲節點的樹,它能夠作到StateSet相同的RenderLeaf同時渲染而不用切換OpenGL狀態,而且作到儘可能少在多個不一樣的State間切換。指針

Osg::StateSet類

       渲染時,須要在osg::StateSet中設置渲染狀態,能夠將StateSet關聯到場景圖形中的任意一個節點Node或關聯到Drawable類。code

       OSG將渲染狀態分爲2個部分,分別爲渲染屬性(Attribute)和渲染模式(Mode)。orm

  • 渲染屬性:控制渲染特性的狀態變量,如霧的顏色。
  • 渲染模式:設置模式量以容許或禁用某個功能,如紋理映射、燈光等。

OSG渲染

        渲染必須的步驟:

  • 爲將要設置狀態的Node和Drawable對象提供一個StateSet實例。
  • 在StateSet實例中設置狀態的渲染模式和渲染屬性。

設置渲染屬性

       要設置一項屬性,首先須要將修改的屬性類實例化,設置該類的數值,而後用osg::StateSet::setAttribute()將其關聯到StateSet。

示例代碼

// 獲取StateSet指針
osg::ptr<osg::StateSet> pStateSet = _pGeometry->getOrCreateStateSet();
// 建立並添加CullFace屬性類
osg::ptr<osg::CullFace> pCullFace = new osg::CullFace(osg::CullFace::BACK);
pStateSet->setAttribute(pCullFace.get());

設置渲染模式

       用於可使用osg::StateSet::setMode設置容許或禁止某種模式,例如,打開霧效果模式的許可。

// 獲取StateSet指針
osg::ptr<osg::StateSet> pStateSet = _pGeometry->getOrCreateStateSet();
// 容許這個StateSet的霧效果
pStateSet(GL_FOG, osg::StateAttribute::ON);

同時設置渲染屬性和模式

       OSG還提供了一個同時設置屬性和渲染模式的單一接口,第一個參數爲屬性,第二個參數默認爲打開功能。

// 獲取StateSet指針
osg::ptr<osg::StateSet> pStateSet = _pGeometry->getOrCreateStateSet();
// 設置屬性和渲染模式
Osg::ptr<Osg::BlendFunc> pBlendFunc = new osg::BlendFunc;
pStateSet->setAttributeAndModes(pBlendFunc);

 

OSG二維紋理映射

       紋理映射主要包括:一維紋理、二維紋理、三維紋理、凹凸紋理、多重紋理、Mipmap紋理、壓縮紋理和立方紋理等。

       OSG全面支持OpenGL的紋理映射機制,爲了在程序中實現基本的紋理映射功能,用戶的代碼須要遵循如下步驟:

  • 指定用戶幾何體的紋理座標
  • 建立紋理屬性對象並保存紋理圖形數據
  • 爲StateSet設置合適的紋理屬性和模式

紋理座標

       用一個二維的向量數組來保存紋理座標,紋理座標與定點一一對應

    

osg::ref_ptr<osg::Vec2Array> pVec2Array = new osg::Vec2Array;
pVec2Array->push_back(osg::Vec2(0.0, 0.0));
pVec2Array->push_back(osg::Vec2(1.0, 0.0));
pVec2Array->push_back(osg::Vec2(0.5, 1.0));

       注意:紋理座標老是綁定到每一個頂點的。

OSG實現效果

        

 

幾何體紋理貼圖代碼

三角形

osg::ref_ptr<osg::Node> OsgWidget::getWindowDemoNode()
{
    osg::ref_ptr<osg::Group> pGroop = new osg::Group;
#if 1
    {
        // 繪製三角形
        // 建立一個用戶保存幾何信息的對象
        osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
        // 建立四個頂點的數組
        osg::ref_ptr<osg::Vec3Array> pVec3Array = new osg::Vec3Array;
        // 添加四個頂點
        pGeometry->setVertexArray(pVec3Array.get());
        //          OPENGL的座標系:X正方向向右,Y正方向朝上,Z正方向朝裏
        //                     OpenGL中  x     y     z
        //          OSG的座標系:X正方向向右,Y正方向朝裏,Z正方向朝上
        //                     Osg中     x     y     z
        pVec3Array->push_back(osg::Vec3(-3.0, 0.0, 0.0));
        pVec3Array->push_back(osg::Vec3(-1.0, 0.0, 0.0));
        pVec3Array->push_back(osg::Vec3(-2.0, 0.0, 10.0));

        // 讀取紋理圖片
        osg::ref_ptr<osg::Image> image = new osg::Image;
        image = osgDB::readImageFile(QString("D:/qtProject/osgDemo/osgDemo/modules/osgWidget/image/window.bmp").toStdString());
        // 將圖片關聯到紋理
        if(!image->valid())
        {
            LOG_WARN(QString("Failed to open image file: %1").arg(QString::fromStdString(image->getFileName())));
            return 0;
        }
        osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D;
        texture2D->setImage(image.get());
        // 綁定紋理後,釋放內部的ref_ptr<Image>,刪除image圖像
        texture2D->setUnRefImageDataAfterApply(true);
        // 建立紋理頂點
        osg::ref_ptr<osg::Vec2Array> pVec2Array = new osg::Vec2Array;
        //                      紋理單元號
        pVec2Array->push_back(osg::Vec2(0.0, 0.0));
        pVec2Array->push_back(osg::Vec2(1.0, 0.0));
        pVec2Array->push_back(osg::Vec2(0.5, 1.0));
        // 貼圖失敗
//        osg::ref_ptr<osg::StateSet> pStateSet = new osg::StateSet;
        // Texture類關聯到渲染狀態StateSet
        osg::ref_ptr<osg::StateSet> pStateSet = pGeometry->getOrCreateStateSet();
        // 將紋理關聯給StateSet紋理單元0
        pStateSet->setTextureAttributeAndModes(0, texture2D.get(), osg::StateAttribute::ON);
        pGeometry->setTexCoordArray(0, pVec2Array.get());


        // 爲惟一的法線建立一個數組    法線: normal
        osg::ref_ptr<osg::Vec3Array> pVec3ArrayNormal = new osg::Vec3Array;
        pGeometry->setNormalArray(pVec3ArrayNormal.get());
        pGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
        pVec3ArrayNormal->push_back(osg::Vec3(0.0, -1.0, 0.0));
        // 由保存的數據繪製四個頂點的多邊形
        pGeometry->setStateSet(pStateSet);
        pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, 3));
        // 向Geode類添加幾何體(Drawable)
        osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;
        pGeode->addDrawable(pGeometry.get());
        pGroop->addChild(pGeode);
    }
#endif
    return pGroop.get();
}

四邊形

       

       綁定了顏色的同時貼了紋理。

osg::ref_ptr<osg::Node> OsgWidget::getWindowRectDemoNode()
{
    osg::ref_ptr<osg::Group> pGroop = new osg::Group;
#if 1
    {
        // 繪製四邊形
        // 建立一個用戶保存幾何信息的對象
        osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;

        // 建立四個頂點的數組
        osg::ref_ptr<osg::Vec3Array> pVec3Array = new osg::Vec3Array;
        // 添加四個頂點
        pGeometry->setVertexArray(pVec3Array.get());
        //
        //                               x     y     z
        pVec3Array->push_back(osg::Vec3( 1.0, 0.0, 0.0));
        pVec3Array->push_back(osg::Vec3( 3.0, 0.0, 0.0));
        pVec3Array->push_back(osg::Vec3( 3.0, 0.0, 3.0));
        pVec3Array->push_back(osg::Vec3( 1.0, 0.0, 3.0));
        // 注意:此處若不綁定畫筆,則表示使用以前綁定的畫筆

        // 建立四種顏色的數據
        osg::ref_ptr<osg::Vec4Array> pVec4Array = new osg::Vec4Array;
        // 添加四種顏色
        pGeometry->setColorArray(pVec4Array.get());
        // 綁定顏色
        pGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
        pVec4Array->push_back(osg::Vec4(1.0, 0.0, 0.0, 1.0));
        pVec4Array->push_back(osg::Vec4(0.0, 1.0, 0.0, 1.0));
        pVec4Array->push_back(osg::Vec4(0.0, 0.0, 1.0, 1.0));
        pVec4Array->push_back(osg::Vec4(1.0, 1.0, 1.0, 1.0));

#if 1

        // 爲紋理建立數組
        osg::ref_ptr<osg::Vec2Array> pVec2Array = new osg::Vec2Array;
        //                      紋理單元號
        pVec2Array->push_back(osg::Vec2(0.0, 0.0));
        pVec2Array->push_back(osg::Vec2(1.0, 0.0));
        pVec2Array->push_back(osg::Vec2(1.0, 1.0));
        pVec2Array->push_back(osg::Vec2(0.0, 1.0));
        // Texture類關聯到渲染狀態StateSet
        pGeometry->setTexCoordArray(0, pVec2Array.get());


        // 讀取紋理圖片
        osg::ref_ptr<osg::Image> image = new osg::Image;
        image = osgDB::readImageFile(QString("D:/qtProject/osgDemo/osgDemo/modules/osgWidget/image/window.bmp").toStdString());
        // 將圖片關聯到紋理
        osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D;
        texture2D->setImage(image.get());
        // 綁定紋理後,釋放內部的ref_ptr<Image>,刪除image圖像
        texture2D->setUnRefImageDataAfterApply(true);
        // 將紋理關聯給StateSet紋理單元0
        // 貼圖失敗
//        osg::ref_ptr<osg::StateSet> pStateSet = new osg::StateSet;
        osg::ref_ptr<osg::StateSet> pStateSet = pGeometry->getOrCreateStateSet();
        pStateSet->setTextureAttributeAndModes(0, texture2D.get());
#endif

        // 爲惟一的法線建立一個數組    法線: normal
        osg::ref_ptr<osg::Vec3Array> pVec3ArrayNormal = new osg::Vec3Array;
        pGeometry->setNormalArray(pVec3ArrayNormal.get());
        pGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
        pVec3ArrayNormal->push_back(osg::Vec3(0.0, -1.0, 0.0));
//        pVec3ArrayNormal->push_back(osg::Vec3(0.0,  1.0, 0.0));
        // 由保存的數據繪製四個頂點的多邊形
        pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
        // 向Geode類添加幾何體(Drawable)
        osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;
        pGeode->addDrawable(pGeometry.get());
        pGroop->addChild(pGeode);
    }
#endif
    return pGroop.get();
}

 

入坑

入坑一:2D紋理貼圖未成功

        緣由:編譯的時候沒有帶jpg插件,是編譯osg庫時能夠帶第三方庫,筆者沒有編譯。

        解決方法:將圖片換bmp,使用osgDB::writeImageFile能夠測試。

入坑二:2D紋理貼圖未成功

        緣由:是設置了StateSet的屬性,沒有設置mode

        解決方法:補上mode

入坑三:2D紋理貼圖未成功

        緣由:是本身從新new了StateSet

        解決方法:須要使用Node::getOrCreateStateSet()。

工程模板:對應版本號1.8.0

        對應版本號1.8.0

 

上一篇:OSG開發筆記(十):OSG模型的變換之平移、旋轉和縮放

下一篇:OSG開發筆記(十二):OSG基本幾何圖形、內置幾何類型

 

原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:http://www.javashuo.com/article/p-wxwjppoc-mo.html
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/95938112

本文同步分享在 博客「紅胖子(AAA紅模仿)」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索