显示文字是一种非常实用的技术,可以用来把一些重要的文字始终显示在屏幕上。HUD的全称是HeadsUpDisplay,即抬头显示,这种技术最早应用在军事战斗机上。
创建HUD显示的基本步骤如下:
<1> 创建一个osg::Camera对象,设置视图、投影矩阵及渲染顺序,以确保在场景图形全部渲染完后才进行渲染。
<2> 创建一个osg::Geode 对象和一个osgText::Text 对象,并设置相应的文字属性。把osgText::Text对象添加到 Geode 叶节点。
<3> 把叶节点Geode关联到步骤(1)所创建的相机
在创建HUD显示文字显示时,需要注意的有如下几点:
- 渲染顺序设置为 POST,否则可能会被场景中的其他图形所覆盖。
- 注意关闭光照和深度。
- 投影矩阵通常设置为屏幕尺寸大小。
代码如程序清单9-3所示。
1. /* HUD 显示汉字 */
2. osg::ref_ptr<osg::Camera> createHUDText(const string strFontPath)
3. {
4. osg::ref_ptr<osg::Camera> camera = new osg::Camera();
5.
6. // 设置投影矩阵
7. camera->setProjectionMatrix(osg::Matrix::ortho2D(0, 1280, 0, 800));
8.
9. // 设置视图矩阵,同事确保不被场景中其它图形位置变换影响,使用绝对帧引用
10. camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
11. camera->setViewMatrix(osg::Matrix::identity());
12.
13. // 清除深度缓存
14. camera->setClearMask(GL_DEPTH_BUFFER_BIT);
15.
16. // 设置渲染顺序为POST
17. camera->setRenderOrder(osg::Camera::POST_RENDER);
18.
19. // 设置为不接收时间,始终不得到焦点
20. camera->setAllowEventFocus(false);
21.
22. osg::ref_ptr<osg::Geode> geode = new osg::Geode();
23. osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();
24.
25. // 关闭光照
26. stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
27.
28. // 关闭深度测试
29. stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
30.
31. // 设置文字
32. osg::ref_ptr<osgText::Text> text = new osgText::Text();
33. osg::ref_ptr<osgText::Font> font = new osgText::Font();
34. font = osgText::readFontFile(strFontPath);
35. text->setFont(font.get());
36. text->setText(L"http://www.OsgChina.osg-OpenScenseGraph 中国官方");
37. text->setPosition(osg::Vec3(100.0, 600.0, 0));
38. text->setCharacterSize(40.0);
39. text->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
40. text->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX);
41.
42. geode->addDrawable(text.get());
43. camera->addChild(geode.get());
44.
45. return camera.get();
46. }
47.
48. void osgText_HUD_Text_9_3(const string &strDataFolder)
49. {
50. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
51. osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
52. traits->x = 40;
53. traits->y = 40;
54. traits->width = 600;
55. traits->height = 480;
56. traits->windowDecoration = true;
57. traits->doubleBuffer = true;
58. traits->sharedContext = 0;
59.
60. osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
61.
62. osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
63. camera->setGraphicsContext(gc.get());
64. camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
65. GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
66. camera->setDrawBuffer(buffer);
67. camera->setReadBuffer(buffer);
68.
69. osg::ref_ptr<osg::Group> root = new osg::Group();
70.
71. // 读取模型
72. string strDataPath = strDataFolder + "logo.ive";
73. osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(strDataPath);
74.
75. root->addChild(node.get());
76.
77. // 添加HUD文字
78. string strFontPath = strDataFolder + "font\\simhei.ttf";
79. root->addChild(createHUDText(strFontPath));
80.
81. // 优化场景数据
82. osgUtil::Optimizer optimizer;
83. optimizer.optimize(root.get());
84.
85. viewer->setSceneData(root.get());
86. viewer->realize();
87. viewer->run();
88. }
运行程序,截图如图9-5 所示。
图9-5 HUD显示汉字示例截图