Commit d5f5fb8b authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[FIX #380] - WShader can now also be used directly for statesets in the...

[FIX #380] - WShader can now also be used directly for statesets in the context of own drawable implementations.
parent 809c2ad3
......@@ -83,6 +83,12 @@ void WShader::apply( osg::ref_ptr< osg::Node > node )
node->addUpdateCallback( osg::ref_ptr< SafeUpdaterCallback >( new SafeUpdaterCallback( this ) ) );
}
void WShader::applyDirect( osg::State& state ) // NOLINT <- ensure this matches the official OSG API by using a non-const ref
{
updatePrograms();
osg::Program::apply( state );
}
void WShader::deactivate( osg::ref_ptr< osg::Node > node )
{
// set the shader attribute
......@@ -102,76 +108,85 @@ void WShader::reload()
m_reload = true;
}
WShader::SafeUpdaterCallback::SafeUpdaterCallback( WShader* shader ):
m_shader( shader )
{
}
void WShader::SafeUpdaterCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
void WShader::reloadShader()
{
// is it needed to do something here?
if ( m_shader->m_deactivated )
try
{
// remove the shaders
m_shader->removeShader( m_shader->m_vertexShader );
m_shader->removeShader( m_shader->m_fragmentShader );
m_shader->removeShader( m_shader->m_geometryShader );
}
removeShader( m_vertexShader );
removeShader( m_fragmentShader );
removeShader( m_geometryShader );
// reload the sources and set the shader
// vertex shader
WLogger::getLogger()->addLogMessage( "Reloading vertex shader \"" + m_name + "-vertex.glsl\"", "WShader", LL_DEBUG );
std::string source = processShader( m_name + "-vertex.glsl" );
if ( source != "" )
{
m_vertexShader->setShaderSource( source );
addShader( m_vertexShader );
}
else if ( m_shader->m_reload )
{
try
// fragment shader
WLogger::getLogger()->addLogMessage( "Reloading fragment shader \"" + m_name + "-fragment.glsl\"", "WShader", LL_DEBUG );
source = processShader( m_name + "-fragment.glsl" );
if ( source != "" )
{
// remove the shaders
m_shader->removeShader( m_shader->m_vertexShader );
m_shader->removeShader( m_shader->m_fragmentShader );
m_shader->removeShader( m_shader->m_geometryShader );
// reload the sources and set the shader
// vertex shader
WLogger::getLogger()->addLogMessage( "Reloading vertex shader \"" + m_shader->m_name + "-vertex.glsl\"", "WShader", LL_DEBUG );
std::string source = m_shader->processShader( m_shader->m_name + "-vertex.glsl" );
if ( source != "" )
{
m_shader->m_vertexShader->setShaderSource( source );
m_shader->addShader( m_shader->m_vertexShader );
}
m_fragmentShader->setShaderSource( source );
addShader( m_fragmentShader );
}
// fragment shader
WLogger::getLogger()->addLogMessage( "Reloading fragment shader \"" + m_shader->m_name + "-fragment.glsl\"", "WShader", LL_DEBUG );
source = m_shader->processShader( m_shader->m_name + "-fragment.glsl" );
if ( source != "" )
{
m_shader->m_fragmentShader->setShaderSource( source );
m_shader->addShader( m_shader->m_fragmentShader );
}
// Geometry Shader
WLogger::getLogger()->addLogMessage( "Reloading geometry shader \"" + m_name + "-geometry.glsl\"", "WShader", LL_DEBUG );
source = processShader( m_name + "-geometry.glsl", true );
if ( source != "" )
{
m_geometryShader->setShaderSource( source );
addShader( m_geometryShader );
}
// Geometry Shader
WLogger::getLogger()->addLogMessage( "Reloading geometry shader \"" + m_shader->m_name + "-geometry.glsl\"", "WShader", LL_DEBUG );
source = m_shader->processShader( m_shader->m_name + "-geometry.glsl", true );
if ( source != "" )
{
m_shader->m_geometryShader->setShaderSource( source );
m_shader->addShader( m_shader->m_geometryShader );
}
m_shaderLoaded = true;
}
catch( const std::exception& e )
{
m_shaderLoaded = false;
m_shader->m_shaderLoaded = true;
}
catch( const std::exception& e )
{
m_shader->m_shaderLoaded = false;
WLogger::getLogger()->addLogMessage( "Problem loading shader.", "WShader", LL_ERROR );
WLogger::getLogger()->addLogMessage( "Problem loading shader.", "WShader", LL_ERROR );
// clean up the mess
removeShader( m_vertexShader );
removeShader( m_fragmentShader );
removeShader( m_geometryShader );
}
// clean up the mess
m_shader->removeShader( m_shader->m_vertexShader );
m_shader->removeShader( m_shader->m_fragmentShader );
m_shader->removeShader( m_shader->m_geometryShader );
}
// everything done now.
m_reload = false;
}
// everything done now.
m_shader->m_reload = false;
void WShader::updatePrograms()
{
// is it needed to do something here?
if ( m_deactivated )
{
// remove the shaders
removeShader( m_vertexShader );
removeShader( m_fragmentShader );
removeShader( m_geometryShader );
}
else if ( m_reload )
{
reloadShader();
}
}
WShader::SafeUpdaterCallback::SafeUpdaterCallback( WShader* shader ):
m_shader( shader )
{
}
void WShader::SafeUpdaterCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
{
m_shader->updatePrograms();
// forward the call
traverse( node, nv );
......
......@@ -66,6 +66,14 @@ public:
*/
virtual void apply( osg::ref_ptr< osg::Node > node );
/**
* If enabled, activate our program in the GL pipeline, performing any rebuild operations that might be pending. In addition to the standard
* OSG functionality, it also loads/reloads the shader source from file.
*
* \param state the state to apply the shader program to.
*/
virtual void applyDirect( osg::State& state ); // NOLINT <- ensure this matches the official OSG API by using a non-const ref
/**
* Removes the shader from the specified node.
*
......@@ -113,6 +121,16 @@ protected:
*/
std::string processShader( const std::string filename, bool optional = false, int level = 0 );
/**
* This completely reloads the shader file and processes it. It also resets m_reload to false.
*/
void reloadShader();
/**
* Handles all state changes in m_reload and m_deactivated. It ensure that the shader programs are bound properly or deactivated.
*/
void updatePrograms();
/**
* String that stores the location of all shader files
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment