文章

3.osg之为球增加纹理

1.源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#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对象。

本文由作者按照 CC BY 4.0 进行授权