2016-09-21 63 views
0

我是新的使用OSG,我有一些問題試圖解決問題。OpenSceneGraph - 隱形Cloack

我創建了一個場景(一個四邊形和兩個球體,有一個固定的背景),我試圖用透明四邊形遮擋其中一個球體。我的意思是,製作一張「隱形衣」,所以我可以通過它看到背景圖像,但不能看到它背後的球體(或任何在投影線中的物體)。

我完全卡住了,因爲我一直在做的所有測試都沒有讓我接近我想要的東西。如果你能幫助我,我會非常感激,任何想法(或代碼!)都會比歡迎! =)

我附上了我用來做測試的簡單場景的代碼。

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

由於提前,

乾杯, 阿爾瓦羅

回答

0

如果我理解正確的話你以後,你應該簡單地在這個特定的順序呈現:

  • 背景飛機
  • 「隱形」四格
  • 所有其他物件(即兩個領域等等)

因此,所有呈現在四元組之後的東西,如果恰好在它後面,它將被掩蓋。在OSG中,您可以通過明確分配用於其狀態集中不同(羣組)的渲染器來實現該目的:

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

您好rickyviking,感謝您的快速響應! 真的很感激 但是,即使設置你告訴我渲染次序,它不斷髮生,我認爲 1.如果提供TRANSPARENT_BIN呈現提示:這兩個領域呈現,而不只是最近的一個。 2.如果我不知道,我可以看到的是通過四邊形表面的藍色osg默認背景,而不是我的固定背景。 ----- (也許任何一種渲染實心四邊形+渲染球體後將其狀態集更新爲透明?最近渲染背景?) – AVGrimaldi

+0

對不起@AVGrimaldi,但這裏也有涉及的許多概念無法在單個問題中澄清。我在回答中提到的渲染順序應該會給你正確的結果。但是您需要更好地瞭解osg:TRANSPARENT_BIN會將對象排在前面,而不是您之後的對象,並且在渲染一幀時無法更改狀態集。檢查osg檔案和正確用法的例子 – rickyviking

+0

太棒了,一定會做!雖然我仍然陷入困境......因爲你的答案也導致了「四重背景擦除」! (即使在任何情況下都不使用transparent_bin,正如你已經解釋的那樣),所以一定有一些缺失,爲了保持背景自定義圖像完好無損... – AVGrimaldi