]> git.mxchange.org Git - simgear.git/blob - simgear/scene/material/Effect.hxx
Move tree shaders to an effect
[simgear.git] / simgear / scene / material / Effect.hxx
1 // Copyright (C) 2008 - 2009  Tim Moore timoore@redhat.com
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
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 GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16
17 #ifndef SIMGEAR_EFFECT_HXX
18 #define SIMGEAR_EFFECT_HXX 1
19
20 #include <vector>
21 #include <string>
22
23 #include <boost/unordered_map.hpp>
24
25 #include <osg/Object>
26 #include <osgDB/ReaderWriter>
27
28 #include <simgear/props/props.hxx>
29 #include <simgear/scene/util/UpdateOnceCallback.hxx>
30
31 namespace osg
32 {
33 class Drawable;
34 class StateSet;
35 class RenderInfo;
36 }
37
38 namespace osgUtil
39 {
40 class CullVisitor;
41 }
42
43 namespace simgear
44 {
45 class Technique;
46 class Effect;
47
48 /**
49  * Object to be initialized at some point after an effect -- and its
50  * containing effect geode -- are hooked into the scene graph. Some
51  * things, like manipulations of the global property tree, are are
52  * only safe in the update process.
53  */
54
55 class InitializeWhenAdded
56 {
57 public:
58     InitializeWhenAdded() : _initialized(false) {};
59     virtual ~InitializeWhenAdded() {};
60     void initOnAdd(Effect* effect, SGPropertyNode* propRoot)
61     {
62         if (!_initialized) {
63             initOnAddImpl(effect, propRoot);
64             _initialized = true;
65         }
66     }
67     bool getInitialized() const { return _initialized; }
68 private:
69     virtual void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot) = 0;
70     bool _initialized;
71 };
72
73 class Effect : public osg::Object
74 {
75 public:
76     META_Object(simgear,Effect)
77     Effect();
78     Effect(const Effect& rhs,
79            const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
80     osg::StateSet* getDefaultStateSet();
81     std::vector<osg::ref_ptr<Technique> > techniques;
82     SGPropertyNode_ptr root;
83     // Pointer to the parameters node, if it exists
84     SGPropertyNode_ptr parametersProp;
85     Technique* chooseTechnique(osg::RenderInfo* renderInfo);
86     virtual void resizeGLObjectBuffers(unsigned int maxSize);
87     virtual void releaseGLObjects(osg::State* state = 0) const;
88     /**
89      * Build the techniques from the effect properties.
90      */
91     bool realizeTechniques(const osgDB::ReaderWriter::Options* options = 0);
92     /**
93      * Updaters that should be derefed when the effect is
94      * deleted. Updaters arrange to be run by listening on properties
95      * or something.
96      */
97     struct Updater : public virtual SGReferenced
98     {
99         virtual ~Updater() {}
100     };
101     void addUpdater(Updater* data) { _extraData.push_back(data); }
102     // Callback that is added to the effect geode to initialize the
103     // effect.
104     friend struct InitializeCallback;
105     struct InitializeCallback : public UpdateOnceCallback
106     {
107         void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
108     };
109 protected:
110     std::vector<SGSharedPtr<Updater> > _extraData;
111     ~Effect();
112     // Support for a cache of effects that inherit from this one, so
113     // Effect objects with the same parameters and techniques can be
114     // shared.
115     struct Key
116     {
117         Key() {}
118         Key(SGPropertyNode* unmerged_, const osgDB::FilePathList& paths_)
119             : unmerged(unmerged_), paths(paths_)
120         {
121         }
122         Key& operator=(const Key& rhs)
123         {
124             unmerged = rhs.unmerged;
125             paths = rhs.paths;
126             return *this;
127         }
128         SGPropertyNode_ptr unmerged;
129         osgDB::FilePathList paths;
130         struct EqualTo
131         {
132             bool operator()(const Key& lhs, const Key& rhs) const;
133         };
134     };
135     typedef boost::unordered_map<Key, osg::ref_ptr<Effect>, boost::hash<Key>,
136                                  Key::EqualTo> Cache;
137     Cache* getCache()
138     {
139         if (!_cache)
140             _cache = new Cache;
141         return _cache;
142     }
143     Cache* _cache;
144     friend size_t hash_value(const Key& key);
145     friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
146                               const osgDB::ReaderWriter::Options* options);
147     bool _isRealized;
148 };
149 // Automatic support for boost hash function
150 size_t hash_value(const Effect::Key&);
151
152
153 Effect* makeEffect(const std::string& name,
154                    bool realizeTechniques,
155                    const osgDB::ReaderWriter::Options* options = 0);
156
157 Effect* makeEffect(SGPropertyNode* prop,
158                    bool realizeTechniques,
159                    const osgDB::ReaderWriter::Options* options = 0);
160
161 bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
162                                 const osg::StateSet* ss);
163
164 namespace effect
165 {
166 /**
167  * The function that implements effect property tree inheritance.
168  */
169 void mergePropertyTrees(SGPropertyNode* resultNode,
170                         const SGPropertyNode* left,
171                         const SGPropertyNode* right);
172 }
173 }
174 #endif