/*****************************************************************************
 * $LastChangedDate: 2009-11-25 16:56:38 -0500 (Wed, 25 Nov 2009) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Shader functions.
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#define SHADER_SHADER_FUNCS_CC 1
#include "base/module.hh"
using namespace base;
#include "gfx/module.hh"
#include "gfx/osg.hh"
using namespace gfx;
#include "fx/module.hh"
#include "fx/texture.hh"
using namespace fx;
#include "shader/module.hh"
#include "shader/conf.hh"
#include "shader/shader_funcs.hh"
#include "shader/shader_name.hh"

#include <osg/Fog>

namespace shader {

/*****************************************************************************
 * Disable shader on a node.
 *****************************************************************************/
void
DisableShader( osg::StateSet& stateSet )
{
  //stateSet.removeAttribute( osg::StateAttribute::PROGRAM );  // doesn't work in this case
    stateSet.setAttributeAndModes( new osg::Program, osg::StateAttribute::ON );
}

/*****************************************************************************
 * Reset MOST (not all) shader uniforms.
 *****************************************************************************/
void
ResetShaderUniformsForModel( Node& node )
{
    if ( SHADER_CONF.mEnableShaders )
    {
        // -- see shader_names.hh --
        SetShaderUniform<bool>( SHADER_UNIFORM_NAME_SHADER_MODE_TEXTURE, true,  node );
        SetShaderUniform<int>(  SHADER_UNIFORM_NAME_SHADOW_MODE,         0,     node );
        SetShaderUniform<bool>( SHADER_UNIFORM_NAME_GLASS,               false, node );
        SetShaderUniform<bool>( SHADER_UNIFORM_NAME_ALPHA_TEX,           false, node );
        SetShaderUniform<fp>(   SHADER_UNIFORM_NAME_ALPHA_BIAS,          0.0f,  node );
        SetShaderUniform<int>(  SHADER_UNIFORM_NAME_TEXTURE_0,           0,     node );  // int, not uint
        SetShaderUniform<int>(  SHADER_UNIFORM_NAME_TEXTURE_SHADOW,      fx::defs::TEXTURE_UNIT_SHADOW, node );
    }
}

/*****************************************************************************
 * Reset ALL shader uniforms.
 * Some uniforms are attached only to the root node.
 *****************************************************************************/
void
ResetShaderUniformsForRootNode( Node& node )
{
    if ( SHADER_CONF.mEnableShaders )
    {
        // -- see shader_names.hh --
        ResetShaderUniformsForModel( node );
        SetShaderUniform<fp>(         SHADER_UNIFORM_NAME_BRIGHTNESS, 1.0f, node );
        SetShaderUniform<osg::Vec4f>( SHADER_UNIFORM_NAME_BASE_AMBIENT, osg::Vec4f(0,0,0,0), node );
    }
}

/*****************************************************************************
 * Set fog parameters.
 *****************************************************************************/
void
SetShaderFog( Node& node, const fp fogDensity, const RGBA fogColor )
{
    if ( SHADER_CONF.mEnableFog )
    {
        RefPtr<osg::StateSet> stateSet = node.getOrCreateStateSet();

        // Set both forms of fog in case a model has HW lighting.

        // Shader fog:
        SetShaderUniform<fp>( SHADER_UNIFORM_NAME_FOG_DENSITY, fogDensity, stateSet );
        // (fog color/mode aren't implemented in shader yet)

        // HW fog:
        RefPtr<osg::Fog> fog = new osg::Fog;
        fog->setColor( RGBA2VEC4F( fogColor ) );
        fog->setDensity( fogDensity );
      //fog->setMode( fogMode );
        stateSet->setAttributeAndModes( fog.get() );
        stateSet->setMode( GL_FOG, osg::StateAttribute::ON );
    }
}

} // namespace shader
