From 174f9bbfe0288f551aa9ce3b8dd0ff2d7bc67518 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 19 Jun 2008 11:09:20 +0000 Subject: [PATCH] From Michael Platings and Robert Osfield, added support for controlling, via StateSet::setNestedRenderBin(bool) whether the new RenderBin should be nested with the existing RenderBin, or be nested with the enclosing RenderStage. --- include/osg/StateSet | 15 ++++++++++++++- include/osgUtil/CullVisitor | 20 ++++++++++++++++---- src/osg/StateSet.cpp | 8 +++++--- src/osgUtil/CullVisitor.cpp | 2 ++ src/osgWrappers/osg/StateSet.cpp | 13 +++++++++++++ 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/include/osg/StateSet b/include/osg/StateSet index 1ce25bf01..03ea009c7 100644 --- a/include/osg/StateSet +++ b/include/osg/StateSet @@ -1,4 +1,4 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -363,6 +363,18 @@ class OSG_EXPORT StateSet : public Object /** Get the render bin name.*/ inline const std::string& getBinName() const { return _binName; } + /** By default render bins will be nested within each other dependent + * upon where they are set in the scene graph. This can be problematic + * if a transparent render bin is attached to an opaque render bin + * which is attached to another transparent render bin as these render + * bins will be sorted separately, giving the wrong draw ordering for + * back-to-front transparency. Therefore, to prevent render bins being + * nested, call setNestRenderBins(false). */ + inline void setNestRenderBins(bool val) { _nestRenderBins = val; } + + /** Get whether associated RenderBin should be nested within parents RenderBin.*/ + inline bool getNestRenderBins() const { return _nestRenderBins; } + struct Callback : public virtual osg::Object { @@ -487,6 +499,7 @@ class OSG_EXPORT StateSet : public Object RenderBinMode _binMode; int _binNum; std::string _binName; + bool _nestRenderBins; ref_ptr _updateCallback; unsigned int _numChildrenRequiringUpdateTraversal; diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index 83e0e9f39..33c48ede6 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -1,4 +1,4 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -103,10 +103,16 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac inline void pushStateSet(const osg::StateSet* ss) { _currentStateGraph = _currentStateGraph->find_or_insert(ss); + if (_numberOfEncloseOverrideRenderBinDetails==0 && ss->useRenderBinDetails() && !ss->getBinName().empty()) { - _currentRenderBin = _currentRenderBin->find_or_insert(ss->getBinNumber(),ss->getBinName()); + _renderBinStack.push_back(_currentRenderBin); + + _currentRenderBin = ss->getNestRenderBins() ? + _currentRenderBin->find_or_insert(ss->getBinNumber(),ss->getBinName()) : + _currentRenderBin = _currentRenderBin->getStage()->find_or_insert(ss->getBinNumber(),ss->getBinName()); } + if (ss->getRenderBinMode()==osg::StateSet::OVERRIDE_RENDERBIN_DETAILS) { ++_numberOfEncloseOverrideRenderBinDetails; @@ -126,9 +132,14 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac } if (_numberOfEncloseOverrideRenderBinDetails==0 && ss->useRenderBinDetails() && !ss->getBinName().empty()) { - if (_currentRenderBin->getParent()) + if (_renderBinStack.empty()) { - _currentRenderBin = _currentRenderBin->getParent(); + _currentRenderBin = _currentRenderBin->getStage(); + } + else + { + _currentRenderBin = _renderBinStack.back(); + _renderBinStack.pop_back(); } } _currentStateGraph = _currentStateGraph->_parent; @@ -289,6 +300,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac osg::ref_ptr _rootRenderStage; RenderBin* _currentRenderBin; + std::vector _renderBinStack; value_type _computed_znear; diff --git a/src/osg/StateSet.cpp b/src/osg/StateSet.cpp index 40d35f70d..e89ffaafe 100644 --- a/src/osg/StateSet.cpp +++ b/src/osg/StateSet.cpp @@ -1,4 +1,4 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -81,7 +81,8 @@ bool osg::isTextureMode(StateAttribute::GLMode mode) } StateSet::StateSet(): - Object(true) + Object(true), + _nestRenderBins(true) { _renderingHint = DEFAULT_BIN; @@ -91,7 +92,8 @@ StateSet::StateSet(): setRenderBinToInherit(); } -StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop) +StateSet::StateSet(const StateSet& rhs,const CopyOp& copyop):Object(rhs,copyop), + _nestRenderBins(rhs._nestRenderBins) { _modeList = rhs._modeList; diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 4ae2b021d..003cae574 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -140,6 +140,8 @@ void CullVisitor::reset() // CullStack::reset(); + + _renderBinStack.clear(); _numberOfEncloseOverrideRenderBinDetails = 0; diff --git a/src/osgWrappers/osg/StateSet.cpp b/src/osgWrappers/osg/StateSet.cpp index a9db947ae..908013d28 100644 --- a/src/osgWrappers/osg/StateSet.cpp +++ b/src/osgWrappers/osg/StateSet.cpp @@ -426,6 +426,16 @@ BEGIN_OBJECT_REFLECTOR(osg::StateSet) __C5_std_string_R1__getBinName, "Get the render bin name. ", ""); + I_Method1(void, setNestRenderBins, IN, bool, val, + Properties::NON_VIRTUAL, + __void__setNestRenderBins__bool, + "By default render bins will be nested within each other dependent upon where they are set in the scene graph. ", + "This can be problematic if a transparent render bin is attached to an opaque render bin which is attached to another transparent render bin as these render bins will be sorted separately, giving the wrong draw ordering for back-to-front transparency. Therefore, to prevent render bins being nested, call setNestRenderBins(false). "); + I_Method0(bool, getNestRenderBins, + Properties::NON_VIRTUAL, + __bool__getNestRenderBins, + "Get whether associated RenderBin should be nested within parents RenderBin. ", + ""); I_Method1(void, setUpdateCallback, IN, osg::StateSet::Callback *, ac, Properties::NON_VIRTUAL, __void__setUpdateCallback__Callback_P1, @@ -623,6 +633,9 @@ BEGIN_OBJECT_REFLECTOR(osg::StateSet) I_SimpleProperty(osg::StateSet::ModeList &, ModeList, __ModeList_R1__getModeList, __void__setModeList__ModeList_R1); + I_SimpleProperty(bool, NestRenderBins, + __bool__getNestRenderBins, + __void__setNestRenderBins__bool); I_ArrayProperty(osg::Object *, Parent, __Object_P1__getParent__unsigned_int, 0,