]> git.mxchange.org Git - flightgear.git/blob - src/Viewer/renderingpipeline.cxx
Remove pre-OSG 'enable/disable-textures' option.
[flightgear.git] / src / Viewer / renderingpipeline.cxx
1 // renderingpipeline.cxx -- description of the cameras needed by the Rembrandt renderer
2 //
3 // Written by Curtis Olson, started May 1997.
4 // This file contains parts of main.cxx prior to october 2004
5 //
6 // Copyright (C) 1997 - 2012  Curtis L. Olson  - http://www.flightgear.org/~curt
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25
26 #ifdef HAVE_WINDOWS_H
27 #  include <windows.h>
28 #endif
29
30 #include <boost/lexical_cast.hpp>
31
32 #include <osg/GL>
33 #include <osg/FrameBufferObject> // For texture formats
34
35 #include <simgear/debug/logstream.hxx>
36 #include <simgear/scene/util/SGReaderWriterOptions.hxx>
37 #include <simgear/scene/model/modellib.hxx>
38 #include <simgear/scene/material/EffectBuilder.hxx>
39 #include <simgear/scene/material/EffectCullVisitor.hxx>
40 #include <simgear/props/props_io.hxx>
41 #include <simgear/structure/exception.hxx>
42 #include <simgear/math/SGMath.hxx>
43
44 #include "renderingpipeline.hxx"
45 #include "CameraGroup.hxx"
46 #include <Main/globals.hxx>
47 #include "renderer.hxx"
48
49 namespace flightgear {
50
51 FGRenderingPipeline* makeRenderingPipeline(const std::string& name,
52                    const simgear::SGReaderWriterOptions* options)
53 {
54     std::string fileName = "Effects/" + name;
55     fileName += ".xml";
56     std::string absFileName
57         = simgear::SGModelLib::findDataFile(fileName, options);
58     if (absFileName.empty()) {
59         SG_LOG(SG_INPUT, SG_ALERT, "can't find \"" << fileName << "\"");
60         return 0;
61     }
62     SGPropertyNode_ptr effectProps = new SGPropertyNode();
63     try {
64         readProperties(absFileName, effectProps.ptr(), 0, true);
65     }
66     catch (sg_io_exception& e) {
67         SG_LOG(SG_INPUT, SG_ALERT, "error reading \"" << absFileName << "\": "
68                << e.getFormattedMessage());
69         return 0;
70     }
71
72     osg::ref_ptr<FGRenderingPipeline> pipeline = new FGRenderingPipeline;
73     std::vector<SGPropertyNode_ptr> buffers = effectProps->getChildren("buffer");
74     for (int i = 0; i < (int)buffers.size(); ++i) {
75         pipeline->buffers.push_back(new FGRenderingPipeline::Buffer(buffers[i]));
76     }
77
78     std::vector<SGPropertyNode_ptr> stages = effectProps->getChildren("stage");
79     for (int i = 0; i < (int)stages.size(); ++i) {
80         pipeline->stages.push_back(new FGRenderingPipeline::Stage(stages[i]));
81     }
82
83     return pipeline.release();
84 }
85
86 }
87
88 void
89 FGRenderingPipeline::Conditionable::parseCondition(SGPropertyNode* prop)
90 {
91     const SGPropertyNode* predProp = prop->getChild("condition");
92     if (!predProp) {
93         setAlwaysValid(true);
94     } else {
95         setAlwaysValid(false);
96         try {
97             flightgear::PipelinePredParser parser;
98             SGExpressionb* validExp = dynamic_cast<SGExpressionb*>(parser.read(predProp->getChild(0)));
99             if (validExp)
100                 setValidExpression(validExp);
101             else
102                 throw simgear::expression::ParseError("pipeline condition is not a boolean expression");
103         }
104         catch (simgear::expression::ParseError& except)
105         {
106             SG_LOG(SG_INPUT, SG_ALERT,
107                    "parsing pipeline condition " << except.getMessage());
108             setAlwaysValid(false);
109         }
110     }
111 }
112
113 void FGRenderingPipeline::Conditionable::setValidExpression(SGExpressionb* exp)
114 {
115     _validExpression = exp;
116 }
117
118 bool FGRenderingPipeline::Conditionable::valid()
119 {
120     return _alwaysValid || _validExpression->getValue();
121 }
122
123 template<typename T>
124 void findAttrOrHex(const simgear::effect::EffectPropertyMap<T>& pMap,
125               const SGPropertyNode* prop,
126               T& result)
127 {
128     try {
129         simgear::findAttr(pMap, prop, result);
130     } catch (simgear::effect::BuilderException&) {
131         std::string val = prop->getStringValue();
132         try {
133             result = boost::lexical_cast<T>(val);
134         } catch (boost::bad_lexical_cast &) {
135             throw simgear::effect::BuilderException(std::string("findAttrOrHex: could not find attribute ")
136                                                     + std::string(val));
137         }
138     }
139 }
140
141 const SGPropertyNode* getPropertyNode(const SGPropertyNode* prop)
142 {
143     if (!prop)
144         return 0;
145     if (prop->nChildren() > 0) {
146         const SGPropertyNode* propertyProp = prop->getChild("property");
147         if (!propertyProp)
148             return prop;
149         return globals->get_props()->getNode(propertyProp->getStringValue());
150     }
151     return prop;
152 }
153
154 const SGPropertyNode* getPropertyChild(const SGPropertyNode* prop,
155                                              const char* name)
156 {
157     const SGPropertyNode* child = prop->getChild(name);
158     if (!child)
159         return 0;
160     else
161         return getPropertyNode(child);
162 }
163
164 simgear::effect::EffectNameValue<GLint> internalFormatInit[] =
165 {
166     { "rgb8", GL_RGB8 },
167     { "rgba8", GL_RGBA8 },
168     { "rgb16", GL_RGB16 },
169     { "rgba16", GL_RGBA16 },
170     { "rg16", 0x822C },
171     { "depth-component24", GL_DEPTH_COMPONENT24 },
172     { "depth-component32", GL_DEPTH_COMPONENT32 }
173 };
174 simgear::effect::EffectPropertyMap<GLint> internalFormats(internalFormatInit);
175
176 simgear::effect::EffectNameValue<GLenum> sourceFormatInit[] =
177 {
178     { "rg", 0x8227 },
179     { "rgb", GL_RGB },
180     { "rgba", GL_RGBA },
181     { "depth-component", GL_DEPTH_COMPONENT }
182 };
183 simgear::effect::EffectPropertyMap<GLenum> sourceFormats(sourceFormatInit);
184
185 simgear::effect::EffectNameValue<GLenum> sourceTypeInit[] =
186 {
187     { "unsigned-byte", GL_UNSIGNED_BYTE },
188     { "unsigned-short", GL_UNSIGNED_SHORT },
189     { "unsigned-int", GL_UNSIGNED_INT },
190     { "float", GL_FLOAT }
191 };
192 simgear::effect::EffectPropertyMap<GLenum> sourceTypes(sourceTypeInit);
193
194 simgear::effect::EffectNameValue<GLenum> wrapModesInit[] =
195 {
196     {"clamp", GL_CLAMP},
197     {"clamp-to-border", GL_CLAMP_TO_BORDER_ARB},
198     {"clamp-to-edge", GL_CLAMP_TO_EDGE},
199     {"mirror", GL_MIRRORED_REPEAT_IBM},
200     {"repeat", GL_REPEAT}
201 };
202 simgear::effect::EffectPropertyMap<GLenum> wrapModes(wrapModesInit);
203
204 FGRenderingPipeline::Buffer::Buffer(SGPropertyNode* prop)
205 {
206     SGPropertyNode_ptr nameProp = prop->getChild("name");
207     if (!nameProp.valid()) {
208         throw sg_exception("Buffer name is mandatory");
209     }
210     internalFormat = GL_RGBA8;
211     sourceFormat = GL_RGBA;
212     sourceType = GL_UNSIGNED_BYTE;
213     wrapMode = GL_CLAMP_TO_BORDER_ARB;
214     name = nameProp->getStringValue();
215     SGPropertyNode* internalFormatProp = prop->getChild("internal-format");
216     if (internalFormatProp)
217         findAttrOrHex(internalFormats, internalFormatProp, internalFormat);
218     SGPropertyNode* sourceFormatProp = prop->getChild("source-format");
219     if (sourceFormatProp)
220         findAttrOrHex(sourceFormats, sourceFormatProp, sourceFormat);
221     SGPropertyNode* sourceTypeProp = prop->getChild("source-type");
222     if (sourceTypeProp)
223         findAttrOrHex(sourceTypes, sourceTypeProp, sourceType);
224     SGPropertyNode* wrapModeProp = prop->getChild("wrap-mode");
225     if (wrapModeProp)
226         findAttrOrHex(wrapModes, wrapModeProp, wrapMode);
227     SGConstPropertyNode_ptr widthProp = getPropertyChild(prop, "width");
228     if (!widthProp.valid())
229         width = -1;
230     else if (widthProp->getStringValue() == std::string("screen"))
231         width = -1;
232     else {
233         width = widthProp->getIntValue();
234     }
235     SGConstPropertyNode_ptr heightProp = getPropertyChild(prop, "height");
236     if (!heightProp.valid())
237         height = -1;
238     else if (heightProp->getStringValue() == std::string("screen"))
239         height = -1;
240     else
241         height = heightProp->getIntValue();
242
243     scaleFactor = prop->getFloatValue("scale-factor", 1.f);
244     shadowComparison = prop->getBoolValue("shadow-comparison", false);
245
246     parseCondition(prop);
247 }
248
249 simgear::effect::EffectNameValue<osg::Camera::BufferComponent> componentsInit[] =
250 {
251     {"depth",   osg::Camera::DEPTH_BUFFER},
252     {"stencil", osg::Camera::STENCIL_BUFFER},
253     {"packed-depth-stencil",   osg::Camera::PACKED_DEPTH_STENCIL_BUFFER},
254     {"color0",  osg::Camera::COLOR_BUFFER0},
255     {"color1",  osg::Camera::COLOR_BUFFER1},
256     {"color2",  osg::Camera::COLOR_BUFFER2},
257     {"color3",  osg::Camera::COLOR_BUFFER3}
258 };
259 simgear::effect::EffectPropertyMap<osg::Camera::BufferComponent> components(componentsInit);
260
261 FGRenderingPipeline::Pass::Pass(SGPropertyNode* prop)
262 {
263     SGPropertyNode_ptr nameProp = prop->getChild("name");
264     if (!nameProp.valid()) {
265         throw sg_exception("Pass name is mandatory");
266     }
267     name = nameProp->getStringValue();
268     SGPropertyNode_ptr typeProp = prop->getChild("type");
269     if (!typeProp.valid()) {
270         type = nameProp->getStringValue();
271     } else {
272         type = typeProp->getStringValue();
273     }
274
275     orderNum = prop->getIntValue("order-num", -1);
276     effect = prop->getStringValue("effect", "");
277     debugProperty = prop->getStringValue("debug-property", "");
278
279     parseCondition(prop);
280 }
281
282 FGRenderingPipeline::Stage::Stage(SGPropertyNode* prop) : Pass(prop)
283 {
284     needsDuDv = prop->getBoolValue("needs-du-dv", false);
285     scaleFactor = prop->getFloatValue("scale-factor", 1.f);
286
287     std::vector<SGPropertyNode_ptr> attachments = prop->getChildren("attachment");
288     for (int i = 0; i < (int)attachments.size(); ++i) {
289         this->attachments.push_back(new FGRenderingPipeline::Attachment(attachments[i]));
290     }
291
292     std::vector<SGPropertyNode_ptr> passes = prop->getChildren("pass");
293     for (int i = 0; i < (int)passes.size(); ++i) {
294         this->passes.push_back(new FGRenderingPipeline::Pass(passes[i]));
295     }
296 }
297
298 FGRenderingPipeline::Attachment::Attachment(SGPropertyNode* prop)
299 {
300     simgear::findAttr(components, prop->getChild("component"), component);
301     SGPropertyNode_ptr bufferProp = prop->getChild("buffer");
302     if (!bufferProp.valid()) {
303         throw sg_exception("Attachment buffer is mandatory");
304     }
305     buffer = bufferProp->getStringValue();
306
307     parseCondition(prop);
308 }
309
310 FGRenderingPipeline::FGRenderingPipeline()
311 {
312 }
313
314 class FGStageCameraCullCallback : public osg::NodeCallback {
315 public:
316     FGStageCameraCullCallback(FGRenderingPipeline::Stage* s, flightgear::CameraInfo* i) : stage(s), info(i) {}
317     virtual void operator()( osg::Node *n, osg::NodeVisitor *nv) {
318         simgear::EffectCullVisitor* cv = dynamic_cast<simgear::EffectCullVisitor*>(nv);
319         osg::Camera* camera = static_cast<osg::Camera*>(n);
320
321         cv->clearBufferList();
322         for (flightgear::RenderBufferMap::iterator ii = info->buffers.begin(); ii != info->buffers.end(); ++ii) {
323             cv->addBuffer(ii->first, ii->second.texture );
324         }
325
326                 if ( !info->getRenderStageInfo(stage->name).fullscreen )
327                         info->setMatrices( camera );
328
329         cv->traverse( *camera );
330     }
331
332 private:
333     osg::ref_ptr<FGRenderingPipeline::Stage> stage;
334     flightgear::CameraInfo* info;
335 };