0

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

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

我完全陷入困境,因为我一直在做的所有测试都没有让我接近我想要的。如果您能帮我解决这个问题,我将不胜感激,任何想法(或代码!)都非常受欢迎!=)

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

#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;
}

提前致谢,

干杯,阿尔瓦罗

4

1 回答 1

0

如果我正确理解了您所追求的,您应该简单地按以下特定顺序呈现:

  • 背景平面
  • “隐形”四边形
  • 所有其他对象(即两个球体等...)

所以在四边形之后渲染的所有东西,如果碰巧在它后面,都会被它掩盖。在 OSG 中,您可以通过显式分配 renderbin 以用于其状态集中的不同(组)节点来实现:

osg::StateSet* stateset = backgroundNode->getOrCreateStateSet();
stateset->setRenderBinDetails(1, "RenderBin");
// and increasing the number for the other nodes...
于 2016-09-22T08:57:35.157 回答