3.用三维引擎为球增加颜色(代码+解析)
1.源码
#include <osgViewer/Viewer>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
int main()
{
// 创建一个Viewer对象
osgViewer::Viewer viewer;
// 创建一个用于绘制形状的Geode节点
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
// 创建一个球体,设置其半径为1.0
osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere(osg::Vec3(), 1.0);
// 创建一个ShapeDrawable对象,将球体添加到其中
osg::ref_ptr<osg::ShapeDrawable> shapeDrawable = new osg::ShapeDrawable(sphere.get());
// 设置ShapeDrawable的颜色
shapeDrawable->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0)); // 红色
// 将ShapeDrawable添加到Geode节点
geode->addDrawable(shapeDrawable.get());
// 创建一个纹理对象
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
// 读取纹理图像
osg::ref_ptr<osg::Image> image = osgDB::readImageFile("zyh.jpg");
if (!image)
{
std::cout << "无法读取纹理文件" << std::endl;
return 1;
}
// 将纹理图像设置到纹理对象中
texture->setImage(image.get());
// 创建一个新的状态集
osg::ref_ptr<osg::StateSet> stateSet = new osg::StateSet();
// 将纹理添加到状态集中
stateSet->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON);
// 将状态集设置到Geode节点中
geode->setStateSet(stateSet.get());
// 将Geode节点添加到场景图中
viewer.setSceneData(geode.get());
// 开始渲染循环
return viewer.run();
}
2.说明
2.1综述
在这个示例中,我们添加了一些新的代码来加载和设置纹理。首先,我们创建了一个新的osg::Texture2D
对象,然后使用osgDB::readImageFile
函数从文件中读取纹理图像。然后,我们将图像设置到纹理对象中。
接下来,我们创建了一个新的osg::StateSet
对象,并将纹理添加到其中。最后,我们将状态集设置到Geode节点中。
2.2场景图
我们有一个根节点,它是一个osgViewer::Viewer
对象。这个根节点下面只有一个子节点,即osg::Geode
对象。osg::Geode
对象下面有一个osg::ShapeDrawable
对象,它包含了我们的球体形状。
2.3状态集
至于为什么要使用状态集(osg::StateSet
),这是因为在OpenGL和OSG中,很多渲染属性(如纹理、光照、材质等)都是通过状态集来管理的。你可以把状态集看作是一组OpenGL状态的集合。当OSG在渲染一个节点时,它会首先应用这个节点的状态集,然后再渲染这个节点的所有子节点。这样,我们就可以方便地控制每个节点的渲染属性了。
2.4 setStateSet和addDrawable
关于setStateSet
和addDrawable
的问题,这是因为这两个方法的功能不同。setStateSet
方法是用来设置节点的状态集的,而addDrawable
方法是用来添加可绘制对象的。在我们的示例中,我们首先创建了一个osg::ShapeDrawable
对象,并通过addDrawable
方法将其添加到了osg::Geode
节点中。然后,我们创建了一个osg::StateSet
对象,并通过setStateSet
方法将其设置到了osg::Geode
节点中
2.5 osg::Texture2
osg::Texture2D
是OSG中的一个类,它用来表示二维纹理。在我们的示例中,我们创建了一个osg::Texture2D
对象,并通过osgDB::readImageFile
函数从文件中读取了纹理图像。然后,我们将这个图像设置到了osg::Texture2D
对象中,最后将这个osg::Texture2D
对象添加到了状态集中
2.4场景图中有两个对象?
在这个场景图中,osg::Geode
节点包含了一个osg::ShapeDrawable
对象和一个osg::StateSet
对象。但是,我们通常不会说osg::Geode
节点有两个子节点,因为osg::ShapeDrawable
和osg::StateSet
在OSG中的角色和节点是不同的。
osg::ShapeDrawable
是一个可以绘制的几何形状,它被添加到osg::Geode
节点中,以便在渲染时被绘制出来。osg::StateSet
是一组OpenGL状态的集合,它可以包含诸如纹理、光照、材质等渲染属性。当OSG在渲染一个节点时,它会首先应用这个节点的状态集,然后再渲染这个节点的所有子节点。
所以,虽然osg::Geode
节点包含了osg::ShapeDrawable
和osg::StateSet
这两个对象,但我们通常会说osg::Geode
节点包含了一个osg::ShapeDrawable
对象,并且有一个关联的osg::StateSet
对象。
- 点赞
- 收藏
- 关注作者
评论(0)