OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式

Wesley13
• 阅读 1448

若该文为原创文章,未经允许不得转载
原博主博客地址: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。

目标效果

       OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式

       本章节完,基本扫清达到目标效果的技术障碍。

纹理混合模式

原图

       纹理混合模式,2个图形,第一个是纯色,第二个是贴白色纹理。

       OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式

设置纹理混合模式方法(多重纹理映射,颜色也算一层)

// 设置纹理环境,模式为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
};

枚举效果

        OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式

代码

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最后一个点的颜色

解决方法:

       设置纹理混合模式为替代。

       OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式

工程模板:对应版本号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源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
Gif开发笔记(一):gif介绍、编译和工程模板
若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110530966(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fqq21497936%2Fartic
Stella981 Stella981
3年前
Qt开发技术:QCharts(四)QChart面积图介绍、Demo以及代码详解
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fqq21497936)原博主博客导航:https://blog.csdn.net/
Stella981 Stella981
3年前
Keras 时序模型
版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/Thinking\_boy1992/article/details/53207177本文翻译自(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fkeras.io%2Fgettingst
Stella981 Stella981
3年前
OpenCV开发笔记(七十):红胖子带你傻瓜式编译VS2017x64版本的openCV4
若该文为原创文章,未经允许不得转载,经允许后转载请注明原文地址本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107837715(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fqq214
Stella981 Stella981
3年前
Qt开发技术:QCharts(三)QCharts样条曲线图介绍、Demo以及代码详解
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fqq21497936)原博主博客导航:https://blog.csdn.net/
Stella981 Stella981
3年前
Qt开发技术:QtCharts(一)QtCharts基本介绍以及图表框架详解
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fqq21497936)原博主博客导航:https://blog.csdn.net/
Stella981 Stella981
3年前
Mqtt开发笔记:Mqtt服务器搭建
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fqq21497936)原博主博客导航:https://blog.csdn.net/
Stella981 Stella981
3年前
OpenCV开发笔记(四十九):红胖子8分钟带你深入了解轮廓识别(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fqq21497936)原博主博客导航:https://blog.csdn.ne
Stella981 Stella981
3年前
OpenCV开发笔记(四十一):红胖子8分钟带你深入了解scharr滤波器算子边缘检测(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fqq21497936)原博主博客导航:https://blog.csdn.ne