我正在尝试使用Open Scene Graph 3.4.0在http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html上的35-37教程中实现Deferred Shading
现在,我正在努力让模板正确传递,所以我尽可能地简化了我的代码。 结果,现在我正在使用三个摄像头:
当我尝试使用点光源相机显示深度缓冲区时,它可以工作。 当我将pointLightCamera的clear mask设置为STENCIL_BUFFER_BIT并将模板清除设置为1时,它会显示所有内容。将其设置为0时,它不显示任何内容。 当我在pointLightCamera中禁用清除设置(因为它们应该是这样)并为模板相机中的模板缓冲区启用任何清除设置时,它都没有任何效果。 stencilFunc和stencilOperation按照教程中的设置进行设置。
当我启动程序时,它不会显示任何内容(因此所有模板值都为0)。 这导致我得出结论,我的模板摄像机实际上没有写入模板缓冲区,但我不知道为什么,我无法找到帮助osg示例或互联网论坛,我已经尝试了我能想到的一切
以下是我对相机和观察者的设置(rttCamera将我的场景groupnode作为一个孩子,其中包含一个模型,stencilCamera有一个球体模型作为光量的孩子,我的pointLightCamera有一个screenQuad作为子)。
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和createHUDCamera正在从OSG Cookbook中获取)。
答案 0 :(得分:0)
好的,我终于找到了问题。
我使用FRAME_BUFFER_OBJECT
作为RTT摄像机的渲染目标实现,但是我的HUD摄像机使用FRAME_BUFFER
。我后来注意到我得到了一个OpenGL“无效值”错误。现在我对所有三个使用FRAME_BUFFER_OBJECT
,我可以共享模板值并且它可以工作。我只需要将我以前的HUD相机的结果写入一个新的纹理,然后我用最后一个相机读取,这是一个新的HUD相机,并且有FRAME_BUFFER
作为渲染目标。