若該文爲原創文章,未經容許不得轉載
原博主博客地址: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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。