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