3.用三维引擎为球增加颜色(代码+解析)

举报
无敌清风蓝 发表于 2023/11/30 09:05:05 2023/11/30
【摘要】 1.源码#include <osgViewer/Viewer>#include <osg/Geode>#include <osg/ShapeDrawable>#include <osg/Texture2D>#include <osgDB/ReadFile>int main(){ // 创建一个Viewer对象 osgViewer::Viewer viewer; // 创建一个用于绘制形状的...

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

关于setStateSetaddDrawable的问题,这是因为这两个方法的功能不同。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::ShapeDrawableosg::StateSet在OSG中的角色和节点是不同的。

  • osg::ShapeDrawable是一个可以绘制的几何形状,它被添加到osg::Geode节点中,以便在渲染时被绘制出来。
  • osg::StateSet是一组OpenGL状态的集合,它可以包含诸如纹理、光照、材质等渲染属性。当OSG在渲染一个节点时,它会首先应用这个节点的状态集,然后再渲染这个节点的所有子节点。

所以,虽然osg::Geode节点包含了osg::ShapeDrawableosg::StateSet这两个对象,但我们通常会说osg::Geode节点包含了一个osg::ShapeDrawable对象,并且有一个关联的osg::StateSet对象。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。