/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSGSHADOW_SOFTSHADOWMAP
#define OSGSHADOW_SOFTSHADOWMAP 1

#include <osg/Camera>
#include <osg/Material>
#include <osg/MatrixTransform>
#include <osg/LightSource>

#include <osgShadow/ShadowMap>

namespace osgShadow {

/** SoftShadowMap provides an implementation of soft shadows with shadow maps.*/
class OSGSHADOW_EXPORT SoftShadowMap : public ShadowMap
{
    public :
        SoftShadowMap();

        SoftShadowMap(const SoftShadowMap& es, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);

        META_Object(osgShadow, SoftShadowMap);

        /** Set the values for width of the soft penumbra the shader will use.
         *  Zero is for hard shadow (no penumbra). 0.01 is already very soft penumbra.
         *  Default is 0.005.*/
        void setSoftnessWidth(float softnessWidth);

        /** Get the value used for width of the soft penumbra in the shader.*/
        float getSoftnessWidth() const { return _softnessWidth; }

        /** Set the values for jittering scale the shader will use.
         *  Zero is no jittering (i.e. see the banding in penumbra)
         *  High values (>64) cause 'pixelization' of the penumbra.
         *  Usually but not necessarily power of two number.
         *  Default is 32. */
        void setJitteringScale(float jitteringScale);

        /** Get the value used for jittering scale in the shader.*/
        float getJitteringScale() const { return _jitteringScale; }

        /** Set the texture unit that the jitter texture will be applied on.*/
        void setJitterTextureUnit(unsigned int jitterTextureUnit);

        /** Get the texture unit that the jitter texture will be applied on.*/
        unsigned int getJitterTextureUnit() const { return _jitterTextureUnit; }


        /** Add a small bias to the z-value, this can reduce 
         *  shadow acne problem. 
         *  This is the same as calling setPolygonOffset(osg::Vec2(bias,0));
         *  Suitable values are 0-0.005 
         *  Default is 0. */
        void setBias(float bias) { setPolygonOffset(osg::Vec2(bias,0)); }
        
        /** Return the bias value */
        float getBias() const { return getPolygonOffset().x(); }


    protected:
        virtual ~SoftShadowMap(void) {};
        
        /** Create the managed Uniforms */
        void createUniforms();
        void createShaders();
        void initJittering(osg::StateSet *ss);
        
        osg::ref_ptr<osg::Uniform>      _softnessWidthUniform;
        osg::ref_ptr<osg::Uniform>      _jitteringScaleUniform;
        float                           _softnessWidth;
        float                           _jitteringScale;
        unsigned int                    _jitterTextureUnit;

    

};

}

#endif
