]> git.mxchange.org Git - simgear.git/blob - simgear/scene/material/Effect.hxx
Merge Specular and Emission buffers
[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 #include <boost/tr1/unordered_map.hpp>
23
24 #include <boost/functional/hash.hpp>
25
26 #include <osg/Object>
27 #include <osgDB/ReaderWriter>
28
29 #include <simgear/props/props.hxx>
30 #include <simgear/scene/util/UpdateOnceCallback.hxx>
31
32 namespace osg
33 {
34 class Drawable;
35 class StateSet;
36 class RenderInfo;
37 }
38
39 namespace osgUtil
40 {
41 class CullVisitor;
42 }
43
44 namespace simgear
45 {
46 class Technique;
47 class Effect;
48 class SGReaderWriterOptions;
49
50 /**
51  * Object to be initialized at some point after an effect -- and its
52  * containing effect geode -- are hooked into the scene graph. Some
53  * things, like manipulations of the global property tree, are are
54  * only safe in the update process.
55  */
56
57 class InitializeWhenAdded
58 {
59 public:
60     InitializeWhenAdded() : _initialized(false) {};
61     virtual ~InitializeWhenAdded() {};
62     void initOnAdd(Effect* effect, SGPropertyNode* propRoot)
63     {
64         if (!_initialized) {
65             initOnAddImpl(effect, propRoot);
66             _initialized = true;
67         }
68     }
69     bool getInitialized() const { return _initialized; }
70 private:
71     virtual void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot) = 0;
72     bool _initialized;
73 };
74
75 class Effect : public osg::Object
76 {
77 public:
78     META_Object(simgear,Effect)
79     Effect();
80     Effect(const Effect& rhs,
81            const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
82     osg::StateSet* getDefaultStateSet();
83
84     enum Buffer
85     {
86         DEPTH_BUFFER,
87         NORMAL_BUFFER,
88         DIFFUSE_BUFFER,
89         SPEC_EMIS_BUFFER,
90         LIGHTING_BUFFER,
91         MIDDLE_BLOOM_BUFFER,
92         BLOOM_BUFFER,
93         AO_BUFFER
94     };
95
96     // Define what needs to be generated for this effect
97     enum Generator
98     {
99         NORMAL,
100         TANGENT,
101         BINORMAL
102     };
103     void setGenerator(Generator what, int where) { generator[what] = where; }
104     int getGenerator(Generator what) const;  // Returns -1 if generator should not be used
105     std::map<Generator, int> generator;  // What is generated into which attribute location
106
107     std::vector<osg::ref_ptr<Technique> > techniques;
108     SGPropertyNode_ptr root;
109     // Pointer to the parameters node, if it exists
110     SGPropertyNode_ptr parametersProp;
111     Technique* chooseTechnique(osg::RenderInfo* renderInfo);
112     virtual void resizeGLObjectBuffers(unsigned int maxSize);
113     virtual void releaseGLObjects(osg::State* state = 0) const;
114     /**
115      * Build the techniques from the effect properties.
116      */
117     bool realizeTechniques(const SGReaderWriterOptions* options = 0);
118     /**
119      * Updaters that should be derefed when the effect is
120      * deleted. Updaters arrange to be run by listening on properties
121      * or something.
122      */
123     struct Updater : public virtual SGReferenced
124     {
125         virtual ~Updater() {}
126     };
127     void addUpdater(Updater* data) { _extraData.push_back(data); }
128     // Callback that is added to the effect geode to initialize the
129     // effect.
130     friend struct InitializeCallback;
131     struct InitializeCallback : public UpdateOnceCallback
132     {
133         void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
134     };
135 protected:
136     std::vector<SGSharedPtr<Updater> > _extraData;
137     ~Effect();
138     // Support for a cache of effects that inherit from this one, so
139     // Effect objects with the same parameters and techniques can be
140     // shared.
141     struct Key
142     {
143         Key() {}
144         Key(SGPropertyNode* unmerged_, const osgDB::FilePathList& paths_)
145             : unmerged(unmerged_), paths(paths_)
146         {
147         }
148         Key& operator=(const Key& rhs)
149         {
150             unmerged = rhs.unmerged;
151             paths = rhs.paths;
152             return *this;
153         }
154         SGPropertyNode_ptr unmerged;
155         osgDB::FilePathList paths;
156         struct EqualTo
157         {
158             bool operator()(const Key& lhs, const Key& rhs) const;
159         };
160     };
161     typedef std::tr1::unordered_map<Key, osg::ref_ptr<Effect>,
162                                     boost::hash<Key>, Key::EqualTo> Cache;
163     Cache* getCache()
164     {
165         if (!_cache)
166             _cache = new Cache;
167         return _cache;
168     }
169     Cache* _cache;
170     friend size_t hash_value(const Key& key);
171     friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
172                               const SGReaderWriterOptions* options);
173     bool _isRealized;
174 };
175 // Automatic support for boost hash function
176 size_t hash_value(const Effect::Key&);
177
178
179 Effect* makeEffect(const std::string& name,
180                    bool realizeTechniques,
181                    const SGReaderWriterOptions* options = 0);
182
183 Effect* makeEffect(SGPropertyNode* prop,
184                    bool realizeTechniques,
185                    const SGReaderWriterOptions* options = 0);
186
187 bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
188                                 const osg::StateSet* ss);
189
190 namespace effect
191 {
192 /**
193  * The function that implements effect property tree inheritance.
194  */
195 void mergePropertyTrees(SGPropertyNode* resultNode,
196                         const SGPropertyNode* left,
197                         const SGPropertyNode* right);
198 }
199 }
200 #endif