diff --git a/include/osg/Camera b/include/osg/Camera index e1e1ad233..b2b2774ef 100644 --- a/include/osg/Camera +++ b/include/osg/Camera @@ -294,14 +294,14 @@ class OSG_EXPORT Camera : public Transform, public CullSettings /** Set the draw buffer used at the start of each frame draw. * Note, a buffer value of GL_NONE is used to sepecify that the rendering back-end should choose the most appropriate buffer.*/ - void setDrawBuffer(GLenum buffer) { _drawBuffer = buffer; } + void setDrawBuffer(GLenum buffer) { _drawBuffer = buffer; applyMaskAction( DRAW_BUFFER ); } /** Get the draw buffer used at the start of each frame draw. */ GLenum getDrawBuffer() const { return _drawBuffer; } /** Set the read buffer for any required copy operations to use. * Note, a buffer value of GL_NONE is used to sepecify that the rendering back-end should choose the most appropriate buffer.*/ - void setReadBuffer(GLenum buffer) { _readBuffer = buffer; } + void setReadBuffer(GLenum buffer) { _readBuffer = buffer; applyMaskAction( READ_BUFFER ); } /** Get the read buffer for any required copy operations to use. */ GLenum getReadBuffer() const { return _readBuffer; } diff --git a/include/osg/CullSettings b/include/osg/CullSettings index bfe1da58d..617f7251a 100644 --- a/include/osg/CullSettings +++ b/include/osg/CullSettings @@ -58,25 +58,27 @@ class OSG_EXPORT CullSettings enum VariablesMask { - COMPUTE_NEAR_FAR_MODE = 0x0001, - CULLING_MODE = 0x0002, - LOD_SCALE = 0x0004, - SMALL_FEATURE_CULLING_PIXEL_SIZE = 0x0008, - CLAMP_PROJECTION_MATRIX_CALLBACK = 0x0010, - NEAR_FAR_RATIO = 0x0020, - IMPOSTOR_ACTIVE = 0x0040, - DEPTH_SORT_IMPOSTOR_SPRITES = 0x0080, - IMPOSTOR_PIXEL_ERROR_THRESHOLD = 0x0100, - NUM_FRAMES_TO_KEEP_IMPOSTORS_SPRITES = 0x0200, - CULL_MASK = 0x0400, - CULL_MASK_LEFT = 0x0800, - CULL_MASK_RIGHT = 0x1000, - CLEAR_COLOR = 0x2000, - LIGHTING_MODE = 0x4000, - LIGHT = 0x8000, - - NO_VARIABLES = 0x0000, - ALL_VARIABLES = 0xFFFF + COMPUTE_NEAR_FAR_MODE = 0x00000001, + CULLING_MODE = 0x00000002, + LOD_SCALE = 0x00000004, + SMALL_FEATURE_CULLING_PIXEL_SIZE = 0x00000008, + CLAMP_PROJECTION_MATRIX_CALLBACK = 0x00000010, + NEAR_FAR_RATIO = 0x00000020, + IMPOSTOR_ACTIVE = 0x00000040, + DEPTH_SORT_IMPOSTOR_SPRITES = 0x00000080, + IMPOSTOR_PIXEL_ERROR_THRESHOLD = 0x00000100, + NUM_FRAMES_TO_KEEP_IMPOSTORS_SPRITES = 0x00000200, + CULL_MASK = 0x00000400, + CULL_MASK_LEFT = 0x00000800, + CULL_MASK_RIGHT = 0x00001000, + CLEAR_COLOR = 0x00002000, + LIGHTING_MODE = 0x00004000, + LIGHT = 0x00008000, + DRAW_BUFFER = 0x00010000, + READ_BUFFER = 0x00020000, + + NO_VARIABLES = 0x00000000, + ALL_VARIABLES = 0xFFFFFFFF }; /** Set the inheritance mask used in inheritCullSettings to control which variables get overwritten by the passed in CullSettings object.*/ diff --git a/include/osgUtil/RenderStage b/include/osgUtil/RenderStage index 87f58a095..6b50d46c5 100644 --- a/include/osgUtil/RenderStage +++ b/include/osgUtil/RenderStage @@ -53,17 +53,31 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin /** Set the draw buffer used at the start of each frame draw. */ - void setDrawBuffer(GLenum buffer) { _drawBuffer = buffer; } + void setDrawBuffer(GLenum buffer, bool applyMask = true ) { _drawBuffer = buffer; setDrawBufferApplyMask( applyMask ); } /** Get the draw buffer used at the start of each frame draw. */ GLenum getDrawBuffer() const { return _drawBuffer; } + /** Get the apply mask defining whether glDrawBuffer is called at each frame draw. */ + bool getDrawBufferApplyMask() const { return _drawBufferApplyMask; } + + /** Set the apply mask defining whether glDrawBuffer is called at each frame draw. */ + void setDrawBufferApplyMask( bool applyMask ) { _drawBufferApplyMask = applyMask; } + + + /** Set the read buffer for any required copy operations to use. */ - void setReadBuffer(GLenum buffer) { _readBuffer = buffer; } + void setReadBuffer(GLenum buffer, bool applyMask = true) { _readBuffer = buffer; setReadBufferApplyMask( applyMask ); } /** Get the read buffer for any required copy operations to use. */ GLenum getReadBuffer() const { return _readBuffer; } + /** Get the apply mask defining whether glReadBuffer is called at each frame draw. */ + bool getReadBufferApplyMask() const { return _readBufferApplyMask; } + + /** Set the apply mask defining whether glReadBuffer is called at each frame draw. */ + void setReadBufferApplyMask( bool applyMask ) { _readBufferApplyMask = applyMask; } + /** Set the viewport.*/ void setViewport(osg::Viewport* viewport) { _viewport = viewport; } @@ -251,7 +265,9 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin osg::ref_ptr _viewport; GLenum _drawBuffer; + bool _drawBufferApplyMask; GLenum _readBuffer; + bool _readBufferApplyMask; GLbitfield _clearMask; osg::ref_ptr _colorMask; osg::Vec4 _clearColor; diff --git a/src/osg/Camera.cpp b/src/osg/Camera.cpp index 0447b79d4..36f761d8a 100644 --- a/src/osg/Camera.cpp +++ b/src/osg/Camera.cpp @@ -386,11 +386,18 @@ void Camera::inheritCullSettings(const CullSettings& settings, unsigned int inhe { CullSettings::inheritCullSettings(settings, inheritanceMask); - if (inheritanceMask & CLEAR_COLOR) + const Camera* camera = dynamic_cast(&settings); + if (camera) { //osg::notify(osg::NOTICE)<<"Inheriting slave Camera"<(&settings); - _clearColor = camera->_clearColor; + if (inheritanceMask & CLEAR_COLOR) + _clearColor = camera->_clearColor; + + if (inheritanceMask & DRAW_BUFFER) + _drawBuffer = camera->_drawBuffer; + + if (inheritanceMask & READ_BUFFER) + _drawBuffer = camera->_readBuffer; } } diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index b47811aa8..5d5c891c4 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -1262,26 +1262,25 @@ void CullVisitor::apply(osg::Camera& camera) rtts->setCamera(&camera); - if (camera.getDrawBuffer() != GL_NONE) + if ( camera.getInheritanceMask() & DRAW_BUFFER ) + { + // inherit draw buffer from above. + rtts->setDrawBuffer(previous_stage->getDrawBuffer(),previous_stage->getDrawBufferApplyMask()); + } + else { rtts->setDrawBuffer(camera.getDrawBuffer()); } - else + + if ( camera.getInheritanceMask() & READ_BUFFER ) { - // inherit draw buffer from above. - rtts->setDrawBuffer(previous_stage->getDrawBuffer()); + // inherit read buffer from above. + rtts->setReadBuffer(previous_stage->getReadBuffer(), previous_stage->getReadBufferApplyMask()); } - - if (camera.getReadBuffer() != GL_NONE) + else { rtts->setReadBuffer(camera.getReadBuffer()); } - else - { - // inherit read buffer from above. - rtts->setReadBuffer(previous_stage->getReadBuffer()); - } - } else { @@ -1305,6 +1304,7 @@ void CullVisitor::apply(osg::Camera& camera) { rtts->setClearColor(camera.getClearColor()); } + // set the color mask. osg::ColorMask* colorMask = camera.getColorMask()!=0 ? camera.getColorMask() : previous_stage->getColorMask(); diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index 3db0833ec..7e2d8de6f 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -25,6 +25,8 @@ #include +#define FORCE_COLOR_ATTACHMENT 1 +#define FORCE_DEPTH_ATTACHMENT 1 using namespace osg; using namespace osgUtil; @@ -42,7 +44,10 @@ RenderStage::RenderStage(): _stageDrawnThisFrame = false; _drawBuffer = GL_NONE; + _drawBufferApplyMask = false; _readBuffer = GL_NONE; + _readBufferApplyMask = false; + _clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; _clearColor.set(0.0f,0.0f,0.0f,0.0f); _clearAccum.set(0.0f,0.0f,0.0f,0.0f); @@ -69,7 +74,10 @@ RenderStage::RenderStage(SortMode mode): _stageDrawnThisFrame = false; _drawBuffer = GL_NONE; + _drawBufferApplyMask = false; _readBuffer = GL_NONE; + _readBufferApplyMask = false; + _clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; _clearColor.set(0.0f,0.0f,0.0f,0.0f); _clearAccum.set(0.0f,0.0f,0.0f,0.0f); @@ -93,7 +101,9 @@ RenderStage::RenderStage(const RenderStage& rhs,const osg::CopyOp& copyop): _postRenderList(rhs._postRenderList), _viewport(rhs._viewport), _drawBuffer(rhs._drawBuffer), + _drawBufferApplyMask(rhs._drawBufferApplyMask), _readBuffer(rhs._readBuffer), + _readBufferApplyMask(rhs._readBufferApplyMask), _clearMask(rhs._clearMask), _colorMask(rhs._colorMask), _clearColor(rhs._clearColor), @@ -226,6 +236,7 @@ void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo) osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap(); + // compute the required dimensions int width = static_cast(_viewport->x() + _viewport->width()); int height = static_cast(_viewport->y() + _viewport->height()); @@ -419,6 +430,7 @@ void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo) } +#if FORCE_DEPTH_ATTACHMENT if (!depthAttached) { fbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_DEPTH_COMPONENT24))); @@ -428,10 +440,13 @@ void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo) osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_DEPTH_COMPONENT24, samples, colorSamples))); } + depthAttached = true; } +#endif +#if FORCE_COLOR_ATTACHMENT if (!colorAttached) - { + { fbo->setAttachment(osg::Camera::COLOR_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_RGB))); if (fbo_multisample.valid()) { @@ -439,12 +454,26 @@ void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo) osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_RGB, samples, colorSamples))); } + colorAttached = true; } +#endif fbo->apply(state); - + + // If no color attachment make sure to set glDrawBuffer/glReadBuffer to none + // otherwise glCheckFramebufferStatusEXT will fail + // It has to be done after call to glBindFramebuffer (fbo->apply) + // and before call to glCheckFramebufferStatus + if ( !colorAttached ) + { + setDrawBuffer( GL_NONE, true ); + glDrawBuffer( GL_NONE ); + setReadBuffer( GL_NONE, true ); + glReadBuffer( GL_NONE ); + } + GLenum status = fbo_ext->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { osg::notify(osg::NOTICE)<<"RenderStage::runCameraSetUp(), FBO setup failed, FBO status= 0x"<setDrawBuffer(GL_BACK); _requiresFlush = true; @@ -1082,13 +1081,13 @@ void SceneView::draw() break; case(osg::DisplaySettings::ANAGLYPHIC): { - if( getDrawBufferValue() != GL_NONE) + if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER ) ) { - _renderStageLeft->setDrawBuffer(getDrawBufferValue()); - _renderStageLeft->setReadBuffer(getDrawBufferValue()); + _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageLeft->setReadBuffer(_camera->getDrawBuffer()); - _renderStageRight->setDrawBuffer(getDrawBufferValue()); - _renderStageRight->setReadBuffer(getDrawBufferValue()); + _renderStageRight->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageRight->setReadBuffer(_camera->getDrawBuffer()); } _localStateSet->setAttribute(getViewport()); @@ -1142,13 +1141,13 @@ void SceneView::draw() break; case(osg::DisplaySettings::HORIZONTAL_SPLIT): { - if( getDrawBufferValue() != GL_NONE) + if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) ) { - _renderStageLeft->setDrawBuffer(getDrawBufferValue()); - _renderStageLeft->setReadBuffer(getDrawBufferValue()); + _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageLeft->setReadBuffer(_camera->getDrawBuffer()); - _renderStageRight->setDrawBuffer(getDrawBufferValue()); - _renderStageRight->setReadBuffer(getDrawBufferValue()); + _renderStageRight->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageRight->setReadBuffer(_camera->getDrawBuffer()); } // ensure that all color planes are active. @@ -1191,13 +1190,13 @@ void SceneView::draw() break; case(osg::DisplaySettings::VERTICAL_SPLIT): { - if( getDrawBufferValue() != GL_NONE) + if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) ) { - _renderStageLeft->setDrawBuffer(getDrawBufferValue()); - _renderStageLeft->setReadBuffer(getDrawBufferValue()); + _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageLeft->setReadBuffer(_camera->getDrawBuffer()); - _renderStageRight->setDrawBuffer(getDrawBufferValue()); - _renderStageRight->setReadBuffer(getDrawBufferValue()); + _renderStageRight->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageRight->setReadBuffer(_camera->getDrawBuffer()); } // ensure that all color planes are active. @@ -1241,10 +1240,10 @@ void SceneView::draw() case(osg::DisplaySettings::RIGHT_EYE): case(osg::DisplaySettings::LEFT_EYE): { - if( getDrawBufferValue() != GL_NONE) + if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) ) { - _renderStage->setDrawBuffer(getDrawBufferValue()); - _renderStage->setReadBuffer(getDrawBufferValue()); + _renderStage->setDrawBuffer(_camera->getDrawBuffer()); + _renderStage->setReadBuffer(_camera->getDrawBuffer()); } // ensure that all color planes are active. @@ -1268,12 +1267,12 @@ void SceneView::draw() break; case(osg::DisplaySettings::VERTICAL_INTERLACE): { - if( getDrawBufferValue() != GL_NONE) + if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) ) { - _renderStageLeft->setDrawBuffer(getDrawBufferValue()); - _renderStageLeft->setReadBuffer(getDrawBufferValue()); - _renderStageRight->setDrawBuffer(getDrawBufferValue()); - _renderStageRight->setReadBuffer(getDrawBufferValue()); + _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageLeft->setReadBuffer(_camera->getDrawBuffer()); + _renderStageRight->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageRight->setReadBuffer(_camera->getDrawBuffer()); } _localStateSet->setAttribute(getViewport()); @@ -1345,13 +1344,13 @@ void SceneView::draw() break; case(osg::DisplaySettings::HORIZONTAL_INTERLACE): { - if( getDrawBufferValue() != GL_NONE) - { - _renderStageLeft->setDrawBuffer(getDrawBufferValue()); - _renderStageLeft->setReadBuffer(getDrawBufferValue()); - _renderStageRight->setDrawBuffer(getDrawBufferValue()); - _renderStageRight->setReadBuffer(getDrawBufferValue()); - } + if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) ) + { + _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageLeft->setReadBuffer(_camera->getDrawBuffer()); + _renderStageRight->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageRight->setReadBuffer(_camera->getDrawBuffer()); + } _localStateSet->setAttribute(getViewport()); // ensure that all color planes are active. @@ -1422,13 +1421,13 @@ void SceneView::draw() break; case(osg::DisplaySettings::CHECKERBOARD): { - if( getDrawBufferValue() != GL_NONE) - { - _renderStageLeft->setDrawBuffer(getDrawBufferValue()); - _renderStageLeft->setReadBuffer(getDrawBufferValue()); - _renderStageRight->setDrawBuffer(getDrawBufferValue()); - _renderStageRight->setReadBuffer(getDrawBufferValue()); - } + if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) ) + { + _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageLeft->setReadBuffer(_camera->getDrawBuffer()); + _renderStageRight->setDrawBuffer(_camera->getDrawBuffer()); + _renderStageRight->setReadBuffer(_camera->getDrawBuffer()); + } _localStateSet->setAttribute(getViewport()); // ensure that all color planes are active. @@ -1508,13 +1507,13 @@ void SceneView::draw() { // Need to restore draw buffer when toggling Stereo off. - if( _camera->getDrawBuffer() != GL_NONE) + if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER ) ) { _renderStage->setDrawBuffer(_camera->getDrawBuffer()); _renderStage->setReadBuffer(_camera->getDrawBuffer()); } - if( _camera->getReadBuffer() != GL_NONE) + if( 0 == ( _camera->getInheritanceMask() & READ_BUFFER ) ) { _renderStage->setReadBuffer(_camera->getReadBuffer()); }