1 /* -*-c++-*- */
2 /* osgEarth - Geospatial SDK for OpenSceneGraph
3  * Copyright 2019 Pelican Mapping
4  * http://osgearth.org
5  *
6  * osgEarth is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>
18  */
19 #include <osgEarth/ShaderFactory>
20 
21 #include <osgEarth/ShaderLoader>
22 #include <osgEarth/Registry>
23 #include <osgEarth/Capabilities>
24 
25 #define LC "[ShaderFactory] "
26 
27 #if defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE)
28     static bool s_GLES_SHADERS = true;
29 #else
30     static bool s_GLES_SHADERS = false;
31 #endif
32 
33 #define INDENT "    "
34 #define RANGE  osgEarth::Registry::instance()->shaderFactory()->getRangeUniformName()
35 
36 using namespace osgEarth;
37 using namespace osgEarth::ShaderComp;
38 
39 
ShaderFactory()40 ShaderFactory::ShaderFactory()
41 {
42     _fragStageOrder = FRAGMENT_STAGE_ORDER_COLORING_LIGHTING;
43 }
44 
45 
46 #define SPACE_MODEL 0
47 #define SPACE_VIEW  1
48 #define SPACE_CLIP  2
49 
50 namespace
51 {
52     struct Variable
53     {
54         std::string interp;      // interpolation qualifer (flat, etc.)
55         std::string type;        // float, vec4, etc.
56         std::string name;        // name without any array specifiers, etc.
57         std::string prec;        // precision qualifier if any
58         std::string declaration; // name including array specifiers (for decl)
59         int         arraySize;   // 0 if not an array; else array size.
60     };
61 
62     typedef std::vector<Variable> Variables;
63 
addExtensionsToBuffer(std::ostream & buf,const VirtualProgram::ExtensionsSet & in_extensions)64 	void addExtensionsToBuffer(std::ostream& buf, const VirtualProgram::ExtensionsSet& in_extensions)
65 	{
66 	   for (VirtualProgram::ExtensionsSet::const_iterator it = in_extensions.begin(); it != in_extensions.end(); ++it)
67 	   {
68 	      const std::string& extension = *it;
69 	      buf << "#extension "<<extension<< " : enable \n";
70 	   }
71 	}
72 }
73 
74 
75 ShaderComp::StageMask
createMains(const ShaderComp::FunctionLocationMap & functions,const VirtualProgram::ShaderMap & in_shaders,const VirtualProgram::ExtensionsSet & in_extensions,std::vector<osg::ref_ptr<osg::Shader>> & out_shaders) const76 ShaderFactory::createMains(const ShaderComp::FunctionLocationMap&    functions,
77                            const VirtualProgram::ShaderMap&          in_shaders,
78                            const VirtualProgram::ExtensionsSet&      in_extensions,
79                            std::vector< osg::ref_ptr<osg::Shader> >& out_shaders) const
80 {
81     StageMask stages =
82         ShaderComp::STAGE_VERTEX |
83         ShaderComp::STAGE_FRAGMENT;
84 
85     FunctionLocationMap::const_iterator f;
86 
87     // collect the "model" stage vertex functions:
88     f = functions.find( LOCATION_VERTEX_MODEL );
89     const OrderedFunctionMap* modelStage = f != functions.end() ? &f->second : 0L;
90 
91     // collect the "view" stage vertex functions:
92     f = functions.find( LOCATION_VERTEX_VIEW );
93     const OrderedFunctionMap* viewStage = f != functions.end() ? &f->second : 0L;
94 
95     // geometry shader functions:
96     f = functions.find( LOCATION_TESS_CONTROL );
97     const OrderedFunctionMap* tessControlStage = f != functions.end() ? &f->second : 0L;
98 
99     // geometry shader functions:
100     f = functions.find( LOCATION_TESS_EVALUATION );
101     const OrderedFunctionMap* tessEvalStage = f != functions.end() ? &f->second : 0L;
102 
103     // geometry shader functions:
104     f = functions.find( LOCATION_GEOMETRY );
105     const OrderedFunctionMap* geomStage = f != functions.end() ? &f->second : 0L;
106 
107     // collect the "clip" stage functions:
108     f = functions.find( LOCATION_VERTEX_CLIP );
109     const OrderedFunctionMap* clipStage = f != functions.end() ? &f->second : 0L;
110 
111     // fragment shader coloring functions:
112     f = functions.find( LOCATION_FRAGMENT_COLORING );
113     const OrderedFunctionMap* coloringStage = f != functions.end() ? &f->second : 0L;
114 
115     // fragment shader lighting functions:
116     f = functions.find( LOCATION_FRAGMENT_LIGHTING );
117     const OrderedFunctionMap* lightingStage = f != functions.end() ? &f->second : 0L;
118 
119     // fragment shader lighting functions:
120     f = functions.find( LOCATION_FRAGMENT_OUTPUT );
121     const OrderedFunctionMap* outputStage = f != functions.end() ? &f->second : 0L;
122 
123     // what do we need to build?
124     bool hasGS  = geomStage        && !geomStage->empty();
125     bool hasTCS = tessControlStage && !tessControlStage->empty();
126     bool hasTES = tessEvalStage    && !tessEvalStage->empty();
127     bool hasFS  = true;
128     bool hasVS  = true;
129 
130     // where to insert the view/clip stage vertex functions:
131     bool viewStageInGS  = hasGS;
132     bool viewStageInTES = !viewStageInGS && hasTES;
133     bool viewStageInVS  = !viewStageInTES && !viewStageInGS;
134 
135     bool clipStageInGS  = hasGS;
136     bool clipStageInTES = hasTES && !hasGS;
137     bool clipStageInVS  = !clipStageInGS && !clipStageInTES;
138 
139     // search for pragma varyings and build up our interface block definitions.
140     typedef std::set<std::string> VarDefs;
141     VarDefs varDefs;
142 
143     // built-ins:
144     varDefs.insert( "vec4 vp_Color" );
145     varDefs.insert( "vec3 vp_Normal" );
146     varDefs.insert( "vec4 vp_Vertex" );
147 
148     // parse the vp_varyings (which were injected by the ShaderLoader)
149     for(VirtualProgram::ShaderMap::const_iterator s = in_shaders.begin(); s != in_shaders.end(); ++s )
150     {
151         osg::Shader* shader = s->data()._shader->getNominalShader();
152         if ( shader )
153         {
154             ShaderLoader::getAllPragmaValues(shader->getShaderSource(), "vp_varying", varDefs);
155         }
156     }
157 
158     Variables vars;
159     for(VarDefs::iterator i = varDefs.begin(); i != varDefs.end(); ++i)
160     {
161         std::vector<std::string> tokens;
162         StringTokenizer st;
163         st.addDelims( " \t", false );
164         st.addDelims( "[]", true );
165         st.tokenize( *i, tokens ); //(*i, tokens, " \t", "", false, true);
166         if ( tokens.size() >= 2 )
167         {
168             int p=0;
169             Variable v;
170             if ( tokens[p] == "flat" || tokens[p] == "nonperspective" || tokens[p] == "smooth" )
171             {
172                 v.interp = tokens[p++];
173             }
174 
175             if ( tokens[p] == "lowp" || tokens[p] == "mediump" || tokens[p] == "highp" )
176             {
177                 v.prec = tokens[p++];
178             }
179 
180             if ( p+1 < tokens.size() )
181             {
182                 v.type = tokens[p++];
183                 v.name = tokens[p++];
184 
185                 // check for array
186                 if ( p+2 < tokens.size() && tokens[p] == "[" && tokens[p+2] == "]" )
187                 {
188                     v.declaration = Stringify() << v.type << " " << v.name << tokens[p] << tokens[p+1] << tokens[p+2];
189                     v.arraySize = as<int>(tokens[p+1], 0);
190                 }
191                 else
192                 {
193                     v.declaration = Stringify() << v.type << " " << v.name;
194                     v.arraySize = 0;
195                 }
196             }
197 
198             if ( !v.type.empty() && !v.name.empty() && !v.declaration.empty() )
199             {
200                 vars.push_back( v );
201             }
202         }
203     }
204 
205     std::string
206         gl_Color                     = "gl_Color",
207         gl_Vertex                    = "gl_Vertex",
208         gl_Normal                    = "gl_Normal",
209         gl_Position                  = "gl_Position",
210         gl_ModelViewMatrix           = "gl_ModelViewMatrix",
211         gl_ProjectionMatrix          = "gl_ProjectionMatrix",
212         gl_ModelViewProjectionMatrix = "gl_ModelViewProjectionMatrix",
213         gl_NormalMatrix              = "gl_NormalMatrix",
214         gl_FrontColor                = "gl_FrontColor";
215 
216     std::string glMatrixUniforms = "";
217 
218     #define GLSL_330 GLSL_VERSION_STR // "330 compatibility"
219 
220 #if defined(OSG_GL3_AVAILABLE) || defined(OSG_GL4_AVAILABLE)
221 #   define GLSL_400 "400"
222 #else
223 #   define GLSL_400 "400 compatibility"
224 #endif
225 
226     // use GLSL 400 if it's avaiable since that will give the developer
227     // access to double-precision types.
228     bool use400 =
229         Registry::instance()->hasCapabilities() &&
230         Registry::capabilities().getGLSLVersionInt() >= 400;
231 
232     std::string tcs_glsl_version(GLSL_400);
233     std::string tes_glsl_version(GLSL_400);
234 
235     std::string vs_glsl_version = use400 ? GLSL_400 : GLSL_330;
236     std::string fs_glsl_version = use400 ? GLSL_400 : GLSL_330;
237     std::string gs_glsl_version = use400 ? GLSL_400 : GLSL_330;
238 
239     // build the vertex data interface block definition:
240     std::string vertdata;
241     {
242         std::stringstream buf;
243         buf << "VP_PerVertex { \n";
244         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
245             buf << INDENT << i->interp << (i->interp.empty()?"":" ") << i->prec << (i->prec.empty()?"":" ") << i->declaration << "; \n";
246         buf << "}";
247         vertdata = buf.str();
248     }
249 
250     // TODO: perhaps optimize later to not include things we don't need in the FS
251     std::string fragdata = vertdata;
252 
253     // Build the vertex shader.
254     if ( hasVS )
255     {
256         stages |= ShaderComp::STAGE_VERTEX;
257 
258         std::stringstream buf;
259 
260         buf << "#version " << vs_glsl_version << "\n"
261             GLSL_DEFAULT_PRECISION_FLOAT << "\n"
262             "#pragma vp_name VP Vertex Shader Main\n"
263             << (!s_GLES_SHADERS ? "#extension GL_ARB_gpu_shader5 : enable \n" : "");
264 
265         addExtensionsToBuffer(buf, in_extensions);
266 
267         buf << "\n// Vertex stage globals:\n";
268         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
269             buf << i->prec << (i->prec.empty()?"":" ") << i->declaration << "; \n";
270 
271         buf << "\n// Vertex stage outputs:\n";
272         if ( hasGS || hasTCS )
273             buf << "out " << vertdata << " vp_out; \n";
274         else
275             buf << "out " << fragdata << " vp_out; \n";
276 
277         // prototype functions:
278         if ( modelStage || (viewStage && viewStageInVS) || (clipStage && clipStageInVS) )
279         {
280             buf << "\n// Function declarations:\n";
281         }
282 
283         if ( modelStage )
284         {
285             for( OrderedFunctionMap::const_iterator i = modelStage->begin(); i != modelStage->end(); ++i )
286             {
287                 buf << "void " << i->second._name << "(inout vec4); \n";
288             }
289         }
290 
291         // prototypes for view stage methods:
292         if ( viewStage != 0L && viewStageInVS )
293         {
294             for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
295             {
296                 buf << "void " << i->second._name << "(inout vec4); \n";
297             }
298         }
299 
300         // prototypes for clip stage methods:
301         if ( clipStage != 0L && clipStageInVS )
302         {
303             for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
304             {
305                 buf << "void " << i->second._name << "(inout vec4); \n";
306             }
307         }
308 
309         buf <<
310             "\nvoid main(void) \n"
311             "{ \n"
312             INDENT "vp_Vertex = " << gl_Vertex << "; \n"
313             INDENT "vp_Normal = " << gl_Normal << "; \n"
314             INDENT "vp_Color  = " << gl_Color  << "; \n";
315 
316         if ( modelStage )
317         {
318             for( OrderedFunctionMap::const_iterator i = modelStage->begin(); i != modelStage->end(); ++i )
319             {
320                 buf << INDENT << i->second._name << "(vp_Vertex); \n";
321             }
322         }
323 
324         if ( viewStageInVS )
325         {
326             if ( viewStage )
327             {
328                 buf <<
329                     INDENT << "vp_Vertex = " << gl_ModelViewMatrix << " * vp_Vertex; \n"
330                     INDENT << "vp_Normal = normalize(" << gl_NormalMatrix    << " * vp_Normal); \n";
331 
332                 for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
333                 {
334                     buf << INDENT << i->second._name << "(vp_Vertex); \n";
335                 }
336             }
337 
338             if ( clipStageInVS )
339             {
340                 if ( clipStage )
341                 {
342                     if ( viewStage )
343                     {
344                         buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
345                     }
346                     else
347                     {
348                         buf <<
349                             INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
350                             INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
351                     }
352 
353                     for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
354                     {
355                         buf << INDENT << i->second._name << "(vp_Vertex); \n";
356                     }
357                 }
358             }
359         }
360 
361         // if there are no further vertex-processing stages, transform the position into clip coordinates
362         // for the fragment shader now:
363         if ( !hasGS && !hasTCS )
364         {
365             if ( clipStage )
366                 buf << INDENT "gl_Position = vp_Vertex; \n";
367             else if ( viewStage )
368                 buf << INDENT "gl_Position = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
369             else
370                 buf << INDENT "gl_Position = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n";
371         }
372 
373         // otherwise, pass it along as-is.
374         else
375         {
376             buf << INDENT "gl_Position = vp_Vertex; \n";
377         }
378 
379 
380         if ( hasTCS || hasGS || hasFS )
381         {
382             // Copy stage globals to output block:
383             for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
384                 buf << INDENT << "vp_out." << i->name << " = " << i->name << "; \n";
385         }
386 
387         buf << "} \n";
388 
389         osg::Shader* vertexShader = new osg::Shader( osg::Shader::VERTEX, buf.str() );
390         vertexShader->setName( "main(vertex)" );
391         out_shaders.push_back( vertexShader );
392     }
393 
394 
395     //.................................................................................
396 
397 #if OSG_VERSION_LESS_THAN(3,5,8)
398     // for all stages EXCEPT vertex, we will switch over to the OSG aliased
399     // matrix uniforms. Why except vertex? OSG<3.5.8 only replaces these
400     // in the vertex shader and not other stages.
401 
402     gl_ModelViewMatrix           = "osg_ModelViewMatrix",
403     gl_ProjectionMatrix          = "osg_ProjectionMatrix",
404     gl_ModelViewProjectionMatrix = "osg_ModelViewProjectionMatrix",
405     gl_NormalMatrix              = "osg_NormalMatrix",
406     gl_FrontColor                = "osg_FrontColor";
407 
408     glMatrixUniforms =
409         "uniform mat4 osg_ModelViewMatrix;\n"
410         "uniform mat4 osg_ModelViewProjectionMatrix;\n"
411         "uniform mat4 osg_ProjectionMatrix;\n"
412         "uniform mat3 osg_NormalMatrix;\n";
413 #endif
414 
415     if ( hasTCS )
416     {
417         stages |= ShaderComp::STAGE_TESSCONTROL;
418         std::stringstream buf;
419 
420         buf << "#version " << tcs_glsl_version << "\n"
421             << GLSL_DEFAULT_PRECISION_FLOAT << "\n"
422             << "#pragma vp_name VP Tessellation Control Shader (TCS) Main\n"
423             // For gl_MaxPatchVertices
424             << (!s_GLES_SHADERS ? "#extension GL_NV_gpu_shader5 : enable\n" : "");
425 
426         addExtensionsToBuffer(buf, in_extensions);
427 
428         buf << glMatrixUniforms << "\n";
429 
430         if ( hasVS )
431         {
432               buf << "\n// TCS stage inputs:\n"
433                  << "in " << vertdata << " vp_in [gl_MaxPatchVertices]; \n";
434         }
435 
436         // The TES is mandatory.
437         buf << "\n// TCS stage outputs to TES: \n"
438             << "out " << vertdata << " vp_out [gl_MaxPatchVertices]; \n";
439 
440         // Stage globals.
441         buf << "\n// TCS stage globals \n";
442         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
443             buf << i->prec << (i->prec.empty()?"":" ") << i->declaration << "; \n";
444 
445         // Helper functions:
446         // TODO: move this into its own osg::Shader so it can be shared.
447         buf << "\nvoid VP_LoadVertex(in int index) \n"
448             << "{ \n";
449 
450         // Copy input block to stage globals:
451         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
452             buf << INDENT << i->name << " = vp_in[index]." << i->name << "; \n";
453 
454         buf << "} \n";
455 
456         // Function declares
457         if ( tessControlStage )
458         {
459             buf << "\n// Function declarations:\n";
460             for( OrderedFunctionMap::const_iterator i = tessControlStage->begin(); i != tessControlStage->end(); ++i )
461                 buf << "void " << i->second._name << "(); \n";
462         }
463 
464         // Main
465         buf << "\nvoid main(void) \n"
466             << "{ \n"
467             << INDENT "// copy default outputs: \n";
468 
469         // Copy in to globals
470         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
471             buf << INDENT << i->name << " = vp_in[gl_InvocationID]." << i->name << "; \n";
472 
473         // Invoke functions
474         if ( tessControlStage )
475         {
476             for( OrderedFunctionMap::const_iterator i = tessControlStage->begin(); i != tessControlStage->end(); ++i )
477                 buf << INDENT << i->second._name << "(); \n";
478         }
479 
480         // Copy globals to out.
481         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
482             buf << INDENT << "vp_out[gl_InvocationID]." << i->name << " = " << i->name << "; \n";
483 
484         buf << "} \n";
485 
486         std::string str = buf.str();
487         osg::Shader* tcsShader = new osg::Shader(osg::Shader::TESSCONTROL, str);
488         tcsShader->setName("VP TCS");
489         out_shaders.push_back( tcsShader );
490     }
491 
492 
493     //.................................................................................
494 
495 
496     if ( hasTES )
497     {
498         stages |= ShaderComp::STAGE_TESSEVALUATION;
499 
500         std::stringstream buf;
501 
502         buf << "#version " << tes_glsl_version << "\n"
503             << GLSL_DEFAULT_PRECISION_FLOAT << "\n"
504             << "#pragma vp_name VP Tessellation Evaluation (TES) Shader MAIN\n";
505 
506         addExtensionsToBuffer(buf, in_extensions);
507 
508         buf << glMatrixUniforms << "\n";
509 
510         buf << "\n// TES stage inputs (required):\n"
511             << "in " << vertdata << " vp_in []; \n";
512 
513         // Declare stage globals.
514         buf << "\n// TES stage globals: \n";
515         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
516             buf << i->declaration << "; \n";
517 
518         buf << "\n// TES stage outputs: \n";
519         if ( hasGS )
520             buf << "out " << vertdata << " vp_out; \n";
521         else
522             buf << "out " << fragdata << " vp_out; \n";
523 
524         std::set<std::string> types;
525         for(Variables::const_iterator i=vars.begin(); i != vars.end(); ++i)
526             types.insert(i->type);
527 
528         for(std::set<std::string>::const_iterator i = types.begin(); i != types.end(); ++i)
529         {
530             buf << *i << " VP_Interpolate3(" << *i << "," << *i << "," << *i << ");\n";
531         }
532 
533 #if 0
534         buf <<
535             "\n// TES user-supplied interpolators: \n"
536             "float VP_Interpolate16(float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float); \n"
537             "vec2  VP_Interpolate16(vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2,vec2); \n"
538             "vec3  VP_Interpolate16(vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3,vec3); \n"
539             "vec4  VP_Interpolate16(vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4,vec4); \n";
540 #endif
541 
542         if ( tessEvalStage || (viewStage && viewStageInTES) || (clipStage && clipStageInTES) )
543         {
544             buf << "\n// Function declarations:\n";
545             if ( tessEvalStage )
546             {
547                 for( OrderedFunctionMap::const_iterator i = tessEvalStage->begin(); i != tessEvalStage->end(); ++i )
548                 {
549                     buf << "void " << i->second._name << "(); \n";
550                 }
551             }
552 
553             if (viewStage && viewStageInTES)
554             {
555                 for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
556                 {
557                     buf << "void " << i->second._name << "(inout vec4); \n";
558                 }
559             }
560 
561             if (clipStage && clipStageInTES)
562             {
563                 for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
564                 {
565                     buf << "void " << i->second._name << "(inout vec4); \n";
566                 }
567             }
568 
569             // Helper functions:
570             buf << "\nvoid VP_LoadVertex(in int index) \n"
571                 << "{ \n";
572 
573             // Copy input block to stage globals:
574             for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
575                 buf << INDENT << i->name << " = vp_in[index]." << i->name << "; \n";
576 
577             buf << "} \n";
578 
579             buf << "\nvoid VP_Interpolate3() \n"
580                 << "{ \n";
581             for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
582             {
583                 if ( i->interp != "flat" )
584                 {
585                     if ( i->arraySize == 0 )
586                     {
587                         buf << INDENT << i->name << " = VP_Interpolate3"
588                             << "( vp_in[0]." << i->name
589                             << ", vp_in[1]." << i->name
590                             << ", vp_in[2]." << i->name << " ); \n";
591                     }
592                     else
593                     {
594                         for(int n=0; n<i->arraySize; ++n)
595                         {
596                             buf << INDENT << i->name << "[" << n << "] = VP_Interpolate3"
597                                 << "( vp_in[0]." << i->name << "[" << n << "]"
598                                 << ", vp_in[1]." << i->name << "[" << n << "]"
599                                 << ", vp_in[2]." << i->name << "[" << n << "] ); \n";
600                         }
601                     }
602                 }
603                 else
604                 {
605                     buf << INDENT << i->name << " = vp_in[0]." << i->name << "; \n";
606                 }
607             }
608             buf << "} \n";
609 
610             buf << "\nvoid VP_EmitVertex() \n"
611                 << "{ \n";
612 
613             int space = SPACE_MODEL;
614 
615             if ( viewStage && viewStageInTES )
616             {
617                 buf << INDENT << "vp_Vertex = " << gl_ModelViewMatrix << " * vp_Vertex; \n"
618                     << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
619                 space = SPACE_VIEW;
620 
621                 for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
622                 {
623                     buf << INDENT << i->second._name << "(vp_Vertex); \n";
624                 }
625             }
626 
627             if ( clipStage && clipStageInTES )
628             {
629                 if ( space == SPACE_MODEL )
630                     buf << INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
631                     << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
632                 else if ( space == SPACE_VIEW )
633                     buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
634 
635                 space = SPACE_CLIP;
636 
637                 for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
638                 {
639                     buf << INDENT << i->second._name << "(vp_Vertex); \n";
640                 }
641             }
642 
643             // resolve vertex to its next space, but ONLY if this is the final Vertex Processing stage.
644             if ( !hasGS )
645             {
646                 if ( space == SPACE_MODEL )
647                     buf << INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
648                         << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
649                 else if ( space == SPACE_VIEW )
650                     buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
651             }
652 
653             // Copy globals to output block:
654             for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
655                 buf << INDENT << "vp_out." << i->name << " = " << i->name << "; \n";
656 
657             buf << INDENT << "gl_Position = vp_Vertex; \n"
658                 << "} \n";
659         }
660 
661         buf << "\n"
662             << "void main(void) \n"
663             << "{ \n"
664             << INDENT "// copy default outputs: \n";
665 
666         if ( !tessEvalStage )
667         {
668             // Copy default input block to output block (auto passthrough on first vert)
669             // NOT SURE WE NEED THIS
670             for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
671                 buf << INDENT << "vp_out." << i->name << " = vp_in[0]." << i->name << "; \n";
672         }
673 
674         if ( tessEvalStage )
675         {
676             for( OrderedFunctionMap::const_iterator i = tessEvalStage->begin(); i != tessEvalStage->end(); ++i )
677             {
678                 buf << INDENT << i->second._name << "(); \n";
679             }
680         }
681 
682         buf << "} \n";
683 
684         std::string str = buf.str();
685         osg::Shader* tesShader = new osg::Shader(osg::Shader::TESSEVALUATION, str);
686         tesShader->setName("VP TES");
687         out_shaders.push_back( tesShader );
688     }
689 
690 
691     //.................................................................................
692 
693 
694     // Build the geometry shader.
695     if ( hasGS )
696     {
697         stages |= ShaderComp::STAGE_GEOMETRY;
698 
699         std::stringstream buf;
700 
701         buf << "#version " << gs_glsl_version << "\n"
702             << GLSL_DEFAULT_PRECISION_FLOAT << "\n"
703             << "#pragma vp_name VP Geometry Shader Main\n";
704 
705         addExtensionsToBuffer(buf, in_extensions);
706 
707         //buf << glMatrixUniforms << "\n";
708 
709         if ( hasVS || hasTCS || hasTES )
710         {
711             buf << "\n// Geometry stage inputs:\n"
712                 << "in " << vertdata << " vp_in []; \n";
713         }
714 
715         // Declare stage globals.
716         buf << "\n// Geometry stage globals: \n";
717         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
718             buf << i->declaration << "; \n";
719 
720         buf << "\n// Geometry stage outputs: \n"
721             << "out " << fragdata << " vp_out; \n";
722 
723         if ( geomStage || (viewStage && viewStageInGS) || (clipStage && clipStageInGS) )
724         {
725             buf << "\n// Injected function declarations:\n";
726             if ( geomStage )
727             {
728                 for( OrderedFunctionMap::const_iterator i = geomStage->begin(); i != geomStage->end(); ++i )
729                 {
730                     buf << "void " << i->second._name << "(); \n";
731                 }
732             }
733 
734             if ( viewStage && viewStageInGS )
735             {
736                 for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
737                 {
738                     buf << "void " << i->second._name << "(inout vec4); \n";
739                 }
740             }
741 
742             if ( clipStage && clipStageInGS )
743             {
744                 for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
745                 {
746                     buf << "void " << i->second._name << "(inout vec4); \n";
747                 }
748             }
749         }
750 
751         // Build-in helper functions:
752         buf << "\nvoid VP_LoadVertex(in int index) \n"
753             << "{ \n";
754 
755         // Copy input block to stage globals:
756         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
757             buf << INDENT << i->name << " = vp_in[index]." << i->name << "; \n";
758 
759         buf << "} \n";
760 
761         buf << "\nvoid VP_EmitModelVertex() \n"
762             << "{ \n";
763 
764         buf << INDENT << "vp_Vertex = gl_Position; \n";
765         int space = SPACE_MODEL;
766         if ( viewStage && viewStageInGS )
767         {
768             buf << INDENT << "vp_Vertex = " << gl_ModelViewMatrix << " * vp_Vertex;\n"
769                 << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
770 
771             space = SPACE_VIEW;
772 
773             for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
774             {
775                 buf << INDENT << i->second._name << "(vp_Vertex); \n";
776             }
777         }
778 
779         if ( clipStage && clipStageInGS )
780         {
781             if ( space == SPACE_MODEL )
782             {
783                 buf << INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
784                     << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
785             }
786             else if ( space == SPACE_VIEW )
787             {
788                 buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
789             }
790 
791             space = SPACE_CLIP;
792 
793             for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
794             {
795                 buf << INDENT << i->second._name << "(vp_Vertex); \n";
796             }
797         }
798 
799         // resolve vertex to its next space:
800         if ( space == SPACE_MODEL )
801         {
802             buf << INDENT << "vp_Vertex = " << gl_ModelViewProjectionMatrix << " * vp_Vertex; \n"
803                 << INDENT << "vp_Normal = normalize(" << gl_NormalMatrix << " * vp_Normal); \n";
804         }
805         else if ( space == SPACE_VIEW )
806         {
807             buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
808         }
809 
810         // Copy globals to output block:
811         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
812             buf << INDENT << "vp_out." << i->name << " = " << i->name << "; \n";
813 
814         buf << INDENT << "gl_Position = vp_Vertex; \n";
815 
816         buf << INDENT << "EmitVertex(); \n"
817             << "} \n";
818 
819 
820         buf << "\nvoid VP_EmitViewVertex() \n"
821             << "{ \n";
822 
823         buf << INDENT << "vp_Vertex = gl_Position; \n";
824         space = SPACE_VIEW;
825         if ( viewStage && viewStageInGS )
826         {
827             for( OrderedFunctionMap::const_iterator i = viewStage->begin(); i != viewStage->end(); ++i )
828             {
829                 buf << INDENT << i->second._name << "(vp_Vertex); \n";
830             }
831         }
832 
833         if ( clipStage && clipStageInGS )
834         {
835             buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
836             space = SPACE_CLIP;
837             for( OrderedFunctionMap::const_iterator i = clipStage->begin(); i != clipStage->end(); ++i )
838             {
839                 buf << INDENT << i->second._name << "(vp_Vertex); \n";
840             }
841         }
842 
843         // resolve vertex to its next space:
844         if ( space == SPACE_VIEW )
845             buf << INDENT << "vp_Vertex = " << gl_ProjectionMatrix << " * vp_Vertex; \n";
846 
847         // Copy globals to output block:
848         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
849             buf << INDENT << "vp_out." << i->name << " = " << i->name << "; \n";
850 
851         buf << INDENT << "gl_Position = vp_Vertex; \n";
852 
853         buf << INDENT << "EmitVertex(); \n"
854             << "} \n";
855 
856         buf << "\n"
857             << "void main(void) \n"
858             << "{ \n"
859             << INDENT "// copy default outputs: \n";
860 
861         // Copy default input block to output block (auto passthrough on first vert)
862         // NOT SURE WE NEED THIS
863         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
864             buf << INDENT << "vp_out." << i->name << " = vp_in[0]." << i->name << "; \n";
865 
866         if ( geomStage )
867         {
868             for( OrderedFunctionMap::const_iterator i = geomStage->begin(); i != geomStage->end(); ++i )
869             {
870                 buf << INDENT << i->second._name << "(); \n";
871             }
872         }
873 
874         buf << "} \n";
875 
876         std::string str;
877         str = buf.str();
878         osg::Shader* geomShader = new osg::Shader( osg::Shader::GEOMETRY, str );
879         geomShader->setName( "main(geometry)" );
880         out_shaders.push_back( geomShader );
881     }
882 
883 
884     //.................................................................................
885 
886 
887     // Build the Fragment shader.
888     if ( hasFS )
889     {
890         stages |= ShaderComp::STAGE_FRAGMENT;
891 
892         std::stringstream buf;
893 
894         buf << "#version " << fs_glsl_version << "\n"
895             << GLSL_DEFAULT_PRECISION_FLOAT << "\n"
896             << "#pragma vp_name VP Fragment Shader Main\n"
897             << (!s_GLES_SHADERS ? "#extension GL_ARB_gpu_shader5 : enable \n" : "");
898 
899         addExtensionsToBuffer(buf, in_extensions);
900 
901         // no output stage? Use default output
902         if (!outputStage)
903         {
904             buf << "\n// Fragment output\n"
905                 << "out vec4 vp_FragColor;\n";
906         }
907 
908         buf << "\n// Fragment stage inputs:\n";
909         buf << "in " << fragdata << " vp_in; \n";
910 
911         buf <<
912             "\n// Fragment stage globals:\n";
913 
914         // Declare stage globals.
915         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
916             buf << i->prec << (i->prec.empty()?"":" ") << i->declaration << ";\n";
917 
918         if ( coloringStage || lightingStage || outputStage )
919         {
920             buf << "\n// Function declarations:\n";
921         }
922 
923         if ( coloringStage )
924         {
925             for( OrderedFunctionMap::const_iterator i = coloringStage->begin(); i != coloringStage->end(); ++i )
926             {
927                 buf << "void " << i->second._name << "(inout vec4 color); \n";
928             }
929         }
930 
931         if ( lightingStage )
932         {
933             for( OrderedFunctionMap::const_iterator i = lightingStage->begin(); i != lightingStage->end(); ++i )
934             {
935                 buf << "void " << i->second._name << "(inout vec4 color); \n";
936             }
937         }
938 
939         if ( outputStage )
940         {
941             for( OrderedFunctionMap::const_iterator i = outputStage->begin(); i != outputStage->end(); ++i )
942             {
943                 buf << "void " << i->second._name << "(inout vec4 color); \n";
944             }
945         }
946 
947         buf <<
948             "\nvoid main(void) \n"
949             "{ \n";
950 
951         // Copy input block to stage globals:
952         for(Variables::const_iterator i = vars.begin(); i != vars.end(); ++i)
953             buf << INDENT << i->name << " = vp_in." << i->name << "; \n";
954 
955         buf << INDENT << "vp_Normal = normalize(vp_Normal); \n";
956 
957         int coloringPass = _fragStageOrder == FRAGMENT_STAGE_ORDER_COLORING_LIGHTING ? 0 : 1;
958         int lightingPass = 1-coloringPass;
959 
960         for(int pass=0; pass<2; ++pass)
961         {
962             if ( coloringStage && (pass == coloringPass) )
963             {
964                 for( OrderedFunctionMap::const_iterator i = coloringStage->begin(); i != coloringStage->end(); ++i )
965                 {
966                     buf << INDENT << i->second._name << "( vp_Color ); \n";
967                 }
968             }
969 
970             if ( lightingStage && (pass == lightingPass) )
971             {
972                 for( OrderedFunctionMap::const_iterator i = lightingStage->begin(); i != lightingStage->end(); ++i )
973                 {
974                     buf << INDENT << i->second._name << "( vp_Color ); \n";
975                 }
976             }
977         }
978 
979         if ( outputStage )
980         {
981             for( OrderedFunctionMap::const_iterator i = outputStage->begin(); i != outputStage->end(); ++i )
982             {
983                 buf << INDENT << i->second._name << "( vp_Color ); \n";
984             }
985         }
986         else
987         {
988             // in the absense of any output functions, generate a default output statement
989             // that simply writes to gl_FragColor.
990             buf << INDENT << "vp_FragColor = vp_Color;\n";
991         }
992         buf << "}\n";
993 
994         std::string str;
995         str = buf.str();
996         osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, str );
997         shader->setName( "main(fragment)" );
998         out_shaders.push_back( shader );
999     }
1000 
1001     return stages;
1002 }
1003 
1004 
1005 osg::Shader*
createColorFilterChainFragmentShader(const std::string & function,const ColorFilterChain & chain) const1006 ShaderFactory::createColorFilterChainFragmentShader(const std::string&      function,
1007                                                     const ColorFilterChain& chain ) const
1008 {
1009     std::stringstream buf;
1010     buf <<
1011         "#version " GLSL_VERSION_STR "\n" << GLSL_DEFAULT_PRECISION_FLOAT "\n";
1012 
1013     // write out the shader function prototypes:
1014     for( ColorFilterChain::const_iterator i = chain.begin(); i != chain.end(); ++i )
1015     {
1016         ColorFilter* filter = i->get();
1017         buf << "void " << filter->getEntryPointFunctionName() << "(inout vec4 color);\n";
1018     }
1019 
1020     // write out the main function:
1021     buf << "void " << function << "(inout vec4 color) \n"
1022         << "{ \n";
1023 
1024     // write out the function calls. if there are none, it's a NOP.
1025     for( ColorFilterChain::const_iterator i = chain.begin(); i != chain.end(); ++i )
1026     {
1027         ColorFilter* filter = i->get();
1028         buf << INDENT << filter->getEntryPointFunctionName() << "(color);\n";
1029     }
1030 
1031     buf << "} \n";
1032 
1033     std::string bufstr;
1034     bufstr = buf.str();
1035     return new osg::Shader(osg::Shader::FRAGMENT, bufstr);
1036 }
1037 
1038 std::string
getRangeUniformName() const1039 ShaderFactory::getRangeUniformName() const
1040 {
1041     return "oe_range_to_bs";
1042 }
1043 
1044 osg::Uniform*
createRangeUniform() const1045 ShaderFactory::createRangeUniform() const
1046 {
1047     return new osg::Uniform(osg::Uniform::FLOAT, getRangeUniformName());
1048 }
1049