247 lines
7.9 KiB
Plaintext
247 lines
7.9 KiB
Plaintext
|
/* -*-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 single-child group.
|
||
|
Create an instance of your desired effect, add it to your scene graph (it
|
||
|
is a Node) and call its setChild() method to set its 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::Node {
|
||
|
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 const child node */
|
||
|
inline const osg::Node *getChild() const;
|
||
|
|
||
|
/** get the child node */
|
||
|
inline osg::Node *getChild();
|
||
|
|
||
|
/** set the child node */
|
||
|
inline void setChild(osg::Node *child);
|
||
|
|
||
|
/** 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);
|
||
|
|
||
|
virtual void traverse(osg::NodeVisitor &nv);
|
||
|
|
||
|
protected:
|
||
|
virtual ~Effect() {}
|
||
|
Effect &operator=(const Effect &) { return *this; }
|
||
|
|
||
|
virtual bool computeBound() const;
|
||
|
|
||
|
/** 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::Node> child_;
|
||
|
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 const osg::Node *Effect::getChild() const
|
||
|
{
|
||
|
return child_.get();
|
||
|
}
|
||
|
|
||
|
inline osg::Node *Effect::getChild()
|
||
|
{
|
||
|
return child_.get();
|
||
|
}
|
||
|
|
||
|
inline void Effect::setChild(osg::Node *child)
|
||
|
{
|
||
|
child_ = child;
|
||
|
setNumChildrenRequiringUpdateTraversal(0);
|
||
|
setNumChildrenWithCullingDisabled(0);
|
||
|
setNumChildrenWithOccluderNodes(0);
|
||
|
if (child) {
|
||
|
if (child->getNumChildrenRequiringUpdateTraversal() > 0 || child->getUpdateCallback())
|
||
|
setNumChildrenRequiringUpdateTraversal(1);
|
||
|
if (child->getNumChildrenWithCullingDisabled() > 0 || !child->getCullingActive())
|
||
|
setNumChildrenWithCullingDisabled(1);
|
||
|
if (child->getNumChildrenWithOccluderNodes() > 0 || dynamic_cast<osg::OccluderNode *>(child))
|
||
|
setNumChildrenWithOccluderNodes(1);
|
||
|
}
|
||
|
dirtyBound();
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|