若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/95938112
目录
前言
OpenGL代码示例
传送门
核心代码
OpenGL效果
OSG渲染树
Osg::StateSet类
OSG渲染
设置渲染属性
设置渲染模式
同时设置渲染属性和模式
OSG二维纹理映射
纹理坐标
OSG实现效果
几何体纹理贴图代码
三角形
四边形
入坑
入坑一:2D纹理贴图未成功
入坑二:2D纹理贴图未成功
入坑三:2D纹理贴图未成功
工程模板:对应版本号1.8.0
《OSG开发笔记(一):OSG介绍、编译》
《OSG开发笔记(二):OSG帮助文档编译》
《OSG开发笔记(三):OSG使用osgQt嵌入Qt应用程序》
《OSG开发笔记(四):OSG不使用osgQt重写类嵌入Qt应用程序》:
《OSG开发笔记(五):OSG场景理解与基础类概述》
《OSG开发笔记(六):OSG内存管理》
《OSG开发笔记(七):OSG复现OpenGL入门示例和OSG坐标系》
《OSG开发笔记(八):OSG模型文件存储与读取》
《OSG开发笔记(九):OSG模型的基本操作之添加/删除、显示/隐藏、开关节点开/关》:
《OSG开发笔记(十):OSG模型的变换之平移、旋转和缩放》
《OSG开发笔记(十一):OSG渲染状态与2D纹理映射》
《OSG开发笔记(十二):OSG基本几何图形、内置几何类型》
《OSG开发笔记(十三):OSG三维纹理映射(体渲染)》
《OSG开发笔记(十四):OSG交互》
《OSG开发笔记(十五):OSG光照》
《OSG开发笔记(十六):OSG视口、相机和视点》
《OSG开发笔记(十七):OSG中的相机移动》
《OSG开发笔记(十八):OSG鼠标拾取pick、拽托球体以及多光源》
《OSG开发笔记(十九):OSG文字显示》
《OSG开发笔记(二十):OSG使用HUD显示文字》
《OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式》
《OSG开发笔记(二十二):OSG场景背景》
《OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪》
《OSG开发笔记(二十四):OSG漫游之平移、转向和低抬头》
《OSG开发笔记(二十五):OSG漫游之CS移动、碰撞检测与跳跃》
《OSG开发笔记(二十六):OSG漫游之上下楼梯》
《OSG开发笔记(二十七):OSG路径漫游之录制播放固定路径动画》
《OSG开发笔记(二十八):OSG模型固定路径动画》
持续补充中…
复现OpenGL纹理贴图的效果。
《OpenGL学习笔记(十二):纹理的使用》:
https://blog.csdn.net/qq21497936/article/details/79184344
OSG中存在两棵树,分别为场景树和渲染树,渲染树是一颗以StateSet和RenderLeaf为节点的树,它可以做到StateSet相同的RenderLeaf同时渲染而不用切换OpenGL状态,并且做到尽量少在多个不同的State间切换。
渲染时,需要在osg::StateSet中设置渲染状态,可以将StateSet关联到场景图形中的任意一个节点Node或关联到Drawable类。
OSG将渲染状态分为2个部分,分别为渲染属性(Attribute)和渲染模式(Mode)。
渲染必须的步骤:
要设置一项属性,首先需要将修改的属性类实例化,设置该类的数值,然后用osg::StateSet::setAttribute()将其关联到StateSet。
示例代码
// 获取StateSet指针
osg::ptr pStateSet = _pGeometry->getOrCreateStateSet();
// 创建并添加CullFace属性类
osg::ptr pCullFace = new osg::CullFace(osg::CullFace::BACK);
pStateSet->setAttribute(pCullFace.get());
用于可以使用osg::StateSet::setMode设置允许或禁止某种模式,例如,打开雾效果模式的许可。
// 获取StateSet指针
osg::ptr pStateSet = _pGeometry->getOrCreateStateSet();
// 允许这个StateSet的雾效果
pStateSet(GL_FOG, osg::StateAttribute::ON);
OSG还提供了一个同时设置属性和渲染模式的单一接口,第一个参数为属性,第二个参数默认为打开功能。
// 获取StateSet指针
osg::ptr pStateSet = _pGeometry->getOrCreateStateSet();
// 设置属性和渲染模式
Osg::ptr pBlendFunc = new osg::BlendFunc;
pStateSet->setAttributeAndModes(pBlendFunc);
纹理映射主要包括:一维纹理、二维纹理、三维纹理、凹凸纹理、多重纹理、Mipmap纹理、压缩纹理和立方纹理等。
OSG全面支持OpenGL的纹理映射机制,为了在程序中实现基本的纹理映射功能,用户的代码需要遵循以下步骤:
用一个二维的向量数组来保存纹理坐标,纹理坐标与定点一一对应
osg::ref_ptr 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 OsgWidget::getWindowDemoNode()
{
osg::ref_ptr pGroop = new osg::Group;
#if 1
{
// 绘制三角形
// 创建一个用户保存几何信息的对象
osg::ref_ptr pGeometry = new osg::Geometry;
// 创建四个顶点的数组
osg::ref_ptr 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 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 texture2D = new osg::Texture2D;
texture2D->setImage(image.get());
// 绑定纹理后,释放内部的ref_ptr
,删除image图像
texture2D->setUnRefImageDataAfterApply(true);
// 创建纹理顶点
osg::ref_ptr 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 pStateSet = new osg::StateSet;
// Texture类关联到渲染状态StateSet
osg::ref_ptr pStateSet = pGeometry->getOrCreateStateSet();
// 将纹理关联给StateSet纹理单元0
pStateSet->setTextureAttributeAndModes(0, texture2D.get(), osg::StateAttribute::ON);
pGeometry->setTexCoordArray(0, pVec2Array.get());
// 为唯一的法线创建一个数组 法线: normal
osg::ref_ptr 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 pGeode = new osg::Geode;
pGeode->addDrawable(pGeometry.get());
pGroop->addChild(pGeode);
}
#endif
return pGroop.get();
}
绑定了颜色的同时贴了纹理。
osg::ref_ptr OsgWidget::getWindowRectDemoNode()
{
osg::ref_ptr pGroop = new osg::Group;
#if 1
{
// 绘制四边形
// 创建一个用户保存几何信息的对象
osg::ref_ptr pGeometry = new osg::Geometry;
// 创建四个顶点的数组
osg::ref_ptr 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 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 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 image = new osg::Image;
image = osgDB::readImageFile(QString("D:/qtProject/osgDemo/osgDemo/modules/osgWidget/image/window.bmp").toStdString());
// 将图片关联到纹理
osg::ref_ptr texture2D = new osg::Texture2D;
texture2D->setImage(image.get());
// 绑定纹理后,释放内部的ref_ptr
,删除image图像
texture2D->setUnRefImageDataAfterApply(true);
// 将纹理关联给StateSet纹理单元0
// 贴图失败
// osg::ref_ptr pStateSet = new osg::StateSet;
osg::ref_ptr pStateSet = pGeometry->getOrCreateStateSet();
pStateSet->setTextureAttributeAndModes(0, texture2D.get());
#endif
// 为唯一的法线创建一个数组 法线: normal
osg::ref_ptr 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 pGeode = new osg::Geode;
pGeode->addDrawable(pGeometry.get());
pGroop->addChild(pGeode);
}
#endif
return pGroop.get();
}
原因:编译的时候没有带jpg插件,是编译osg库时可以带第三方库,笔者没有编译。
解决方法:将图片换bmp,使用osgDB::writeImageFile可以测试。
原因:是设置了StateSet的属性,没有设置mode
解决方法:补上mode
原因:是自己重新new了StateSet
解决方法:需要使用Node::getOrCreateStateSet()。
对应版本号1.8.0
欢迎技术交流和帮助,提供IT相关服务,索要源码请联系博主QQ: 21497936,若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/95938112