/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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.
*/
//osgFX - Copyright (C) 2003 Marco Jez

#ifndef OSGFX_ANISOTROPICLIGHTING_
#define OSGFX_ANISOTROPICLIGHTING_

#include <osgFX/Export>
#include <osgFX/Effect>

#include <osg/ref_ptr>
#include <osg/Texture2D>

namespace osgFX
{

    /**
     This single-pass effect implements a sort of anisotropic 
     lighting that replaces the standard OpenGL lighting model.
     The final color of vertices is not computed directly, it is 
     the result of a texture lookup on a user-supplied lighting 
     image map. A vertex program is used to compute the s and t 
     texture coordinates as follows: s = (N dot H) ; t = (N dot L) 
     where N is the vertex normal, L is the light-to-vertex vector, 
     H is the half-way vector. This is a good example of how you 
     can use the State::getInitialViewMatrix() method to retrieve 
     the view matrix and perform view-dependant effects without 
     fakes of any kind.
     This effect requires the ARB_vertex_program extension.
     */
    class OSGFX_EXPORT AnisotropicLighting: public Effect {
    public:
        AnisotropicLighting();
        AnisotropicLighting(const AnisotropicLighting &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);

        META_Effect(osgFX, AnisotropicLighting, 
        
            "Anisotropic Lighting", 
            
            "This single-pass effect implements a sort of anisotropic "
            "lighting that replaces the standard OpenGL lighting model.\n"
            "The final color of vertices is not computed directly, it is "
            "the result of a texture lookup on a user-supplied lighting "
            "image map. A vertex program is used to compute the s and t "
            "texture coordinates as follows: s = (N dot H) ; t = (N dot L) "
            "where N is the vertex normal, L is the light-to-vertex vector, "
            "H is the half-way vector. This is a good example of how you "
            "can use the State::getInitialViewMatrix() method to retrieve "
            "the view matrix and perform view-dependant effects without "
            "fakes of any kind.\n"
            "This effect requires the ARB_vertex_program extension.", 
            
            "Marco Jez");
            
        
        /** get the lighting map */
        inline osg::Image *getLightingMap();
        
        /** get the const lighting map */
        inline const osg::Image *getLightingMap() const;
        
        /** set the lighting map */
        inline void setLightingMap(osg::Image *image);

        /** get the OpenGL light number */
        inline int getLightNumber() const;
        
        /** set the OpenGL light number that will be used in lighting computations */
        inline void setLightNumber(int n);

    protected:
        virtual ~AnisotropicLighting() {}
        AnisotropicLighting &operator=(const AnisotropicLighting &) { return *this; }

        bool define_techniques();

    private:
        int lightnum_;
        osg::ref_ptr<osg::Texture2D> texture_;
    };

    // INLINE METHODS
    
    inline osg::Image *AnisotropicLighting::getLightingMap()
    {
        return texture_->getImage();
    }
    
    inline const osg::Image *AnisotropicLighting::getLightingMap() const
    {
        return texture_->getImage();
    }
    
    inline void AnisotropicLighting::setLightingMap(osg::Image *image)
    {
        texture_->setImage(image);
    }
    
    inline int AnisotropicLighting::getLightNumber() const
    {
        return lightnum_;
    }
    
    inline void AnisotropicLighting::setLightNumber(int n)
    {
        lightnum_ = n;
        dirtyTechniques();
    }

}

#endif
