1.材质类
材质类 (osg::Material)继承自osg::StateAttribute 类。osg::Material 封装了 OpenGL的 glMaterial()和glColorMaterial()指令的函数功能,其继承关系图如图5-27 所示。
图 5-27 osg::Material 的继承关系图
在场景中设置节点的材质属性,首先要创建一个osg::Material 对象,然后设置颜色和其他参数,再关联到场景图形的StateSet 中,如下面的代码:
- osg::StateSet* state = node->getOrCreateStateSet();
- osg::ref_ptr<osg::Material> mat = new osg::Material;
- state->setAttribute(mat.get());
osg::Material类包含的主要属性如下
- bool _ambientFrontAndBack;// 前面与后面的环境光
- Vec4 _ambientFront; // 前面的环境光,r、g、b、w
- Vec4 _ambientBack; // 后面的环境光,r、g、b、w
- bool _diffuseFrontAndBack;// 前面与后面的漫射光
- Vec4 _diffuseFront;// 前面的漫射光,r、g、b、w
- Vec4 _diffuseBack: // 后面的漫射光,r、g、b、w
- bool _specularFrontAndBack;// 前面与后面的镜面光
- Vec4 _specularFront;//前面的镜面光,r、g、b、w
- Vec4 _specularBack;//后面的镜面光,r、g、b、w
- bool _emissionFrontAndBack;// 前面与后面的发射光(emission)
- Vec4 _emissionFront; // 前面的emission,r、g、b、w
- Veo4 _emissionBack: // 后面的emission,r、g、b、w
- bool _shininessFrontAndBack;// 前面与后面的发光(shininess)
- float _shininessFront:// 前面的shininess
- float _shinincssBack; // 后面的shininess
- 注意:shininess是一个在0~128.0之间的值,值越大,亮点越小、越亮。
OSG材质的面如下:
- enum Face
- {
- FRONT=GL_FRONT,//前
- BACK=GL_BACK,//后
- FRONT_AND_BACK=GL_FRONT_AND_BACK/前、后
- }
OSG材质的颜色模式如下:
- enum ColorMode
- {
- AMBIENT = GL_AMBIENT, //环境光颜色
- DIFFUSE = GL_DIFFUSE, //漫射光颜色
- SPECULAR = GL_SPECULAR, //镜面光颜色
- EMISSION = GL_EMISSION, //发射光颜色
- AMBIENT_AND_DIFFUSE=GL_AMBIENT_AND_DIFFUSE,// 环境与漫射光颜色
- OFF // 关闭模式
- }
在进行很多 OpenGL的操作时,直接设置材质属性可能会过于耗费资源,而OSG提供了一种颜色跟踪材质的高效方法,操作比直接修改材质属性的效率更高,颜色跟踪材质 (color material)允许用户程序通过改变当前颜色的方法,自动改变某一特定的材质属性。在许多情形下,这一操作比直接修改材质属性的效率要高,能加强光照场景和无光照场景的联系,并满足应用程序对材质的需要。
允许颜色跟踪材质的特性需要调用 setColorMode()方法。osg::Material类为之定义了枚举量AMBIENT、DIFFUSE、SPECULAR、EMISSION、AMBIENT_AND_DIFFUSE 以及 OFF。默认情况下,颜色跟踪模式被设置为 OFF,颜色跟踪材质被禁止。如果用户程序设置颜色跟踪模式为其他的值,那么OSG 将为特定的材质属性开启颜色跟踪材质特性,此时主颜色的改变将会改变相应的材质属性。第5.4.2节的代码段将允许颜色跟踪材质,此时几何体正面的环境材质和散射材质颜色将自动跟踪当前颜色的改变而改变。
- 注意:根据颜色跟踪模式的取值不同,Material 类会自动允许或禁止GL_COLOR_MATERIAL,因此,用户程序不需要调用setAttributeAndModes()来允许或禁止相关的模式值。
2.材质类示例
材质类(osg::Material)示例的代码如程序清单5-14 所示。
1. osg::ref_ptr<osg::Node> createNode_5_14() // 创建一个四边形节点
2. {
3. osg::ref_ptr<osg::Geode> geode = new osg::Geode();
4.
5. osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
6.
7. // 设置顶点
8. osg::ref_ptr<osg::Vec3Array> vc = new osg::Vec3Array();
9. vc->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
10. vc->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
11. vc->push_back(osg::Vec3(1.0f, 0.0f, 1.0f));
12. vc->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
13. geom->setVertexArray(vc.get());
14.
15. // 设置纹理坐标
16. osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array();
17. vt->push_back(osg::Vec2(0.0f, 0.0f));
18. vt->push_back(osg::Vec2(1.0f, 0.0f));
19. vt->push_back(osg::Vec2(1.0f, 1.0f));
20. vt->push_back(osg::Vec2(0.0f, 1.0f));
21. geom->setTexCoordArray(0, vt.get());
22.
23. // 设置法线
24. osg::ref_ptr<osg::Vec3Array> nc = new osg::Vec3Array();
25. nc->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
26. geom->setNormalArray(nc.get());
27. geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
28. geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4)); // 添加图元
29. geode->addDrawable(geom.get()); // 绘制
30.
31. return geode.get();
32. }
33.
34. void material_5_14()
35. {
36. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
37. osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
38. traits->x = 40;
39. traits->y = 40;
40. traits->width = 600;
41. traits->height = 480;
42. traits->windowDecoration = true;
43. traits->doubleBuffer = true;
44. traits->sharedContext = 0;
45.
46. osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
47. osg::ref_ptr<osg::Camera> camera = new osg::Camera;
48. camera->setGraphicsContext(gc.get());
49. camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
50. GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
51. camera->setDrawBuffer(buffer);
52. camera->setReadBuffer(buffer);
53. viewer->addSlave(camera.get());
54. osg::ref_ptr<osg::Group> root = new osg::Group();
55.
56. osg::ref_ptr<osg::Node> node = createNode_5_14();
57.
58. // 得到状态属性
59. osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
60. stateset = node->getOrCreateStateSet();
61.
62. // 创建材质对象
63. osg::ref_ptr<osg::Material> mat = new osg::Material();
64. mat->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); // 设置正面散射颜色
65. mat->setSpecular(osg::Material::FRONT, osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); // 设置正面镜面颜色
66. mat->setShininess(osg::Material::FRONT, 90.0f); // 设置正面指数
67. stateset->setAttribute(mat.get());
68.
69. // 设置背面剔除
70. osg::ref_ptr<osg::CullFace> cullface = new osg::CullFace(osg::CullFace::BACK);
71. stateset->setAttribute(cullface.get());
72. stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
73. root->addChild(node.get());
74.
75. // 优化场景数据
76. osgUtil::Optimizer optimizer;
77. optimizer.optimize(root.get());
78. viewer->setSceneData(root.get());
79. viewer->realize();
80. viewer->run();
81. }
运行程序,截图如图5-28所示。
图5-28 材质类示例截图