????????材质类 (osg::Material)继承自osg::StateAttribute 类。osg::Material 封装了 OpenGL的 glMaterial()和glColorMaterial()指令的函数功能,其继承关系图如图5-27 所示。
图 5-27 ?osg::Material 的继承关系图
?
????????在场景中设置节点的材质属性,首先要创建一个osg::Material 对象,然后设置颜色和其他参数,再关联到场景图形的StateSet 中,如下面的代码:
????????osg::Material类包含的主要属性如下
????????OSG材质的面如下:
????????OSG材质的颜色模式如下:
????????在进行很多 OpenGL的操作时,直接设置材质属性可能会过于耗费资源,而OSG提供了一种颜色跟踪材质的高效方法,操作比直接修改材质属性的效率更高,颜色跟踪材质 (color material)允许用户程序通过改变当前颜色的方法,自动改变某一特定的材质属性。在许多情形下,这一操作比直接修改材质属性的效率要高,能加强光照场景和无光照场景的联系,并满足应用程序对材质的需要。
????????允许颜色跟踪材质的特性需要调用 setColorMode()方法。osg::Material类为之定义了枚举量AMBIENT、DIFFUSE、SPECULAR、EMISSION、AMBIENT_AND_DIFFUSE 以及 OFF。默认情况下,颜色跟踪模式被设置为 OFF,颜色跟踪材质被禁止。如果用户程序设置颜色跟踪模式为其他的值,那么OSG 将为特定的材质属性开启颜色跟踪材质特性,此时主颜色的改变将会改变相应的材质属性。第5.4.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 材质类示例截图