若该文为原创文章,未经容许不得转载
原博主博客地址: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源创计划”,欢迎正在阅读的你也加入,一块儿分享。