若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/97614261
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
OSG开发专栏(点击传送门)
上一篇:《OSG开发笔记(二十):OSG使用HUD显示文字》
下一篇:《OSG开发笔记(二十二):OSG场景背景》
前言
前面显示文字抬头显示(HUD),现在将图片和图片纹理也添加进HUD。
目标效果
本章节完,基本扫清达到目标效果的技术障碍。
纹理混合模式
原图
纹理混合模式,2个图形,第一个是纯色,第二个是贴白色纹理。
设置纹理混合模式方法(多重纹理映射,颜色也算一层)
// 设置纹理环境,模式为REPLACE
osg::ref_ptr<osg::TexEnv> pTexEnv=new osg::TexEnv;
pTexEnv->setMode(osg::TexEnv::Mode::REPLACE);
pTexEnv->setColor(osg::Vec4(0.0,0.0,0.0,0.0));
// Texture类关联到渲染状态StateSet
osg::ref_ptr<osg::StateSet> pStateSet = pGeometry->getOrCreateStateSet();
// 将纹理关联给StateSet纹理单元0,同时将纹理环境混合模式关联到纹理单元0
pStateSet->setTextureAttributeAndModes(0, texture2D.get(), osg::StateAttribute::ON);
pStateSet->setTextureAttributeAndModes(0, pTexEnv.get(), osg::StateAttribute::ON);
纹理混合模式
enum Mode {
DECAL = GL_DECAL,
MODULATE = GL_MODULATE,
BLEND = GL_BLEND,
REPLACE = GL_REPLACE,
ADD = GL_ADD
};
枚举效果
代码
HUB绘制两个图形:纯色和纹理
osg::ref_ptr<osg::Node> OsgWidget::getHudTextAndShapeNode()
{
osg::ref_ptr<osg::Group> pGroup = new osg::Group();
osg::ref_ptr<osg::Geode> pGeode = new osg::Geode();
osg::ref_ptr<osgText::Text> pText = 0;
// 步骤一:创建HUD摄像机
osg::ref_ptr<osg::Camera> pCamera = new osg::Camera;
// 步骤二:设置投影矩阵
pCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, 1920, 0, 1080));
// 步骤三:设置视图矩阵,同时确保不被场景中其他图形位置变换影响, 使用绝对帧引用
pCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
pCamera->setViewMatrix(osg::Matrix::identity());
// 步骤四:清除深度缓存
pCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
// 步骤五:设置POST渲染顺序(最后渲染)
pCamera->setRenderOrder(osg::Camera::POST_RENDER);
// 步骤六:设置为不接收事件,始终得不到焦点
pCamera->setAllowEventFocus(false);
// 步骤七:添加文字
{
pText = new osgText::Text();
pText->setFont(osgText::readFontFile("fonts/simsun.ttc"));
QString text = QString("苔原带");
pText->setText(text.toStdString(), osgText::String::ENCODING_UTF8);
pText->setPosition(osg::Vec3f(0, 0, 0));
pText->setCharacterSize(10);
pText->setColor(osg::Vec4f(1.0, 1.0, 1.0, 1.0));
pText->setDrawMode(osgText::Text::TEXT);
pText->setAxisAlignment(osgText::Text::XY_PLANE);
pText->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
pText->setFontResolution(32, 32);
pText->setAlignment(osgText::Text::LEFT_TOP);
pText->setAlignment(osgText::Text::LEFT_CENTER);
pText->setAlignment(osgText::Text::LEFT_BOTTOM);
pText->setLayout(osgText::Text::LEFT_TO_RIGHT);
pText->setBackdropType(osgText::Text::NONE);
pText->setColorGradientMode(osgText::Text::SOLID);
pGeode = new osg::Geode();
osg::ref_ptr<osg::StateSet> pStateSet = pGeode->getOrCreateStateSet();
pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
pStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
pGeode->addDrawable(pText.get());
}
pCamera->addChild(pGeode);
// 步骤八:添加图形-纯色
{
// 绘制四边形
// 创建一个用户保存几何信息的对象
osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
// 创建四个顶点的数组
osg::ref_ptr<osg::Vec3Array> pVec3Array = new osg::Vec3Array;
// 添加四个顶点
pGeometry->setVertexArray(pVec3Array.get());
// 注意:HUD中的XY是正常屏幕坐标,而OSG中Y屏幕向里
pVec3Array->push_back(osg::Vec3( 0.0, 0.0, 0.0));
pVec3Array->push_back(osg::Vec3( 300.0, 0.0, 0.0));
pVec3Array->push_back(osg::Vec3( 300.0, 100.0, 0.0));
pVec3Array->push_back(osg::Vec3( 0.0, 100.0, 0.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(141/255.0, 179/255.0, 222/255.0, 1.0));
pVec4Array->push_back(osg::Vec4(141/255.0, 179/255.0, 222/255.0, 1.0));
pVec4Array->push_back(osg::Vec4(141/255.0, 179/255.0, 222/255.0, 1.0));
pVec4Array->push_back(osg::Vec4(141/255.0, 179/255.0, 222/255.0, 1.0));
// Texture类关联到渲染状态StateSet
osg::ref_ptr<osg::StateSet> pStateSet = pGeometry->getOrCreateStateSet();
// 将纹理关联给StateSet纹理单元0
pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
pStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
// 为唯一的法线创建一个数组 法线: 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->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
// 向Geode类添加几何体(Drawable)
pGeode = new osg::Geode;
pGeode->addDrawable(pGeometry.get());
}
pCamera->addChild(pGeode);
// 步骤九:添加图形-纹理
{
// 绘制四边形
// 创建一个用户保存几何信息的对象
osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
// 创建四个顶点的数组
osg::ref_ptr<osg::Vec3Array> pVec3Array = new osg::Vec3Array;
// 添加四个顶点
pGeometry->setVertexArray(pVec3Array.get());
// 注意:HUD中的XY是正常屏幕坐标,而OSG中Y屏幕向里
pVec3Array->push_back(osg::Vec3( 300.0, 100.0, 0.0));
pVec3Array->push_back(osg::Vec3( 600.0, 100.0, 0.0));
pVec3Array->push_back(osg::Vec3( 600.0, 200.0, 0.0));
pVec3Array->push_back(osg::Vec3( 300.0, 200.0, 0.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(0, 0, 0, 0));
pVec4Array->push_back(osg::Vec4(0, 0, 1, 1));
pVec4Array->push_back(osg::Vec4(0, 0, 0, 1));
pVec4Array->push_back(osg::Vec4(0, 1, 0, 0));
// 读取纹理图片
osg::ref_ptr<osg::Image> pImage = 0;
pImage = osgDB::readImageFile(QString("D:/qtProject/osgDemo/osgDemo/modules/osgWidget/image/iceSheet.jpg").toStdString());
// 将图片关联到纹理
if(!pImage->valid())
{
LOG_WARN(QString("Failed to open image file: %1").arg(QString::fromStdString(pImage->getFileName())));
return 0;
}
osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D;
texture2D->setImage(pImage.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(1.0, 1.0));
pVec2Array->push_back(osg::Vec2(0.0, 1.0));
pGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
// 设置纹理环境(决定是否和原先的颜色融合)
// 设置纹理环境,模式为REPLACE
osg::ref_ptr<osg::TexEnv> pTexEnv=new osg::TexEnv;
// pTexEnv->setMode(osg::TexEnv::Mode::DECAL);
// pTexEnv->setMode(osg::TexEnv::Mode::MODULATE);
// pTexEnv->setMode(osg::TexEnv::Mode::BLEND);
// pTexEnv->setMode(osg::TexEnv::Mode::REPLACE);
pTexEnv->setMode(osg::TexEnv::Mode::ADD);
pTexEnv->setColor(osg::Vec4(1.0,0.0,0.0,1.0));
// Texture类关联到渲染状态StateSet
osg::ref_ptr<osg::StateSet> pStateSet = pGeometry->getOrCreateStateSet();
// 将纹理关联给StateSet纹理单元0
pStateSet->setTextureAttributeAndModes(0, texture2D.get(), osg::StateAttribute::ON);
pStateSet->setTextureAttributeAndModes(0, pTexEnv.get(), osg::StateAttribute::ON);
pGeometry->setTexCoordArray(0, pVec2Array.get());
pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
pStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
// 为唯一的法线创建一个数组 法线: 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->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
// 向Geode类添加几何体(Drawable)
pGeode = new osg::Geode;
pGeode->addDrawable(pGeometry.get());
}
pCamera->addChild(pGeode);
pGroup->addChild(pCamera.get());
return pGroup.get();
}
入坑
入坑一:纹理第一个图形A有颜色后,B绑定纹理有A最后一个点的颜色
解决方法:
设置纹理混合模式为替代。
工程模板:对应版本号1.18.0
对应版本号1.18.0
上一篇:《OSG开发笔记(二十):OSG使用HUD显示文字》
下一篇:《OSG开发笔记(二十二):OSG场景背景》
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/97614261
本文同步分享在 博客“红胖子(AAA红模仿)”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。