目录
前言
前一篇文章有提到利用着色器,实现GeoNode颜色的改变,这篇文章主要是根据osgEarth的一个例子改进,实现鼠标在矢量要素上的一个hover拣选效果。
效果如下:
一、关键代码
shader:
const char* highlight_shader = R"(
#pragma vp_function check_for_highlight, vertex_clip
uniform uint objectid_to_highlight;
uint oe_index_objectid; // Stage global containing object id
flat out int selected;
void check_for_highlight(inout vec4 vertex)
{
selected = (objectid_to_highlight > 1u && objectid_to_highlight == oe_index_objectid) ? 1 : 0;
}
[break]
#pragma vp_function highlight_fragment, fragment
flat in int selected;
void highlight_fragment(inout vec4 color)
{
if ( selected == 1 )
color.rgb = vec3(0.2, 1.0, 1.0);
}
)";
ViewPicker:
struct ViewPicker
{
ViewPicker()
: mapNode(nullptr)
, picker(nullptr)
, highlightUniform(nullptr)
{ }
osgEarth::MapNode* mapNode;
osgEarth::Util::ObjectIDPicker* picker;
osg::Uniform* highlightUniform;
osg::ref_ptr<osgEarth::Feature> _pickedFeature;
osg::ref_ptr<osgEarth::AnnotationNode> _pickedAnno;
osg::ref_ptr<osg::Node> _pickedNode;
};
InitPicker:
void OsgEarthQtMainWindow::InitPicker(ViewPicker& Picker, osgViewer::View* pView, osgEarth::MapNode* pNode)
{
// Highlight features as we pick'em.
Picker.mapNode = pNode;
InstallHighlighter(Picker);
osgEarth::ObjectIDPicker::Function pick = [&](osgEarth::ObjectID id)
{
if (Picker.picker == Picker2D.picker)
{
Picker3D._pickedFeature = nullptr;
Picker3D._pickedAnno = nullptr;
Picker3D._pickedNode = nullptr;
Picker3D.highlightUniform->set(0u);
}
else
{
Picker2D._pickedFeature = nullptr;
Picker2D._pickedAnno = nullptr;
Picker2D._pickedNode = nullptr;
Picker2D.highlightUniform->set(0u);
}
if (id > 0)
{
// Got a pick:
osgEarth::FeatureIndex* index = osgEarth::Registry::objectIndex()->get<osgEarth::FeatureIndex>(id).get();
osgEarth::Feature* feature = index ? index->getFeature(id) : 0L;
Picker._pickedFeature = feature;
Picker._pickedAnno = osgEarth::Registry::objectIndex()->get<osgEarth::AnnotationNode>(id).get();
Picker._pickedNode = osgEarth::Registry::objectIndex()->get<osg::Node>(id).get();
Picker.highlightUniform->set(id);
}
else
{
// No pick:
Picker._pickedFeature = nullptr;
Picker._pickedAnno = nullptr;
Picker._pickedNode = nullptr;
Picker.highlightUniform->set(0u);
}
};
Picker.picker = new osgEarth::ObjectIDPicker();
Picker.picker->setView(pView);
Picker.picker->setGraph(pNode);
Picker.mapNode->addChild(Picker.picker);
// Call our handler when hovering over the map
Picker.picker->onHover(pick);
}
InstallHighlighter:
void OsgEarthQtMainWindow::InstallHighlighter(ViewPicker& viewPicker)
{
osg::StateSet* stateSet = viewPicker.mapNode->getOrCreateStateSet();
int attrLocation = osgEarth::Registry::objectIndex()->getObjectIDAttribLocation();
// This shader program will highlight the selected object.
osgEarth::VirtualProgram* vp = osgEarth::VirtualProgram::getOrCreate(stateSet);
osgEarth::ShaderLoader::load(vp, highlight_shader);
// Since we're accessing object IDs, we need to load the indexing shader as well:
osgEarth::Registry::objectIndex()->loadShaders(vp);
// A uniform that will tell the shader which object to highlight:
viewPicker.highlightUniform = new osg::Uniform("objectid_to_highlight", 0u);
stateSet->addUniform(viewPicker.highlightUniform);
}
实例化 ViewPicker然后调用InitPicker即可,如下: