HEAD-UP DISPLAY, 即是抬头显示功能,在opengl编程中,我们有时需要一种屏幕区域,这个区域并不会随着三维场景视角表换而发生改变,也可以讲,是在三维场景中实现了一个二维子场景,故常用来显示提示信息。下面这个小例子实现了GL3版本中的HUD功能(OSG编译选项里面,我们选择了编译GLcore版本,因为我们想要这个功能应用在osgEarth3.0以后的版本中,不熟悉什么叫GLCore的童靴可以参考我的另一篇博文《opengl版本发展史及各种概念的厘清》)。
首先,我们要创建一个相机
osg::Camera* camera = new osg::Camera;
camera->setName("Hud Camera");
// set the projection matrix
camera->setProjectionMatrixAsOrtho2D(0, screen_width, 0, screen_heigh);
camera->setViewport(0, 0, screen_width, screen_heigh);
// set the view matrix
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrix(osg::Matrix::identity());
camera->setClearColor(osg::Vec4(1, 0.5, 0.5, 0.5));
将相机的投影方式设置为正射投影(Ortho2D);视口设置为屏幕大小;现在我们看到的界面是整个屏幕;设置参考帧为绝对。
创建完了相机,接下来我们创建要在屏幕上显示的内容。一般情况下我们会创建一个矩形,在这个矩形上贴纹理,或绘制图案,作为HUD的显示内容,下面的代码,创建一个白色的矩形。
osg::Geometry* createQuad(int screen_width, int screen_heigh, float z) {
osg::Geometry* polyGeom = new osg::Geometry();
polyGeom->setSupportsDisplayList(false);
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec2Array* texcoords = new osg::Vec2Array;
osg::Vec4Array* colors = new osg::Vec4Array;
/*four vertex*/
vertices->push_back(osg::Vec3d(0, 0, z));
texcoords->push_back(osg::Vec2f(0, 0));
vertices->push_back(osg::Vec3d(screen_width, 0, z));
texcoords->push_back(osg::Vec2f(1, 0));
vertices->push_back(osg::Vec3d(screen_width, screen_heigh, z));
texcoords->push_back(osg::Vec2f(1, 1));
vertices->push_back(osg::Vec3d(0, screen_heigh, z));
texcoords->push_back(osg::Vec2f(0, 1));
/*four vertex*/
colors->push_back(osg::Vec4f(1.0,1.0,1.0,1.0));
colors->setBinding(osg::Array::BIND_OVERALL);
/*set vertex array and tex coord array*/
polyGeom->setVertexArray(vertices);
polyGeom->setTexCoordArray(0, texcoords);
polyGeom->setColorArray(colors);
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN, 0, vertices->size()));
return polyGeom;
}
创建一个viewer,并且取得窗口的宽高。
// initialize a viewer:
osgViewer::Viewer viewer;
viewer.setUpViewAcrossAllScreens();
osgViewer::Viewer::Windows windows;
viewer.getWindows(windows);
int screen_width = windows[0]->getTraits()->width;
int screen_heigh = windows[0]->getTraits()->height;
然后创建一个场景树中的叶子节点,将createQuad函数创建的矩形包含在geode中:
/*create a geode*/
osg::Geode* _geode = new osg::Geode();
_geode->setName("GeodeOfHUD");
osg::Geometry* polyGeom = createQuad(screen_width, screen_heigh, -100);
polyGeom->setName("PolyGeomOfHUD_");
_geode->addDrawable(polyGeom);
最后,我们将场景加入到view中
camera->addChild(_geode);
viewer.setSceneData(camera);
这样,我们就完成了整个HUD效果的创建。
完整的代码如下
osg::Geometry* createQuad(int screen_width, int screen_heigh, float z) {
osg::Geometry* polyGeom = new osg::Geometry();
polyGeom->setSupportsDisplayList(false);
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec2Array* texcoords = new osg::Vec2Array;
osg::Vec4Array* colors = new osg::Vec4Array;
/*four vertex*/
vertices->push_back(osg::Vec3d(0, 0, z));
texcoords->push_back(osg::Vec2f(0, 0));
vertices->push_back(osg::Vec3d(screen_width, 0, z));
texcoords->push_back(osg::Vec2f(1, 0));
vertices->push_back(osg::Vec3d(screen_width, screen_heigh, z));
texcoords->push_back(osg::Vec2f(1, 1));
vertices->push_back(osg::Vec3d(0, screen_heigh, z));
texcoords->push_back(osg::Vec2f(0, 1));
/*four vertex*/
colors->push_back(osg::Vec4f(1.0,1.0,1.0,1.0));
colors->setBinding(osg::Array::BIND_OVERALL);
/*set vertex array and tex coord array*/
polyGeom->setVertexArray(vertices);
polyGeom->setTexCoordArray(0, texcoords);
polyGeom->setColorArray(colors);
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN, 0, vertices->size()));
return polyGeom;
}
int
main(int argc, char** argv)
{
// initialize a viewer:
osgViewer::Viewer viewer;
/*得到窗口的宽高*/
viewer.setUpViewAcrossAllScreens();
osgViewer::Viewer::Windows windows;
viewer.getWindows(windows);
int screen_width = windows[0]->getTraits()->width;
int screen_heigh = windows[0]->getTraits()->height;
/*创建HUD相机*/
osg::Camera* camera = new osg::Camera;
camera->setName("Hud Camera");
// set the projection matrix
camera->setProjectionMatrixAsOrtho2D(0, screen_width, 0, screen_heigh);
camera->setViewport(0, 0, screen_width, screen_heigh);
// set the view matrix
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrix(osg::Matrix::identity());
camera->setClearColor(osg::Vec4(1, 0.5, 0.5, 0.5));
/*create quad with texture from rtt*/
osg::Geode* _geode = new osg::Geode();
_geode->setName("GeodeOfHUD");
osg::Geometry* polyGeom = createQuad(screen_width, screen_heigh, -100);
polyGeom->setName("PolyGeomOfHUD_");
_geode->addDrawable(polyGeom);
camera->addChild(_geode);
viewer.setSceneData(camera);
int r = viewer.run();
return r;
}