尝试了两种不同的方式设置背景。
创建HUD相机
图片背景
主要是通过osg::Iamge读取图片文件后渲染到Texture2D,关联到hud相机中子节点上,重点还是hud相机的设置:
osg::ref_ptr<osg::Group> group = new osg::Group;
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");
group->addChild(node);
//创建hud相机
osg::ref_ptr<osg::Camera> hudCamera = new osg::Camera;
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
osg::ref_ptr<osg::Image> image = osgDB::readImageFile("E:/wallpaper/road.jpg");
texture->setImage(image.get());
osg::ref_ptr<osg::Drawable> quad = osg::createTexturedQuadGeometry(
osg::Vec3(0.f, 0.f, 0.f), osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f));
quad->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture.get());
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(quad.get());
geode->setNodeMask(1024);
hudCamera->setClearMask(0);
hudCamera->setCullingActive(false);
hudCamera->setAllowEventFocus(false);
hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
hudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0.0, 1.0, 0.0, 1.0));
hudCamera->setViewport(0, 0, 800, 600);
hudCamera->addChild(geode.get());
osg::StateSet* ss = hudCamera->getOrCreateStateSet();
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
ss->setAttributeAndModes(new osg::Depth(osg::Depth::LEQUAL, 1.0, 1.0));
group->addChild(hudCamera);
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->setSceneData(group);
viewer->setUpViewInWindow(500, 500, 800, 600);
return viewer->run();
渐变色背景
渐变色背景的实现中hud的创建是一致的。颜色显示也可以通过第一种方式去实现,比如使用qt的qimage自定义填充后当成一张图片被osg读入,也可以使用设置顶点数组和颜色数组的方式,如:
osg::ref_ptr<osg::Group> group = new osg::Group;
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");
group->addChild(node);
//创建hud相机
osg::ref_ptr<osg::Camera> hudCamera = new osg::Camera;
osg::ref_ptr<osg::Geometry> quad = new osg::Geometry;
osg::ref_ptr<osg::Vec3Array> vertex = new osg::Vec3Array;
vertex->push_back(osg::Vec3(0.0, 0.0, 0.0));
vertex->push_back(osg::Vec3(1.0, 0.0, 0.0));
vertex->push_back(osg::Vec3(1.0, 1.0, 0.0));
vertex->push_back(osg::Vec3(0.0, 1.0, 0.0));
quad->setVertexArray(vertex);
osg::ref_ptr<osg::Vec4Array> color = new osg::Vec4Array;
color->push_back(osg::Vec4(0.0, 1.0, 1.0, 1.0));
color->push_back(osg::Vec4(0.0, 1.0, 1.0, 1.0));
color->push_back(osg::Vec4(0.0, 0.0, 1.0, 1.0));
color->push_back(osg::Vec4(0.0, 0.0, 1.0, 1.0));
quad->setColorArray(color, osg::Array::BIND_PER_VERTEX);
quad->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
...节点的添加与hud相机的设置同上...
shader
渐变色背景
通过使用shader创建一个全屏的三角形来充当背景,原理是从opengl渐变背景这篇文章中看到的。
#define SHADER_HEADER "#version 330 core\n"
#define SHADER_STR(x) #x
int main()
{
osg::ref_ptr<osg::Geometry> geo = new osg::Geometry;
const char* vs_src = (const char*)SHADER_HEADER SHADER_STR
(
out vec2 v_uv;
void main()
{
uint idx = uint(gl_VertexID);
gl_Position = vec4(idx & 1U, idx >> 1U, 0.0, 0.5) * 4.0 - 1.0;
v_uv = vec2(gl_Position.xy * 0.5 + 0.5);
}
);
const char* fs_src = (const char*)SHADER_HEADER SHADER_STR
(
uniform vec4 top_color = vec4(0.0, 1.0, 1.0, 1.0);
uniform vec4 bot_color = vec4(0.0, 0.0, 1.0, 1.0);
in vec2 v_uv;
out vec4 frag_color;
void main()
{
frag_color = bot_color * (1 - v_uv.y) + top_color * v_uv.y;
}
);
osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX, vs_src);
osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, fs_src);
osg::ref_ptr<osg::Program> m_program = new osg::Program;
m_program->addShader(vertexShader);
m_program->addShader(fragmentShader);
geo->getOrCreateStateSet()->setAttributeAndModes(m_program, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
//osg中还是需要传递顶点,不然画不出来
osg::Vec3Array* vertices = new osg::Vec3Array;
vertices->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
vertices->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
vertices->push_back(osg::Vec3(1.0f, 0.0f, 1.0f));
geo->setVertexArray(vertices);
geo->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, 3));
geo->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
//小于0表示优先绘制,处于底层
geo->getOrCreateStateSet()->setRenderBinDetails(-2, "RenderBin");
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");
osg::ref_ptr<osg::Group> group = new osg::Group;
group->addChild(node);
group->addChild(geo);
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->setSceneData(group);
viewer->setUpViewInWindow(500, 500, 800, 600);
return viewer->run();
}
图片背景
大体和上面一致,修改了shader来对纹理采样:
#define SHADER_HEADER "#version 330 core\n"
#define SHADER_STR(x) #x
int main()
{
...同上...
const char* fs_src = (const char*)SHADER_HEADER SHADER_STR
(
uniform sampler2D tex;
in vec2 v_uv;
out vec4 frag_color;
void main()
{
vec4 tempColor = texture(tex, v_uv);
frag_color = tempColor;
}
);
...shader的编译和节点其他属性的设置代码同上...
osg::ref_ptr<osg::Texture2D> tex2d = new osg::Texture2D;
tex2d->setDataVariance(osg::Object::DYNAMIC);
tex2d->setImage(osgDB::readImageFile("E:/wallpaper/road.jpg"));
geo->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex2d, osg::StateAttribute::ON);
...场景的设置和节点的添加代码同上...
}