Ich versuche Deferred Shading zu implementieren entsprechend den Anleitungen 35-37 auf http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html mit Öffnen Scene Graph 3.4.0Stencilbuffer für Deferred Shading mit offenem Szenengraph
Gerade jetzt, ich kämpfen, um die Schablone zu erhalten pass richtig, also habe ich meinen Code so weit wie möglich vereinfacht. Als Ergebnis jetzt bin ich mit drei Kameras:
- eine RTT-Kamera für postion-, den Tiefenpuffer normal- und Farbtextur sowie Schreiben.
- eine Schablonenkamera (aufgebaut als RTT Kamera ohne Farbausgabe in dem Fragment-Shader) für die in die Puffer zu schreiben Schablone des Tiefentest unter Verwendung führt
- eine Punktlichtkamera (aufgebaut als HUD-Kamera), unter Verwendung von verzögerte Schattierung und nur für Schreiboperationen gesetzt, wenn der Stencil-Puffer nicht 0 ist.
Wenn ich versuche, den Tiefenpuffer mit der Punktlichtkamera anzuzeigen, funktioniert es. Wenn ich die klare Maske von pointLightCamera auf STENCIL_BUFFER_BIT setze und die Schablone auf 1 setze, wird alles angezeigt. Es zeigt nichts an, wenn es auf 0 gesetzt wird. Wenn ich die Löscheinstellungen in der pointLightCamera (wie sie sein sollten) deaktivieren und alle Einstellungen für den Stencil Buffer in der Schablonenkamera deaktivieren, hat das keinerlei Auswirkungen. Die Funktionen stencilFunc und stencilOperation werden wie in den Lernprogrammen festgelegt.
Wenn ich das Programm starte, wird nichts angezeigt (also sind alle Schablonenwerte 0). Das bringt mich zu dem Schluss, dass meine stencilCamera eigentlich nicht in den Stencil Buffer schreibt, aber ich habe keine Ahnung warum, ich konnte keine Hilfe mehr bei den OSG Beispielen oder Internetforen finden und habe alles versucht was ich mir vorstellen konnte.
Hier sind meine Einstellungen für die Kameras und Betrachter (die rtTCamera hat meine Szene groupnode als Kind, die ein Modell enthält, die stencilCamera hat ein Kugelmodell als Kind für das Lichtvolumen und meine pointLightCamera hat ein screenQuad als ein Kind).
texDepth->setTextureSize(1024, 1024);
texDepth->setInternalFormat(GL_DEPTH24_STENCIL8_EXT);
texDepth->setSourceFormat(GL_DEPTH_STENCIL_EXT);
texDepth->setSourceType(GL_UNSIGNED_INT_24_8_EXT);
osg::ref_ptr<osg::Texture2D> texColor = createTexture();
osg::ref_ptr<osg::Texture2D> texPosition = createTexture();
osg::ref_ptr<osg::Texture2D> texNormal = createTexture();
//1. pass camera and set up
osg::ref_ptr<osg::Camera> rttCamera = createRTTCamera(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, texDepth, false);
rttCamera->setRenderOrder(osg::Camera::PRE_RENDER, 0);
rttCamera->attach(osg::Camera::COLOR_BUFFER0, texColor);
rttCamera->attach(osg::Camera::COLOR_BUFFER1, texPosition);
rttCamera->attach(osg::Camera::COLOR_BUFFER2, texNormal);
rttCamera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 0.0));
osg::ref_ptr<osg::Stencil> rttStencil = new osg::Stencil;
rttStencil->setWriteMask(0);
rttCamera->getOrCreateStateSet()->setAttribute(rttStencil, osg::StateAttribute::ON);
rttCamera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
osg::ref_ptr<osg::StateSet> ss = rttCamera->getOrCreateStateSet();
osg::ref_ptr<osg::Program> rttProg = new osg::Program;
osg::Shader* vertShader = osgDB::readShaderFile("pass1.vert");
osg::Shader* fragShader = osgDB::readShaderFile("pass1.frag");
rttProg->addShader(vertShader);
rttProg->addShader(fragShader);
ss->setAttributeAndModes(rttProg.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc;
bf->setFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ss->setAttributeAndModes(bf, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
rttCamera->addChild(scene.get());
//2. pass: stencil pass camera and set up
osg::ref_ptr<osg::Camera> stencilCamera = createRTTCamera(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, texDepth, false);//createHUDCamera(0.0, 1.0, 0.0, 1.0);//
stencilCamera->setRenderOrder(osg::Camera::PRE_RENDER, 2);
stencilCamera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, texDepth);//depth buffer was filled by rttCamera
stencilCamera->getOrCreateStateSet()->setMode(GL_STENCIL_TEST, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
stencilCamera->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); //depth test result will fill stencil buffer
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
depth->setWriteMask(false); //depth test is needed to compare scene to light volume, but light volume must not write into depth buffer
stencilCamera->getOrCreateStateSet()->setAttribute(depth, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
stencilCamera->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
stencilCamera->setClearMask(GL_STENCIL_BUFFER_BIT);
osg::ref_ptr<osg::StencilTwoSided> stencilWrite = new osg::StencilTwoSided;
stencilWrite->setFunction(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::ALWAYS, 0, 0);
stencilWrite->setFunction(osg::StencilTwoSided::BACK, osg::StencilTwoSided::ALWAYS, 0, 0);
stencilWrite->setOperation(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::DECR_WRAP, osg::StencilTwoSided::KEEP);
stencilWrite->setOperation(osg::StencilTwoSided::BACK, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::INCR_WRAP, osg::StencilTwoSided::KEEP);
stencilWrite->setWriteMask(osg::StencilTwoSided::FRONT, 0xFF); //may not be needed
stencilWrite->setWriteMask(osg::StencilTwoSided::BACK, 0xFF);
stencilCamera->getOrCreateStateSet()->setAttribute(stencilWrite, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
stencilCamera->addChild(mtSphere);//lights.get());
osg::ref_ptr<osg::Program> stencilProg = new osg::Program;
stencilProg->addShader(osgDB::readShaderFile("nullTechnique.vert"));
stencilProg->addShader(osgDB::readShaderFile("nullTechnique.frag"));
stencilCamera->getOrCreateStateSet()->setAttributeAndModes(stencilProg.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
//3. pass: point light pass camera and set up
osg::ref_ptr<osg::Camera> pointLightCamera = createHUDCamera(0.0, 1.0, 0.0, 1.0);
pointLightCamera->setClearMask(0);
pointLightCamera->setRenderOrder(osg::Camera::POST_RENDER, 1);//PRE_RENDER, 2);
pointLightCamera->addChild(screenQuad);
ss = pointLightCamera->getOrCreateStateSet();
osg::ref_ptr<osg::Stencil> stencilRead = new osg::Stencil;
stencilRead->setFunction(osg::Stencil::NOTEQUAL, 1, 0xFF); //render only where stencil buffer is != 0 (this will be 1 as set in stencil pass)
stencilRead->setWriteMask(0);//it should not write into the stencil buffer it reads from
ss->setAttribute(stencilRead, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
osg::ref_ptr<osg::Depth> depthRead = new osg::Depth;
depth->setWriteMask(false);
ss->setAttribute(depth, osg::StateAttribute::ON);
pointLightCamera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, texDepth);
ss->setMode(GL_STENCIL_TEST, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
ss->setMode(GL_BLEND, osg::StateAttribute::ON); //all light passes shall add their renderings to the previous light passes
osg::ref_ptr<osg::BlendFunc> renderAddBlendFunc = new osg::BlendFunc;
renderAddBlendFunc->setFunction(GL_ONE, GL_ONE);
ss->setAttribute(renderAddBlendFunc, osg::StateAttribute::ON);
osg::ref_ptr<osg::BlendEquation> renderAddBlendEq = new osg::BlendEquation;
renderAddBlendEq->setEquation(osg::BlendEquation::FUNC_ADD);
ss->setAttribute(renderAddBlendEq, osg::StateAttribute::ON);
osg::ref_ptr<osg::CullFace> cullFacePointLightPass = new osg::CullFace(osg::CullFace::FRONT);
osg::ref_ptr<osg::Program> pointLightProg = new osg::Program;
vertShader = osgDB::readShaderFile("pass2.vert");
fragShader = osgDB::readShaderFile("pass2.frag");
pointLightProg->addShader(vertShader);
pointLightProg->addShader(fragShader);
ss->setAttributeAndModes(pointLightProg.get(), osg::StateAttribute::ON);
ss->setTextureAttributeAndModes(0, texColor);
ss->setTextureAttributeAndModes(1, texPosition);
ss->setTextureAttributeAndModes(2, texNormal);
ss->setTextureAttributeAndModes(3, texDepth);
ss->addUniform(new osg::Uniform("tDiffuse", 0));
ss->addUniform(new osg::Uniform("tPosition", 1));
ss->addUniform(new osg::Uniform("tNormals", 2));
ss->addUniform(new osg::Uniform("tDepth", 3));
ss->addUniform(new osg::Uniform("lightPosition", osg::Vec3(0.0, 0.0, 0.0)));
osg::Vec3 eye, center, up;
rttCamera->getViewMatrixAsLookAt(eye, center, up);
ss->addUniform(new osg::Uniform("cameraPosition", eye));
pointLightCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER);
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(rttCamera);
root->addChild(stencilCamera);
root->addChild(pointLightCamera);
osgViewer::Viewer viewer;
viewer.setCameraManipulator(new osgGA::TrackballManipulator);
viewer.getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
viewer.setSceneData(root.get());
osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);
(createRTTCamera und createHUDCamera nehmen aus dem OSG-Kochbuch).