@ -84,7 +84,8 @@ namespace MWRender
} ;
// Set up alpha blending to Additive mode to avoid issues caused by transparent objects writing onto the alpha value of the FBO
// Set up alpha blending mode to avoid issues caused by transparent objects writing onto the alpha value of the FBO
// This makes the RTT have premultiplied alpha, though, so the source blend factor must be GL_ONE when it's applied
class SetUpBlendVisitor : public osg : : NodeVisitor
{
public :
@ -94,22 +95,40 @@ namespace MWRender
void apply ( osg : : Node & node ) override
{
if ( osg : : StateSet* stateset = node . getStateSet ( ) )
if ( osg : : ref_ptr< osg : : StateSet > stateset = node . getStateSet ( ) )
{
osg : : ref_ptr < osg : : StateSet > newStateSet ;
if ( stateset - > getAttribute ( osg : : StateAttribute : : BLENDFUNC ) | | stateset - > getBinNumber ( ) = = osg : : StateSet : : TRANSPARENT_BIN )
{
osg : : ref_ptr < osg : : StateSet > newStateSet = new osg : : StateSet ( * stateset , osg : : CopyOp : : SHALLOW_COPY ) ;
osg : : BlendFunc * blendFunc = static_cast < osg : : BlendFunc * > ( stateset - > getAttribute ( osg : : StateAttribute : : BLENDFUNC ) ) ;
osg : : ref_ptr < osg : : BlendFunc > newBlendFunc = blendFunc ? new osg : : BlendFunc ( * blendFunc ) : new osg : : BlendFunc ;
newBlendFunc - > setDestinationAlpha ( osg : : BlendFunc : : ONE ) ;
newStateSet - > setAttribute ( newBlendFunc , osg : : StateAttribute : : ON ) ;
node . setStateSet ( newStateSet ) ;
if ( blendFunc )
{
newStateSet = new osg : : StateSet ( * stateset , osg : : CopyOp : : SHALLOW_COPY ) ;
node . setStateSet ( newStateSet ) ;
osg : : ref_ptr < osg : : BlendFunc > newBlendFunc = new osg : : BlendFunc ( * blendFunc ) ;
newStateSet - > setAttribute ( newBlendFunc , osg : : StateAttribute : : ON ) ;
// I *think* (based on some by-hand maths) that the RGB and dest alpha factors are unchanged, and only dest determines source alpha factor
// This has the benefit of being idempotent if we assume nothing used glBlendFuncSeparate before we touched it
if ( blendFunc - > getDestination ( ) = = osg : : BlendFunc : : ONE_MINUS_SRC_ALPHA )
newBlendFunc - > setSourceAlpha ( osg : : BlendFunc : : ONE ) ;
else if ( blendFunc - > getDestination ( ) = = osg : : BlendFunc : : ONE )
newBlendFunc - > setSourceAlpha ( osg : : BlendFunc : : ZERO ) ;
// Other setups barely exist in the wild and aren't worth supporting as they're not equippable gear
else
Log ( Debug : : Info ) < < " Unable to adjust blend mode for character preview. Source factor 0x " < < std : : hex < < blendFunc - > getSource ( ) < < " , destination factor 0x " < < blendFunc - > getDestination ( ) < < std : : dec ;
}
}
if ( stateset - > getMode ( GL_BLEND ) & osg : : StateAttribute : : ON )
{
if ( ! newStateSet )
{
newStateSet = new osg : : StateSet ( * stateset , osg : : CopyOp : : SHALLOW_COPY ) ;
node . setStateSet ( newStateSet ) ;
}
// Disable noBlendAlphaEnv
stateset - > setTextureMode ( 7 , GL_TEXTURE_2D , osg : : StateAttribute : : OFF ) ;
stateset - > addUniform ( mNoAlphaUniform ) ;
newStateS et- > setTextureMode ( 7 , GL_TEXTURE_2D , osg : : StateAttribute : : OFF ) ;
newStateS et- > addUniform ( mNoAlphaUniform ) ;
}
}
traverse ( node ) ;
@ -134,6 +153,7 @@ namespace MWRender
mTexture - > setInternalFormat ( GL_RGBA ) ;
mTexture - > setFilter ( osg : : Texture : : MIN_FILTER , osg : : Texture : : LINEAR ) ;
mTexture - > setFilter ( osg : : Texture : : MAG_FILTER , osg : : Texture : : LINEAR ) ;
mTexture - > setUserValue ( " premultiplied alpha " , true ) ;
mCamera = new osg : : Camera ;
// hints that the camera is not relative to the master camera