218 lines
7.0 KiB
C++
218 lines
7.0 KiB
C++
/* -*-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_EFFECT_
|
|
#define OSGFX_EFFECT_
|
|
|
|
#include <osgFX/Export>
|
|
#include <osgFX/Technique>
|
|
|
|
#include <osg/buffered_value>
|
|
#include <osg/ref_ptr>
|
|
#include <osg/Node>
|
|
#include <osg/Group>
|
|
#include <osg/Geode>
|
|
#include <osg/OccluderNode>
|
|
|
|
#include <vector>
|
|
|
|
/**
|
|
An helper macro that defines the methods like effectName() and effectDescription()
|
|
making them return the strings passed as parameters, after the usual library name
|
|
and class name.
|
|
*/
|
|
#define META_Effect(library, classname, effectname, effectdescription, effectauthor) \
|
|
META_Node(library, classname) \
|
|
virtual const char *effectName() const { return effectname; } \
|
|
virtual const char *effectDescription() const { return effectdescription; } \
|
|
virtual const char *effectAuthor() const { return effectauthor; }
|
|
|
|
|
|
namespace osgFX
|
|
{
|
|
|
|
/**
|
|
The base class for special effects. An effect is basically a collection of
|
|
state attributes and an interface for configuring them in a predefined
|
|
fashion. The Effect class does more however, as it handles multipass
|
|
rendering transparently and it allows more than one "technique" to be
|
|
defined. Each technique tries to implement the effect in a different way,
|
|
often using different OpenGL extensions. The active technique can be
|
|
selected either manually, with selectTechnique(), or automatically, in which
|
|
case the first technique that is supported by all active rendering contexts
|
|
is chosen.
|
|
If you are an Effect user, then simply use it as a node group. Create an
|
|
instance of your desired effect, add it to your scene graph and call its
|
|
addChild() method to add a child node as you would do with a Group.
|
|
If you are an Effect developer, you will have to implement the method
|
|
define_techniques() to define the different techniques that can be used
|
|
for obtaining the desired effect. In define_techniques() you will usually
|
|
create one or more instances of custom classes derived from Technique and
|
|
you will add them to the effect with addTechnique(). The order is important:
|
|
techniques added first will have higher priority and will be used first as
|
|
soon as all rendering contexts support it.
|
|
*/
|
|
class OSGFX_EXPORT Effect: public osg::Group {
|
|
public:
|
|
Effect();
|
|
Effect(const Effect ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY);
|
|
|
|
virtual inline bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast<const Effect *>(obj) != NULL; }
|
|
virtual inline const char *libraryName() const { return "osgFX"; }
|
|
virtual inline const char *className() const { return "Effect"; }
|
|
|
|
/** get the name of this effect */
|
|
virtual const char *effectName() const = 0;
|
|
|
|
/** get a brief description of this effect */
|
|
virtual const char *effectDescription() const = 0;
|
|
|
|
/** get the effect author's name */
|
|
virtual const char *effectAuthor() const = 0;
|
|
|
|
/** get whether the effect is enabled or not */
|
|
inline bool getEnabled() const;
|
|
|
|
/** set whether the effect is enabled or not */
|
|
inline void setEnabled(bool v);
|
|
|
|
/**
|
|
optional: set effect parameters to produce a visually significant
|
|
result to be used in demo applications like osgfxbrowser. Default
|
|
is to do nothing.
|
|
*/
|
|
inline virtual void setUpDemo() {}
|
|
|
|
/** get the number of techniques defined for this effect */
|
|
inline int getNumTechniques() const;
|
|
|
|
/** get the i-th technique */
|
|
inline Technique *getTechnique(int i);
|
|
|
|
/** get the i-th const technique */
|
|
inline const Technique *getTechnique(int i) const;
|
|
|
|
/** get the index of the currently selected technique */
|
|
inline int getSelectedTechnique() const;
|
|
|
|
enum TechniqueSelection {
|
|
AUTO_DETECT = -1
|
|
};
|
|
|
|
/** select a technique or enable automatic detection */
|
|
inline void selectTechnique(int i = AUTO_DETECT);
|
|
|
|
/** custom traversal */
|
|
virtual void traverse(osg::NodeVisitor &nv);
|
|
|
|
/** default traversal */
|
|
inline void inherited_traverse(osg::NodeVisitor &nv);
|
|
|
|
protected:
|
|
virtual ~Effect();
|
|
Effect &operator=(const Effect &) { return *this; }
|
|
|
|
/** force rebuilding of techniques on next traversal */
|
|
inline void dirtyTechniques();
|
|
|
|
/** add a technique to the effect */
|
|
inline void addTechnique(Technique *tech);
|
|
|
|
/**
|
|
abstract method to be implemented in derived classes; its purpose
|
|
if to create the techniques that can be used for obtaining the
|
|
desired effect. You will usually call addTechnique() inside
|
|
this method.
|
|
*/
|
|
virtual bool define_techniques() = 0;
|
|
|
|
private:
|
|
friend class Validator;
|
|
|
|
bool enabled_;
|
|
|
|
typedef std::vector<osg::ref_ptr<Technique> > Technique_list;
|
|
Technique_list techs_;
|
|
|
|
mutable osg::buffered_value<int> sel_tech_;
|
|
|
|
// use int instead of bool to avoid errors
|
|
mutable osg::buffered_value<int> tech_selected_;
|
|
|
|
int global_sel_tech_;
|
|
|
|
bool techs_defined_;
|
|
|
|
osg::ref_ptr<osg::Geode> dummy_for_validation_;
|
|
|
|
void build_dummy_node();
|
|
};
|
|
|
|
// INLINE METHODS
|
|
|
|
inline bool Effect::getEnabled() const
|
|
{
|
|
return enabled_;
|
|
}
|
|
|
|
inline void Effect::setEnabled(bool v)
|
|
{
|
|
enabled_ = v;
|
|
}
|
|
|
|
inline int Effect::getNumTechniques() const
|
|
{
|
|
return static_cast<int>(techs_.size());
|
|
}
|
|
|
|
inline Technique *Effect::getTechnique(int i)
|
|
{
|
|
return techs_[i].get();
|
|
}
|
|
|
|
inline const Technique *Effect::getTechnique(int i) const
|
|
{
|
|
return techs_[i].get();
|
|
}
|
|
|
|
inline int Effect::getSelectedTechnique() const
|
|
{
|
|
return global_sel_tech_;
|
|
}
|
|
|
|
inline void Effect::selectTechnique(int i)
|
|
{
|
|
global_sel_tech_ = i;
|
|
}
|
|
|
|
inline void Effect::addTechnique(Technique *tech)
|
|
{
|
|
techs_.push_back(tech);
|
|
}
|
|
|
|
inline void Effect::dirtyTechniques()
|
|
{
|
|
techs_defined_ = false;
|
|
}
|
|
|
|
inline void Effect::inherited_traverse(osg::NodeVisitor &nv)
|
|
{
|
|
typedef osg::Group inherited;
|
|
inherited::traverse(nv);
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|