OpenSceneGraph - 无形的Cloack

时间:2016-09-21 17:11:25

标签: rendering depth openscenegraph depth-buffer culling

我是使用OSG的新手,我在尝试解决问题时遇到了一些问题。

我创建了一个场景(一个四边形和两个球体,背景固定),我试图用一个透明的四边形遮挡其中一个球体。我的意思是,制作一个" Invisibility斗篷" ,这样我就可以通过它看到背景图像,而不是它背后的球体(或投射线中的任何东西)。

我完全陷入困境,因为我所做的所有测试都让我无法接近我想要的东西。如果你能帮助我,我真的很感激,任何想法(或代码!)都会受到欢迎! =)

我附上了我用来进行测试的简单场景的代码。

#include <osg/Geometry>
#include <osg/Geode>
#include <osg/Depth>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/ShapeDrawable>
#include <osg/BlendFunc>
#include <osgGA/TrackBallManipulator>

int main ()
{
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
osg::ref_ptr<osg::Image> image = osgDB::readImageFile( "C:/OpenSceneGraph-3.4.0/esc.jpg" );
texture->setDataVariance(osg::Object::DYNAMIC);
texture->setResizeNonPowerOfTwoHint(false);
texture->setImage( image.get() );

// Background
osg::ref_ptr<osg::Drawable> quad = osg::createTexturedQuadGeometry(osg::Vec3(),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> geodeBack = new osg::Geode;
geodeBack->addDrawable( quad.get() );

osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setCullingActive( false );
camera->setClearMask( 0 );
camera->setAllowEventFocus( false );
camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
camera->setRenderOrder( osg::Camera::POST_RENDER );
camera->setProjectionMatrix( osg::Matrix::ortho2D( 0.0, 1.0, 0.0, 1.0) );
camera->addChild( geodeBack.get() );

osg::StateSet* ss = camera->getOrCreateStateSet(); 
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
ss->setMode(GL_DEPTH, osg::StateAttribute::ON);
ss->setAttributeAndModes( new osg::Depth( osg::Depth::LEQUAL,0.99,1.0 ) );


// Quad geometry
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
vertices->push_back( osg::Vec3(-1.0f, 1.0f,-1.0f) );
vertices->push_back( osg::Vec3( 0.0f, 1.0f,-1.0f) );
vertices->push_back( osg::Vec3( 0.0f, 1.0f, 0.0f) );
vertices->push_back( osg::Vec3(-1.0f, 1.0f, 0.0f) );

osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
normals->push_back( osg::Vec3(0.0f,-1.0f, 0.0f) );

osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back( osg::Vec4(1.0f, 1.0f, 1.0f, 0.0f) );

osg::ref_ptr<osg::Geometry> quad2 = new osg::Geometry;
quad2->setVertexArray( vertices.get() );
quad2->setNormalArray( normals.get() );
quad2->setNormalBinding( osg::Geometry::BIND_OVERALL );
quad2->setColorArray( colors.get() );
quad2->setColorBinding( osg::Geometry::BIND_OVERALL );

quad2->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) );

osg::ref_ptr<osg::Geode> geodeTransp = new osg::Geode;
geodeTransp->addDrawable( quad2.get() );


osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc;
blendFunc->setFunction( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
osg::StateSet* stateset = geodeTransp->getOrCreateStateSet();
stateset->setAttributeAndModes( blendFunc ); 

// I'd see both spheres if I uncomment this. Otherwise I'd see the blue osg default background
//stateset->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );

// Sphere 1
osg::ref_ptr<osg::ShapeDrawable> shape1 = new osg::ShapeDrawable;
shape1->setShape( new osg::Sphere(osg::Vec3(-0.3f,0.5f,-0.3f), 0.2f) );
shape1->setColor( osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) );

// Sphere 2
osg::ref_ptr<osg::ShapeDrawable> shape2 = new osg::ShapeDrawable;
shape2->setShape( new osg::Sphere(osg::Vec3(-0.7f,1.5f,-0.7f), 0.2f) );
shape2->setColor( osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) );

osg::ref_ptr<osg::Geode> geodeFront = new osg::Geode;
geodeFront->addDrawable( shape1.get() );
geodeFront->addDrawable( shape2.get() );

osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild( camera.get() );
root->addChild( geodeTransp.get() );
root->addChild( geodeFront.get() );

osgViewer::Viewer viewer;
viewer.setSceneData( root.get() );

viewer.setCameraManipulator(new osgGA::TrackballManipulator());
osg::Vec3d eye( -0.5, -3.0, -0.5 );
osg::Vec3d center( -0.5, 0.0, -0.5 );
osg::Vec3d up( 0.0, 0.0, 1.0 );

viewer.getCamera()->setViewMatrixAsLookAt( eye, center, up );

viewer.realize();
while(!viewer.done()) {
    viewer.frame(); 
}
return 0;
}

提前致谢,

干杯, 阿尔瓦罗

1 个答案:

答案 0 :(得分:0)

如果我正确理解了您之后所做的事情,您应该按照以下特定顺序进行渲染:

  • 背景平面
  • &#34;隐身&#34;四
  • 所有其他物体(即两个球体等......)

所以在四边形之后渲染的所有内容都会被它掩盖,如果恰好在它后面。在OSG中,您可以通过明确指定renderbin来实现它,以用于其stateset中的不同(组)节点:

osg::StateSet* stateset = backgroundNode->getOrCreateStateSet();
stateset->setRenderBinDetails(1, "RenderBin");
// and increasing the number for the other nodes...