openscenegraph
Effect
Go to the documentation of this file.
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
12*/
13//osgFX - Copyright (C) 2003 Marco Jez
14
15#ifndef OSGFX__effect
16#define OSGFX__effect
17
18#include <osgFX/Export>
19#include <osgFX/Technique>
20
21#include <osg/buffered_value>
22#include <osg/ref_ptr>
23#include <osg/Node>
24#include <osg/Group>
25#include <osg/Geode>
26#include <osg/OccluderNode>
27
28#include <vector>
29
30/**
31 An helper macro that defines the methods like effectName() and effectDescription()
32 making them return the strings passed as parameters, after the usual library name
33 and class name.
34 */
35#define META_Effect(library, classname, effectname, effectdescription, effectauthor) \
36 META_Node(library, classname) \
37 virtual const char *effectName() const { return effectname; } \
38 virtual const char *effectDescription() const { return effectdescription; } \
39 virtual const char *effectAuthor() const { return effectauthor; }
40
41
42namespace osgFX
43{
44
45 /**
46 The base class for special effects. An effect is basically a collection of
47 state attributes and an interface for configuring them in a predefined
48 fashion. The Effect class does more however, as it handles multipass
49 rendering transparently and it allows more than one "technique" to be
50 defined. Each technique tries to implement the effect in a different way,
51 often using different OpenGL extensions. The active technique can be
52 selected either manually, with selectTechnique(), or automatically, in which
53 case the first technique that is supported by all active rendering contexts
54 is chosen.
55 If you are an Effect user, then simply use it as a node group. Create an
56 instance of your desired effect, add it to your scene graph and call its
57 addChild() method to add a child node as you would do with a Group.
58 If you are an Effect developer, you will have to implement the method
59 define_techniques() to define the different techniques that can be used
60 for obtaining the desired effect. In define_techniques() you will usually
61 create one or more instances of custom classes derived from Technique and
62 you will add them to the effect with addTechnique(). The order is important:
63 techniques added first will have higher priority and will be used first as
64 soon as all rendering contexts support it.
65 */
66 class OSGFX_EXPORT Effect: public osg::Group {
67 public:
68 Effect();
69 Effect(const Effect& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
70
71 virtual inline bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const Effect*>(obj) != NULL; }
72 virtual inline const char* libraryName() const { return "osgFX"; }
73 virtual inline const char* className() const { return "Effect"; }
74
75 /** get the name of this Effect */
76 virtual const char *effectName() const = 0;
77
78 /** get a brief description of this Effect*/
79 virtual const char *effectDescription() const = 0;
80
81 /** get the effect author's name */
82 virtual const char *effectAuthor() const = 0;
83
84 /** get whether the effect is enabled or not */
85 inline bool getEnabled() const;
86
87 /** set whether the effect is enabled or not */
88 inline void setEnabled(bool v);
89
90 /**
91 optional: set effect parameters to produce a visually significant
92 result to be used in demo applications like osgfxbrowser. Default
93 is to do nothing.
94 */
95 inline virtual void setUpDemo() {}
96
97 /** get the number of techniques defined for this Effect */
98 inline int getNumTechniques() const;
99
100 /** get the i-th Technique */
101 inline Technique* getTechnique(int i);
102
103 /** get the i-th const Technique */
104 inline const Technique* getTechnique(int i) const;
105
106 /** get the index of the currently selected Technique */
107 inline int getSelectedTechnique() const;
108
109 enum TechniqueSelection {
110 AUTO_DETECT = -1
111 };
112
113 /** select a technique or enable automatic detection */
114 inline void selectTechnique(int i = AUTO_DETECT);
115
116 /** custom traversal */
117 virtual void traverse(osg::NodeVisitor& nv);
118
119 /** default traversal */
120 inline void inherited_traverse(osg::NodeVisitor& nv);
121
122 virtual void resizeGLObjectBuffers(unsigned int maxSize);
123 virtual void releaseGLObjects(osg::State* state = 0) const;
124
125 protected:
126 virtual ~Effect();
127 Effect &operator=(const Effect &) { return *this; }
128
129 /** force rebuilding of techniques on next traversal */
130 inline void dirtyTechniques();
131
132 /** add a technique to the Effect */
133 inline void addTechnique(Technique* tech);
134
135 /**
136 abstract method to be implemented in derived classes; its purpose
137 if to create the techniques that can be used for obtaining the
138 desired effect. You will usually call addTechnique() inside
139 this method.
140 */
141 virtual bool define_techniques() = 0;
142
143 private:
144 friend class Validator;
145
146 bool _enabled;
147
148 typedef std::vector<osg::ref_ptr<Technique> > Technique_list;
149 Technique_list _techs;
150
151 mutable osg::buffered_value<int> _sel_tech;
152
153 // use int instead of bool to avoid errors
154 mutable osg::buffered_value<int> _tech_selected;
155
156 int _global_sel_tech;
157
158 bool _techs_defined;
159
160 osg::ref_ptr<osg::Geode> _dummy_for_validation;
161
162 void build_dummy_node();
163 };
164
165 // INLINE METHODS
166
167 inline bool Effect::getEnabled() const
168 {
169 return _enabled;
170 }
171
172 inline void Effect::setEnabled(bool v)
173 {
174 _enabled = v;
175 }
176
177 inline int Effect::getNumTechniques() const
178 {
179 return static_cast<int>(_techs.size());
180 }
181
182 inline Technique* Effect::getTechnique(int i)
183 {
184 return _techs[i].get();
185 }
186
187 inline const Technique* Effect::getTechnique(int i) const
188 {
189 return _techs[i].get();
190 }
191
192 inline int Effect::getSelectedTechnique() const
193 {
194 return _global_sel_tech;
195 }
196
197 inline void Effect::selectTechnique(int i)
198 {
199 _global_sel_tech = i;
200 }
201
202 inline void Effect::addTechnique(Technique* tech)
203 {
204 _techs.push_back(tech);
205 }
206
207 inline void Effect::dirtyTechniques()
208 {
209 _techs_defined = false;
210 }
211
212 inline void Effect::inherited_traverse(osg::NodeVisitor& nv)
213 {
214 typedef osg::Group inherited;
215 inherited::traverse(nv);
216 }
217
218}
219
220#endif