FreeWRL/FreeX3D  3.0.0
Compositing_Shaders.c
1 /****************************************************************************
2  This file is part of the FreeWRL/FreeX3D Distribution.
3 
4  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
5 
6  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  FreeWRL/FreeX3D 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 General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
18 ****************************************************************************/
19 
20 /* Aug 9, 2016, Castle Game Engine has given us/freewrl-sourceforge
21  special permission to implement their system
22  for compositing shader permutations via special PLUGS, for use in libfreewrl.
23  For use outside of libfreewrl, please consult Castle Game Engine
24  http://castle-engine.sourceforge.net/compositing_shaders.php
25 
26  In the starting default/base shader, structured for web3d lighting model, with PLUG deckarations:
27  ... PLUG: texture_apply (fragment_color, normal_eye_fragment)
28 
29  In an additive effect shader:
30  void PLUG_texture_color(inout vec4 texture_color,
31  const in vec4 tex_coord)
32  {
33 
34  The idea is to call the additive effect function from the main shader, where the same PLUG: <name> is
35  1. paste the additive effect function at the bottom of the main shader, with a uniquized name
36  2. put a forward declaration above the call
37  3. call at the matching PLUG location
38  4. (add in more effects same way)
39  5. compile shaderparts and shaderprogram
40  6. record permutation for re-use, as hash or bitflag of requirements/effects
41 */
42 #include <config.h>
43 #include <system.h>
44 #include <system_threads.h>
45 
46 #include <display.h>
47 #include <internal.h>
48 
49 #include <libFreeWRL.h>
50 #define TRUE 1
51 #define FALSE 0
52 //type
53 // TShaderType = (vertex, geometry, fragment);
54 // TShaderSource = array [TShaderType] of a string list;
55 //
56 enum TShaderType {
57  SHADERPART_VERTEX,
58  SHADERPART_GEOMETRY,
59  SHADERPART_FRAGMENT
60 };
61 //var
62 // { shader for the whole shape }
63 // FinalShader: TShaderSource;
64 
65 
66 char *insertBefore(char *current, char *insert, char* wholeBuffer, int wholeBuffersize){
67  //inserts insert at current location
68  char *newcurrent, *here;
69  int insertlen, wholelen, need, movesize;
70 
71  wholelen = strlen(current) +1; //plus 1 to get the \0 at the end in memmove
72  insertlen = strlen(insert);
73  need = wholelen + insertlen + 1;
74  movesize = wholelen;
75  newcurrent = current;
76  if(need < wholeBuffersize){
77  here = current;
78  newcurrent = current + insertlen;
79  memmove(newcurrent,current,movesize);
80  memcpy(here,insert,insertlen);
81  }else{
82  ConsoleMessage("Not enough buffer for compositing shader buffsz=%d need=%d\n",wholeBuffersize,need);
83  }
84  //if(1){
85  // char *tmp = strdup(wholeBuffer);
86  // printf("strdup: %s",tmp);
87  // free(tmp);
88  //}
89  return newcurrent;
90 }
91 void removeAt(char *here, int len){
92  //removes len bytes from string, moving tail bytes up by len bytes
93  int wholelen, movesize;
94  char *source;
95  wholelen = strlen(here) + 1; //take the \0
96  source = here + len;
97  movesize = wholelen - len;
98  memmove(here,source,movesize);
99 }
100 
101 void extractPlugCall(char *start, char *PlugName,char *PlugParameters){
102  //from the addon shader, get the name PLUG_<name>(declaredParameters)
103  char *pns, *pne, *pps, *ppe;
104  int len;
105  pns = strstr(start,"PLUG: ");
106  pns += strlen("PLUG: ");
107  pne = strchr(pns,' ');
108  len = pne - pns;
109  strncpy(PlugName,pns,len);
110  PlugName[len] = '\0';
111  pps = strchr(pne,'(');
112  ppe = strchr(pps,')') + 1;
113  len = ppe - pps;
114  strncpy(PlugParameters,pps,len);
115  PlugParameters[len] = '\0';
116  //printf("PlugName %s PlugParameters %s\n",PlugName,PlugParameters);
117 }
118 //{ Look for /* PLUG: PlugName (...) */ inside
119  //given CodeForPlugDeclaration.
120  //Return if any occurrence found. }
121  //function LookForPlugDeclaration(
122  // CodeForPlugDeclaration: string list): boolean;
123  //begin
124 int LookForPlugDeclarations( char * CodeForPlugDeclarations, int bsize, char *PlugName, char *ProcedureName, char *ForwardDeclaration) {
125  //in the main code, look for matching PLUG: <PlugName>(plugparams) and place a call to ProcedureName(plugparams)
126  //Result := false
127  //for each S: string in CodeForPlugDeclaration do
128  //begin
129  int Result;
130  //i = 0;
131  //while(CodeForPlugDeclarations[i]){
132  char *S;
133  char MainPlugName[100], MainPlugParams[1000];
134  //char PlugDeclarationBuffer[10000];
135  int AnyOccurrencesHere = FALSE; //:= false
136  Result = FALSE;
137  //strcpy_s(PlugDeclarationBuffer,10000,*CodeForPlugDeclarations);
138  S = CodeForPlugDeclarations;
139  do {
140  //while we can find an occurrence
141  // of /* PLUG: PlugName (...) */ inside S do
142  //begin
143  S = strstr(S,"/* PLUG: ");
144  //if(S)
145  // printf("found PLUG:\n");
146  //else
147  // printf("PLUG: not found\n");
148  if(S){
149  char ProcedureCallBuffer[500], *ProcedureCall;
150  extractPlugCall(S,MainPlugName,MainPlugParams);
151  if(!strcmp(MainPlugName,PlugName)){
152  //found the place in the main shader to make the call to addon function
153  //insert into S a call to ProcedureName,
154  //with parameters specified inside the /* PLUG: PlugName (...) */,
155  //right before the place where we found /* PLUG: PlugName (...) */
156  ProcedureCall = ProcedureCallBuffer;
157  sprintf(ProcedureCall,"%s%s;\n",ProcedureName,MainPlugParams);
158  S = insertBefore(S,ProcedureCall,CodeForPlugDeclarations,bsize);
159  AnyOccurrencesHere = TRUE; //:= true
160  Result = TRUE; //:= true
161  }else{
162  //printf("found a PLUG: %s but doesn't match PLUG_%s\n",MainPlugName,PlugName);
163  }
164  S += strlen("/* PLUG:") + strlen(MainPlugName) + strlen(MainPlugParams);
165  }
166  }
167  while(S); //AnyOccurrencesHere);
168  //end
169 
170  //if AnyOccurrencesHere then
171  if(AnyOccurrencesHere){
172  //insert the PlugForwardDeclaration into S,
173  //at the place of /* PLUG-DECLARATIONS */ inside
174  //(or at the beginning, if no /* PLUG-DECLARATIONS */)
175  S = CodeForPlugDeclarations;
176  S = strstr(S,"/* PLUG-DECLARATIONS */");
177  if(!S) S = CodeForPlugDeclarations;
178  S = insertBefore(S,ForwardDeclaration,CodeForPlugDeclarations,bsize);
179  //S = *CodeForPlugDeclarations;
180  //*CodeForPlugDeclarations = strdup(PlugDeclarationBuffer);
181  //FREE_IF_NZ(S);
182  }else{
183  printf("didn't find PLUG_%s\n",PlugName);
184  }
185  // i++;
186  //} //end
187  return Result;
188 } //end
189 
190 
191 void replaceAll(char *buffer,int bsize, char *oldstr, char *newstr){
192  char *found;
193  while((found = strstr(buffer,oldstr))){
194  removeAt(found,strlen(oldstr));
195  insertBefore(found,newstr,buffer,bsize);
196  }
197 
198 }
199 //procedure Plug(
200 // EffectPartType: TShaderType;
201 // PlugValue: string;
202 // CompleteCode: TShaderSource);
203 //char *strpbrk(const char *str1, const char *str2) finds the first character in the string str1 that matches any character specified in str2. This does not include the terminating null-characters.
204 void extractPlugName(char *start, char *PlugName,char *PlugDeclaredParameters){
205  //from the addon shader, get the name PLUG_<name>(declaredParameters)
206  char *pns, *pne, *pps, *ppe;
207  int len;
208  pns = strstr(start,"PLUG_");
209  pns += strlen("PLUG_");
210  //pne = strchr(pns,' ');
211  pne = strpbrk(pns," (");
212  len = pne - pns;
213  strncpy(PlugName,pns,len);
214  PlugName[len] = '\0';
215  pps = strchr(pne,'(');
216  ppe = strchr(pps,')') + 1;
217  len = ppe - pps;
218  strncpy(PlugDeclaredParameters,pps,len);
219  PlugDeclaredParameters[len] = '\0';
220  //printf("PlugName %s PlugDeclaredParameters %s\n",PlugName,PlugDeclaredParameters);
221 }
222 #define SBUFSIZE 32767 //must hold final size of composited shader part, could do per-gglobal-instance malloced buffer instead and resize to largest composited shader
223 #define PBUFSIZE 16384 //must hold largets PlugValue
224 int fw_strcpy_s(char *dest, int destsize, const char *source){
225  int ier = -1;
226  if(dest)
227  if(source && strlen(source) < (unsigned)destsize){
228  strcpy(dest,source);
229  ier = 0;
230  }
231  return ier;
232 }
233 int fw_strcat_s(char *dest, int destsize, const char *source){
234  int ier = -1;
235  if(dest){
236  int destlen = strlen(dest);
237  if(source)
238  if(strlen(source)+destlen < (unsigned)destsize){
239  strcat(dest,source);
240  ier = 0;
241  }
242  }
243  return ier;
244 }
245 void Plug( int EffectPartType, const char *PlugValue, char **CompleteCode, int *unique_int)
246 {
247  //Algo:
248  // outer loop: search for PLUG_<name> in (addon) effect
249  // inner loop: search for matching PLUG: <name> in main shader
250  // if found, paste addon into main:
251  // a) forward declaration at top,
252  // b) method call at PLUG: point
253  // c) method definition at bottom
254  //var
255  // PlugName, ProcedureName, PlugForwardDeclaration: string;
256  char PlugName[100], PlugDeclaredParameters[1000], PlugForwardDeclaration[1000], ProcedureName[100], PLUG_PlugName[100];
257  char Code[SBUFSIZE], Plug[PBUFSIZE];
258  int HasGeometryMain = FALSE, AnyOccurrences;
259  char *found;
260  int err;
261 
262  UNUSED(err);
263 
264  //var
265  // Code: string list;
266  //begin
267 
268  if(!CompleteCode[EffectPartType]) return;
269  err = fw_strcpy_s(Code,SBUFSIZE, CompleteCode[EffectPartType]);
270  err = fw_strcpy_s(Plug,PBUFSIZE, PlugValue);
271 
272  //HasGeometryMain := HasGeometryMain or
273  // ( EffectPartType = geometry and
274  // PlugValue contains 'main()' );
275  HasGeometryMain = HasGeometryMain ||
276  ((EffectPartType == SHADERPART_GEOMETRY) && strstr("main(",Plug));
277 
278  //while we can find PLUG_xxx inside PlugValue do
279  //begin
280  found = Plug;
281  do {
282  found = strstr(found,"void PLUG_"); //where = strstr(haystack,needle)
283  //if(!found)
284  // printf("I'd like to complain: void PLUG_ isn't found in the addon\n");
285  if(found){
286  //PlugName := the plug name we found, the "xxx" inside PLUG_xxx
287  //PlugDeclaredParameters := parameters declared at PLUG_xxx function
288  extractPlugName(found,PlugName,PlugDeclaredParameters);
289  found += strlen("void PLUG_") + strlen(PlugName) + strlen(PlugDeclaredParameters);
290  //{ Rename found PLUG_xxx to something unique. }
291  //ProcedureName := generate new unique procedure name,
292  //for example take 'plugged_' + some unique integer
293  sprintf(ProcedureName,"%s_%d",PlugName,(*unique_int));
294  (*unique_int)++;
295 
296  //replace inside PlugValue all occurrences of 'PLUG_' + PlugName
297  //with ProcedureName
298  sprintf(PLUG_PlugName,"%s%s","PLUG_",PlugName);
299  replaceAll(Plug,PBUFSIZE,PLUG_PlugName,ProcedureName);
300 
301  //PlugForwardDeclaration := 'void ' + ProcedureName +
302  //PlugDeclaredParameters + ';' + newline
303  sprintf(PlugForwardDeclaration,"void %s%s;\n",ProcedureName,PlugDeclaredParameters);
304 
305  //AnyOccurrences := LookForPlugDeclaration(Code)
306  AnyOccurrences = LookForPlugDeclarations(Code,SBUFSIZE, PlugName,ProcedureName,PlugForwardDeclaration);
307 
308  /* If the plug declaration is not found in Code, then try to find it
309  in the final shader. This happens if Code is special for given
310  light/texture effect, but PLUG_xxx is not special to the
311  light/texture effect (it is applicable to the whole shape as well).
312  For example, using PLUG_vertex_object_space inside
313  the X3DTextureNode.effects.
314  */
315  //if not AnyOccurrences and
316  // Code <> Source[EffectPartType] then
317  // AnyOccurrences := LookForPlugDeclaration(Source[EffectPartType])
318  //if(!AnyOccurrences && Code != Source[EffectPartType]){
319  // AnyOccurrences = LookForPlugDeclarations(Source[EffectPartType]);
320  //}
321  //if not AnyOccurrences then
322  // Warning('Plug name ' + PlugName + ' not declared')
323  //}
324  if(!AnyOccurrences){
325  ConsoleMessage("Plug name %s not declared\n",PlugName);
326  }
327  }
328  }while(found);
329  //end
330 
331  /*{ regardless if any (and how many) plug points were found,
332  always insert PlugValue into Code. This way EffectPart with a library
333  of utility functions (no PLUG_xxx inside) also works. }*/
334  //Code.Add(PlugValue)
335  //printf("strlen Code = %d strlen PlugValue=%d\n",strlen(Code),strlen(PlugValue));
336  err = fw_strcat_s(Code,SBUFSIZE,Plug);
337  FREE_IF_NZ(CompleteCode[EffectPartType]);
338  CompleteCode[EffectPartType] = strdup(Code);
339 } //end
340 
341 void AddVersion( int EffectPartType, int versionNumber, char **CompleteCode){
342  //puts #version <number> at top of shader, first line
343  char Code[SBUFSIZE], line[1000];
344  char *found;
345  int err;
346 
347  UNUSED(err);
348 
349  if (!CompleteCode[EffectPartType]) return;
350  err = fw_strcpy_s(Code, SBUFSIZE, CompleteCode[EffectPartType]);
351 
352  found = Code;
353  if (found) {
354  sprintf(line, "#version %d \n", versionNumber);
355  insertBefore(found, line, Code, SBUFSIZE);
356  FREE_IF_NZ(CompleteCode[EffectPartType]);
357  CompleteCode[EffectPartType] = strdup(Code);
358  }
359 }
360 void AddDefine0( int EffectPartType, const char *defineName, int defineValue, char **CompleteCode)
361 {
362  //same as AddDEfine but you can say a number other than 1
363  char Code[SBUFSIZE], line[1000];
364  char *found;
365  int err;
366 
367  UNUSED(err);
368 
369  if(!CompleteCode[EffectPartType]) return;
370  err = fw_strcpy_s(Code,SBUFSIZE, CompleteCode[EffectPartType]);
371 
372  found = strstr(Code,"/* DEFINE");
373  if(found){
374  sprintf(line,"#define %s %d \n",defineName,defineValue);
375  insertBefore(found,line,Code,SBUFSIZE);
376  FREE_IF_NZ(CompleteCode[EffectPartType]);
377  CompleteCode[EffectPartType] = strdup(Code);
378  }
379 }
380 void AddDefine( int EffectPartType, const char *defineName, char **CompleteCode){
381  //adds #define <defineName> 1 to shader part, just above "/* DEFINES */" line in ShaderPart
382  // char *CompleteCode[3] has char *vs *gs *fs parts, and will be realloced inside
383  AddDefine0(EffectPartType,defineName,1,CompleteCode);
384 }
385 
386 //procedure EnableEffects(
387 // Effects: list of Effect nodes;
388 // CompleteCode: TShaderSource);
389 //begin
390 // for each Effect in Effects do
391 // if Effect.enabled and
392 // Effect.language matches renderer shader language then
393 // for each EffectPart in Effect.parts do
394 // Plug(EffectPart.type, GetUrl(EffectPart.url), CompleteCode)
395 //end
396 void EnableEffect(struct X3D_Node * node, char **CompletedCode, int *unique_int){
397  int i, ipart;
398  char *str;
399 
400  ipart=SHADERPART_VERTEX;
401  struct X3D_Effect *effect = (struct X3D_Effect *)node;
402  for(i=0;i<effect->parts.n;i++){
403  struct X3D_EffectPart *part = (struct X3D_EffectPart*)effect->parts.p[i];
404  if(part->_nodeType == NODE_EffectPart){
405  if(!strcmp(part->type->strptr,"FRAGMENT"))
406  ipart = SHADERPART_FRAGMENT;
407  else if(!strcmp(part->type->strptr,"VERTEX"))
408  ipart = SHADERPART_VERTEX;
409  str = part->url.p[0]->strptr;
410  if(!strncmp(str,"data:text/plain,",strlen("data:text/plain,")))
411  str += strlen("data:text/plain,");
412  Plug(ipart,str, CompletedCode, unique_int);
413  }
414  }
415 }
416 Stack *getEffectStack();
417 void EnableEffects( char **CompletedCode, int *unique_int){
418  int i;
419  Stack *effect_stack;
420  effect_stack = getEffectStack();
421  for(i=0;i<vectorSize(effect_stack);i++){
422  struct X3D_Node *node = vector_get(struct X3D_Node*,effect_stack,i);
423  if(node->_nodeType == NODE_Effect){
424  EnableEffect(node,CompletedCode,unique_int);
425  }
426  }
427 }
428 
429 
430 
431 //maxLights = 8;
432 //#if defined (GL_ES_VERSION_2_0)
433 //precision highp float;
434 //precision mediump float;
435 //#endif
436 
437 /*
438 started with: http://svn.code.sf.net/p/castle-engine/code/trunk/castle_game_engine/src/x3d/opengl/glsl/template_mobile.vs
439  castle freewrl
440  uniforms:
441  castle_ModelViewMatrix fw_ModelViewMatrix
442  castle_ProjectionMatrix fw_ProjectionMatrix
443  castle_NormalMatrix fw_NormalMatrix
444  castle_MaterialDiffuseAlpha fw_FrontMaterial.diffuse.a
445  castle_MaterialShininess fw_FrontMaterial.shininess
446  castle_SceneColor fw_FrontMaterial.ambient
447  castle_castle_UnlitColor fw_FrontMaterial.emission
448  fw_FrontMaterial.specular
449  per-vertex attributes
450  castle_Vertex fw_Vertex
451  castle_Normal fw_Normal
452  castle_ColorPerVertex fw_Color
453 
454  defines
455  LIT
456  COLOR_PER_VERTEX
457  CASTLE_BUGGY_GLSL_READ_VARYING
458 
459 define LIT if have Shape->appearance->material and NOT linepoints
460 define TWO if you have backface colors ie X3DTwoSidedMaterial
461  http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/shape.html#TwoSidedMaterial
462 define LINE if you have Shape->appearance->material and is linepoints (lines and points use mat.emissive)
463 define TEX if you have texture
464 define CPV if colorNode && image_channels < 3
465 define MAT if material is valid
466 */
467 
468 /* Generic GLSL vertex shader.
469  Used by ../castlerendererinternalshader.pas to construct the final shader.
470 
471  This is converted to template.vs.inc, and is then compiled
472  in program's binary.
473  When you change this file, rerun `make' and then recompile Pascal sources.
474 */
475 
476 static const GLchar *genericVertexGLES2 = "\
477 /* DEFINES */ \n\
478 /* Generic GLSL vertex shader, used on OpenGL ES. */ \n\
479  \n\
480 uniform mat4 fw_ModelViewMatrix; \n\
481 uniform mat4 fw_ProjectionMatrix; \n\
482 uniform mat3 fw_NormalMatrix; \n\
483 #ifdef CUB \n\
484 uniform mat4 fw_ModelViewInverseMatrix; \n\
485 #endif //CUB \n\
486 attribute vec4 fw_Vertex; \n\
487 attribute vec3 fw_Normal; \n\
488  \n\
489 #ifdef TEX \n\
490 uniform mat4 fw_TextureMatrix0; \n\
491 attribute vec4 fw_MultiTexCoord0; \n\
492 //varying vec3 v_texC; \n\
493 varying vec3 fw_TexCoord[4]; \n\
494 #ifdef TEX3D \n\
495 uniform int tex3dUseVertex; \n\
496 #endif //TEX3D \n\
497 #ifdef MTEX \n\
498 uniform mat4 fw_TextureMatrix1; \n\
499 uniform mat4 fw_TextureMatrix2; \n\
500 uniform mat4 fw_TextureMatrix3; \n\
501 attribute vec4 fw_MultiTexCoord1; \n\
502 attribute vec4 fw_MultiTexCoord2; \n\
503 attribute vec4 fw_MultiTexCoord3; \n\
504 #endif //MTEX \n\
505 #ifdef TGEN \n\
506  #define TCGT_CAMERASPACENORMAL 0 \n\
507  #define TCGT_CAMERASPACEPOSITION 1 \n\
508  #define TCGT_CAMERASPACEREFLECTION 2 \n\
509  #define TCGT_COORD 3 \n\
510  #define TCGT_COORD_EYE 4 \n\
511  #define TCGT_NOISE 5 \n\
512  #define TCGT_NOISE_EYE 6 \n\
513  #define TCGT_SPHERE 7 \n\
514  #define TCGT_SPHERE_LOCAL 8 \n\
515  #define TCGT_SPHERE_REFLECT 9 \n\
516  #define TCGT_SPHERE_REFLECT_LOCAL 10 \n\
517  uniform int fw_textureCoordGenType; \n\
518 #endif //TGEN \n\
519 #endif //TEX \n\
520 #ifdef FILL \n\
521 varying vec2 hatchPosition; \n\
522 #endif //FILL \n\
523 \n\
524 /* PLUG-DECLARATIONS */ \n\
525  \n\
526 varying vec4 castle_vertex_eye; \n\
527 varying vec3 castle_normal_eye; \n\
528 varying vec4 castle_Color; //DA diffuse ambient term \n\
529  \n\
530 //uniform float castle_MaterialDiffuseAlpha; \n\
531 //uniform float castle_MaterialShininess; \n\
532 /* Color summed with all the lights. \n\
533  Like gl_Front/BackLightModelProduct.sceneColor: \n\
534  material emissive color + material ambient color * global (light model) ambient. \n\
535 */ \n\
536 \n\
537 #ifdef LITE \n\
538 #define MAX_LIGHTS 8 \n\
539 uniform int lightcount; \n\
540 //uniform float lightRadius[MAX_LIGHTS]; \n\
541 uniform int lightType[MAX_LIGHTS];//ANGLE like this \n\
542 struct fw_LightSourceParameters { \n\
543  vec4 ambient; \n\
544  vec4 diffuse; \n\
545  vec4 specular; \n\
546  vec4 position; \n\
547  vec4 halfVector; \n\
548  vec4 spotDirection; \n\
549  float spotBeamWidth; \n\
550  float spotCutoff; \n\
551  vec3 Attenuations; \n\
552  float lightRadius; \n\
553 }; \n\
554 \n\
555 uniform fw_LightSourceParameters fw_LightSource[MAX_LIGHTS] /* gl_MaxLights */ ;\n\
556 #endif //LITE \n\
557 \n\
558 //uniform vec3 castle_SceneColor; \n\
559 //uniform vec4 castle_UnlitColor; \n\
560 #ifdef UNLIT \n\
561 uniform vec4 fw_UnlitColor; \n\
562 #endif //UNLIT \n\
563 #ifdef LIT \n\
564 struct fw_MaterialParameters { \n\
565  vec4 emission; \n\
566  vec4 ambient; \n\
567  vec4 diffuse; \n\
568  vec4 specular; \n\
569  float shininess; \n\
570 }; \n\
571 uniform fw_MaterialParameters fw_FrontMaterial; \n\
572 varying vec3 castle_ColorES; //emissive shininess term \n\
573 vec3 castle_Emissive; \n\
574 #ifdef TWO \n\
575 uniform fw_MaterialParameters fw_BackMaterial; \n\
576 #endif //TWO \n\
577 #endif //LIT \n\
578 #ifdef FOG \n\
579 struct fogParams \n\
580 { \n\
581  vec4 fogColor; \n\
582  float visibilityRange; \n\
583  float fogScale; //applied on cpu side to visrange \n\
584  int fogType; // 0 None, 1= FOGTYPE_LINEAR, 2 = FOGTYPE_EXPONENTIAL \n\
585  // ifdefed int haveFogCoords; \n\
586 }; \n\
587 uniform fogParams fw_fogparams; \n\
588 #ifdef FOGCOORD \n\
589 attribute float fw_FogCoords; \n\
590 #endif \n\
591 #endif //FOG \n\
592 float castle_MaterialDiffuseAlpha; \n\
593 float castle_MaterialShininess; \n\
594 vec3 castle_SceneColor; \n\
595 vec4 castle_UnlitColor; \n\
596 vec4 castle_Specular; \n\
597  \n\
598 #ifdef CPV \n\
599 attribute vec4 fw_Color; //castle_ColorPerVertex; \n\
600 varying vec4 cpv_Color; \n\
601 #endif //CPV \n\
602 #ifdef PARTICLE \n\
603 uniform vec3 particlePosition; \n\
604 uniform int fw_ParticleGeomType; \n\
605 #endif //PARTICLE \n\
606  \n\
607  vec3 dehomogenize(in mat4 matrix, in vec4 vector){ \n\
608  vec4 tempv = vector; \n\
609  if(tempv.w == 0.0) tempv.w = 1.0; \n\
610  vec4 temp = matrix * tempv; \n\
611  float winv = 1.0/temp.w; \n\
612  return temp.xyz * winv; \n\
613  } \n\
614 void main(void) \n\
615 { \n\
616  #ifdef LIT \n\
617  castle_MaterialDiffuseAlpha = fw_FrontMaterial.diffuse.a; \n\
618  #ifdef TEX \n\
619  #ifdef TAREP \n\
620  //to modulate or not to modulate, this is the question \n\
621  //in here, we turn off modulation and use image alpha \n\
622  castle_MaterialDiffuseAlpha = 1.0; \n\
623  #endif //TAREP \n\
624  #endif //TEX \n\
625  castle_MaterialShininess = fw_FrontMaterial.shininess; \n\
626  castle_SceneColor = fw_FrontMaterial.ambient.rgb; \n\
627  castle_Specular = fw_FrontMaterial.specular; \n\
628  castle_Emissive = fw_FrontMaterial.emission.rgb; \n\
629  #ifdef LINE \n\
630  castle_SceneColor = vec3(0.0,0.0,0.0); //line gets color from castle_Emissive \n\
631  #endif //LINE\n\
632  #else //LIT \n\
633  //default unlits in case we dont set them \n\
634  castle_UnlitColor = vec4(1.0,1.0,1.0,1.0); \n\
635  castle_MaterialDiffuseAlpha = 1.0; \n\
636  #endif //LIT \n\
637  \n\
638  #ifdef FILL \n\
639  hatchPosition = fw_Vertex.xy; \n\
640  #endif //FILL \n\
641  \n\
642  vec4 vertex_object = fw_Vertex; \n\
643  #ifdef PARTICLE \n\
644  if(fw_ParticleGeomType != 4){ \n\
645  vertex_object.xyz += particlePosition; \n\
646  } \n\
647  #endif //PARTICLE \n\
648  vec3 normal_object = fw_Normal; \n\
649  /* PLUG: vertex_object_space_change (vertex_object, normal_object) */ \n\
650  /* PLUG: vertex_object_space (vertex_object, normal_object) */ \n\
651  \n\
652  #ifdef CASTLE_BUGGY_GLSL_READ_VARYING \n\
653  /* use local variables, instead of reading + writing to varying variables, \n\
654  when VARYING_NOT_READABLE */ \n\
655  vec4 temp_castle_vertex_eye; \n\
656  vec3 temp_castle_normal_eye; \n\
657  vec4 temp_castle_Color; \n\
658  #define castle_vertex_eye temp_castle_vertex_eye \n\
659  #define castle_normal_eye temp_castle_normal_eye \n\
660  #define castle_Color temp_castle_Color \n\
661  #endif //CASTLE_BUGGY_GLSL_READ_VARYING \n\
662  \n\
663  castle_vertex_eye = fw_ModelViewMatrix * vertex_object; \n\
664  #ifdef PARTICLE \n\
665  //sprite: align to viewer \n\
666  if(fw_ParticleGeomType == 4){ \n\
667  vec4 ppos = vec4(particlePosition,1.0); \n\
668  vec4 particle_eye = fw_ModelViewMatrix * ppos; \n\
669  ppos.x += 1.0; \n\
670  vec4 particle_eye1 = fw_ModelViewMatrix * ppos; \n\
671  float pscal = length(particle_eye1.xyz - particle_eye.xyz); \n\
672  castle_vertex_eye = particle_eye + pscal*vertex_object; \n\
673  } \n\
674  #endif //PARTICLE \n\
675  castle_normal_eye = normalize(fw_NormalMatrix * normal_object); \n\
676  \n\
677  /* PLUG: vertex_eye_space (castle_vertex_eye, castle_normal_eye) */ \n\
678  \n\
679  #ifdef LIT \n\
680  castle_ColorES = castle_Emissive; \n\
681  castle_Color = vec4(castle_SceneColor, 1.0); \n\
682  /* PLUG: add_light_contribution2 (castle_Color, castle_ColorES, castle_vertex_eye, castle_normal_eye, castle_MaterialShininess) */ \n\
683  /* PLUG: add_light_contribution (castle_Color, castle_vertex_eye, castle_normal_eye, castle_MaterialShininess) */ \n\
684  castle_Color.a = castle_MaterialDiffuseAlpha; \n\
685  /* Clamp sum of lights colors to be <= 1. See template.fs for comments. */ \n\
686  castle_Color.rgb = min(castle_Color.rgb, 1.0); \n\
687  #else //LIT \n\
688  castle_Color.rgb = castle_UnlitColor.rgb; \n\
689  #endif //LIT \n\
690  \n\
691  #ifdef CPV //color per vertex \n\
692  cpv_Color = fw_Color; \n\
693  #endif //CPV \n\
694  \n\
695  #ifdef TEX \n\
696  vec4 texcoord = fw_MultiTexCoord0; \n\
697  #ifdef TEX3D \n\
698  //to re-use vertex coords as texturecoords3D, we need them in 0-1 range: CPU calc of fw_TextureMatrix0 \n\
699  if(tex3dUseVertex == 1) \n\
700  texcoord = vec4(fw_Vertex.xyz,1.0); \n\
701  #endif //TEX3D \n\
702  #ifdef TGEN \n\
703  { \n\
704  vec3 vertexNorm; \n\
705  vec4 vertexPos; \n\
706  vec3 texcoord3 = texcoord.xyz; \n\
707  vertexNorm = normalize(fw_NormalMatrix * fw_Normal); \n\
708  vertexPos = fw_ModelViewMatrix * fw_Vertex; \n\
709  /* sphereEnvironMapping Calculation */ \n\
710  vec3 u=normalize(vec3(vertexPos)); /* u is normalized position, used below more than once */ \n\
711  vec3 r= reflect(u,vertexNorm); \n\
712  if (fw_textureCoordGenType==TCGT_SPHERE) { /* TCGT_SPHERE GL_SPHERE_MAP OpenGL Equiv */ \n\
713  float m=2.0 * sqrt(r.x*r.x + r.y*r.y + (r.z*1.0)*(r.z*1.0)); \n\
714  texcoord3 = vec3(r.x/m+0.5,r.y/m+0.5,0.0); \n\
715  }else if (fw_textureCoordGenType==TCGT_CAMERASPACENORMAL) { \n\
716  /* GL_REFLECTION_MAP used for sampling cubemaps */ \n\
717  float dotResult = 2.0 * dot(u,r); \n\
718  texcoord3 = vec3(u-r)*dotResult; \n\
719  }else if (fw_textureCoordGenType==TCGT_COORD) { \n\
720  /* 3D textures can use coords in 0-1 range */ \n\
721  texcoord3 = fw_Vertex.xyz; //xyz; \n\
722  } else { /* default usage - like default CubeMaps */ \n\
723  vec3 u=normalize(vec3(fw_ProjectionMatrix * fw_Vertex)); /* myEyeVertex */ \n\
724  texcoord3 = reflect(u,vertexNorm); \n\
725  } \n\
726  texcoord.xyz = texcoord3; \n\
727  } \n\
728  #endif //TGEN \n\
729  fw_TexCoord[0] = dehomogenize(fw_TextureMatrix0, texcoord); \n\
730  #ifdef MTEX \n\
731  fw_TexCoord[1] = dehomogenize(fw_TextureMatrix1,fw_MultiTexCoord1); \n\
732  fw_TexCoord[2] = dehomogenize(fw_TextureMatrix2,fw_MultiTexCoord2); \n\
733  fw_TexCoord[3] = dehomogenize(fw_TextureMatrix3,fw_MultiTexCoord3); \n\
734  #endif //MTEX \n\
735  #endif //TEX \n\
736  \n\
737  gl_Position = fw_ProjectionMatrix * castle_vertex_eye; \n\
738  \n\
739  #ifdef CUB \n\
740  //cubemap \n\
741  vec4 camera = fw_ModelViewInverseMatrix * vec4(0.0,0.0,0.0,1.0); \n\
742  //vec3 u = normalize( vec4(castle_vertex_eye - camera).xyz ); \n\
743  vec3 u = normalize( vec4(vertex_object + camera).xyz ); \n\
744  vec3 v = normalize(fw_Normal); \n\
745  fw_TexCoord[0] = normalize(reflect(u,v)); //computed in object space \n\
746  fw_TexCoord[0].st = -fw_TexCoord[0].st; //helps with renderman cubemap convention \n\
747  #endif //CUB \n\
748  #ifdef CASTLE_BUGGY_GLSL_READ_VARYING \n\
749  #undef castle_vertex_eye \n\
750  #undef castle_normal_eye \n\
751  #undef castle_Color \n\
752  castle_vertex_eye = temp_castle_vertex_eye; \n\
753  castle_normal_eye = temp_castle_normal_eye; \n\
754  castle_Color = temp_castle_Color; \n\
755  #endif //CASTLE_BUGGY_GLSL_READ_VARYING \n\
756  \n\
757  #ifdef FOG \n\
758  #ifdef FOGCOORD \n\
759  castle_vertex_eye.z = fw_FogCoords; \n\
760  #endif //FOGCOORD \n\
761  #endif //FOG \n\
762  #ifdef UNLIT \n\
763  castle_Color = fw_UnlitColor; \n\
764  #endif //UNLIT \n\
765 } \n";
766 
767 
768 /* Generic GLSL fragment shader.
769  Used by ../castlerendererinternalshader.pas to construct the final shader.
770 
771  This is converted to template.fs.inc, and is then compiled
772  in program's binary.
773  When you change this file, rerun `make' and then recompile Pascal sources.
774 */
775 /*
776  started with: http://svn.code.sf.net/p/castle-engine/code/trunk/castle_game_engine/src/x3d/opengl/glsl/template_mobile.fs
777  defines:
778  GL_ES_VERSION_2_0 - non-desktop
779  HAS_GEOMETRY_SHADER - version 3+ gles
780 */
781 
782 
783 
784 
785 
786 
787 
788 
789 
790 
791 
792 
793 
794 
795 
796 
797 
798 
799 
800 static const GLchar *genericFragmentGLES2 = "\
801 /* DEFINES */ \n\
802 #ifdef MOBILE \n\
803 //precision highp float; \n\
804 precision mediump float; \n\
805 #endif //MOBILE \n\
806 /* Generic GLSL fragment shader, used on OpenGL ES. */ \n\
807  \n\
808 varying vec4 castle_Color; \n\
809  \n\
810 #ifdef LITE \n\
811 #define MAX_LIGHTS 8 \n\
812 uniform int lightcount; \n\
813 //uniform float lightRadius[MAX_LIGHTS]; \n\
814 uniform int lightType[MAX_LIGHTS];//ANGLE like this \n\
815 struct fw_LightSourceParameters { \n\
816  vec4 ambient; \n\
817  vec4 diffuse; \n\
818  vec4 specular; \n\
819  vec4 position; \n\
820  vec4 halfVector; \n\
821  vec4 spotDirection; \n\
822  float spotBeamWidth; \n\
823  float spotCutoff; \n\
824  vec3 Attenuations; \n\
825  float lightRadius; \n\
826 }; \n\
827 \n\
828 uniform fw_LightSourceParameters fw_LightSource[MAX_LIGHTS] /* gl_MaxLights */ ;\n\
829 #endif //LITE \n\
830 \n\
831 #ifdef CPV \n\
832 varying vec4 cpv_Color; \n\
833 #endif //CPV \n\
834 \n\
835 #ifdef TEX \n\
836 #ifdef CUB \n\
837 uniform samplerCube fw_Texture_unit0; \n\
838 #else //CUB \n\
839 uniform sampler2D fw_Texture_unit0; \n\
840 #endif //CUB \n\
841 varying vec3 fw_TexCoord[4]; \n\
842 #ifdef TEX3D \n\
843 uniform int tex3dTiles[3]; \n\
844 uniform int repeatSTR[3]; \n\
845 uniform int magFilter; \n\
846 #endif //TEX3D \n\
847 #ifdef TEX3DLAY \n\
848 uniform sampler2D fw_Texture_unit1; \n\
849 uniform sampler2D fw_Texture_unit2; \n\
850 uniform sampler2D fw_Texture_unit3; \n\
851 uniform int textureCount; \n\
852 #endif //TEX3DLAY \n\
853 #ifdef MTEX \n\
854 uniform sampler2D fw_Texture_unit1; \n\
855 uniform sampler2D fw_Texture_unit2; \n\
856 uniform sampler2D fw_Texture_unit3; \n\
857 uniform ivec2 fw_Texture_mode0; \n\
858 uniform ivec2 fw_Texture_mode1; \n\
859 uniform ivec2 fw_Texture_mode2; \n\
860 uniform ivec2 fw_Texture_mode3; \n\
861 uniform ivec2 fw_Texture_source0; \n\
862 uniform ivec2 fw_Texture_source1; \n\
863 uniform ivec2 fw_Texture_source2; \n\
864 uniform ivec2 fw_Texture_source3; \n\
865 uniform int fw_Texture_function0; \n\
866 uniform int fw_Texture_function1; \n\
867 uniform int fw_Texture_function2; \n\
868 uniform int fw_Texture_function3; \n\
869 uniform int textureCount; \n\
870 uniform vec4 mt_Color; \n\
871 #define MTMODE_ADD 1\n \
872 #define MTMODE_ADDSIGNED 2\n \
873 #define MTMODE_ADDSIGNED2X 3\n \
874 #define MTMODE_ADDSMOOTH 4\n \
875 #define MTMODE_BLENDCURRENTALPHA 5\n \
876 #define MTMODE_BLENDDIFFUSEALPHA 6\n \
877 #define MTMODE_BLENDFACTORALPHA 7\n \
878 #define MTMODE_BLENDTEXTUREALPHA 8\n \
879 #define MTMODE_DOTPRODUCT3 9\n \
880 #define MTMODE_MODULATE 10\n \
881 #define MTMODE_MODULATE2X 11\n \
882 #define MTMODE_MODULATE4X 12\n \
883 #define MTMODE_MODULATEALPHA_ADDCOLOR 13\n \
884 #define MTMODE_MODULATEINVALPHA_ADDCOLOR 14\n \
885 #define MTMODE_MODULATEINVCOLOR_ADDALPHA 15\n \
886 #define MTMODE_OFF 16\n \
887 #define MTMODE_REPLACE 17\n \
888 #define MTMODE_SELECTARG1 18\n \
889 #define MTMODE_SELECTARG2 19\n \
890 #define MTMODE_SUBTRACT 20\n \
891 #define MTSRC_DIFFUSE 1 \n\
892 #define MTSRC_FACTOR 2 \n\
893 #define MTSRC_SPECULAR 3 \n\
894 #define MTFN_ALPHAREPLICATE 0 \n\
895 #define MTFN_COMPLEMENT 1 \n\
896 #define MT_DEFAULT -1 \n\
897 \n\
898 void finalColCalc(inout vec4 prevColour, in int mode, in int modea, in int func, in sampler2D tex, in vec2 texcoord) { \n\
899  vec4 texel = texture2D(tex,texcoord); \n\
900  vec4 rv = vec4(1.,0.,1.,1.); \n\
901  if (mode==MTMODE_OFF) { \n\
902  rv = vec4(prevColour); \n\
903  } else if (mode==MTMODE_REPLACE) { \n\
904  rv = vec4(texture2D(tex, texcoord)); \n\
905  }else if (mode==MTMODE_MODULATE) { \n\
906  vec3 ct,cf; \n\
907  float at,af; \n\
908  cf = prevColour.rgb; \n\
909  af = prevColour.a; \n\
910  ct = texel.rgb; \n\
911  at = texel.a; \n\
912  rv = vec4(ct*cf, at*af); \n\
913  } else if (mode==MTMODE_MODULATE2X) { \n\
914  vec3 ct,cf; \n\
915  float at,af; \n\
916  cf = prevColour.rgb; \n\
917  af = prevColour.a; \n\
918  ct = texel.rgb; \n\
919  at = texel.a; \n\
920  rv = vec4(vec4(ct*cf, at*af)*vec4(2.,2.,2.,2.)); \n\
921  }else if (mode==MTMODE_MODULATE4X) { \n\
922  vec3 ct,cf; \n\
923  float at,af; \n\
924  cf = prevColour.rgb; \n\
925  af = prevColour.a; \n\
926  ct = texel.rgb; \n\
927  at = texel.a; \n\
928  rv = vec4(vec4(ct*cf, at*af)*vec4(4.,4.,4.,4.)); \n\
929  }else if (mode== MTMODE_ADDSIGNED) { \n\
930  rv = vec4 (prevColour + texel - vec4 (0.5, 0.5, 0.5, -.5)); \n\
931  } else if (mode== MTMODE_ADDSIGNED2X) { \n\
932  rv = vec4 ((prevColour + texel - vec4 (0.5, 0.5, 0.5, -.5))*vec4(2.,2.,2.,2.)); \n\
933  } else if (mode== MTMODE_ADD) { \n\
934  rv= vec4 (prevColour + texel); \n\
935  } else if (mode== MTMODE_SUBTRACT) { \n\
936  rv = vec4 (texel - prevColour); //jas had prev - tex \n\
937  } else if (mode==MTMODE_ADDSMOOTH) { \n\
938  rv = vec4 (prevColour + (prevColour - vec4 (1.,1.,1.,1.)) * texel); \n\
939  } else if (mode==MTMODE_BLENDDIFFUSEALPHA) { \n\
940  rv = vec4 (mix(prevColour,texel,castle_Color.a)); \n\
941  } else if (mode==MTMODE_BLENDTEXTUREALPHA) { \n\
942  rv = vec4 (mix(prevColour,texel,texel.a)); \n\
943  } else if (mode==MTMODE_BLENDFACTORALPHA) { \n\
944  rv = vec4 (mix(prevColour,texel,mt_Color.a)); \n\
945  } else if (mode==MTMODE_BLENDCURRENTALPHA) { \n\
946  rv = vec4 (mix(prevColour,texel,prevColour.a)); \n\
947  } else if (mode==MTMODE_SELECTARG1) { \n\
948  rv = texel; \n\
949  } else if (mode==MTMODE_SELECTARG2) { \n\
950  rv = prevColour; \n\
951  } \n\
952  if(modea != 0){ \n\
953  if (modea==MTMODE_OFF) { \n\
954  rv.a = prevColour.a; \n\
955  } else if (modea==MTMODE_REPLACE) { \n\
956  rv.a = 1.0; \n\
957  }else if (modea==MTMODE_MODULATE) { \n\
958  float at,af; \n\
959  af = prevColour.a; \n\
960  at = texel.a; \n\
961  rv.a = at*af; \n\
962  } else if (modea==MTMODE_MODULATE2X) { \n\
963  float at,af; \n\
964  af = prevColour.a; \n\
965  at = texel.a; \n\
966  rv.a = at*af*2.0; \n\
967  }else if (modea==MTMODE_MODULATE4X) { \n\
968  float at,af; \n\
969  af = prevColour.a; \n\
970  at = texel.a; \n\
971  rv.a = at*af*4.0; \n\
972  }else if (modea== MTMODE_ADDSIGNED) { \n\
973  rv.a = (prevColour.a + texel.a + .5); \n\
974  } else if (modea== MTMODE_ADDSIGNED2X) { \n\
975  rv.a = ((prevColour.a + texel.a + .5))*2.0; \n\
976  } else if (modea== MTMODE_ADD) { \n\
977  rv.a = prevColour.a + texel.a; \n\
978  } else if (modea== MTMODE_SUBTRACT) { \n\
979  rv.a = texel.a - prevColour.a; //jas had prev - texel \n\
980  } else if (modea==MTMODE_ADDSMOOTH) { \n\
981  rv.a = (prevColour.a + (prevColour.a - 1.)) * texel.a; \n\
982  } else if (modea==MTMODE_BLENDDIFFUSEALPHA) { \n\
983  rv.a = mix(prevColour.a,texel.a,castle_Color.a); \n\
984  } else if (modea==MTMODE_BLENDTEXTUREALPHA) { \n\
985  rv.a = mix(prevColour.a,texel.a,texel.a); \n\
986  } else if (modea==MTMODE_BLENDFACTORALPHA) { \n\
987  rv.a = mix(prevColour.a,texel.a,mt_Color.a); \n\
988  } else if (modea==MTMODE_BLENDCURRENTALPHA) { \n\
989  rv.a = mix(prevColour.a,texel.a,prevColour.a); \n\
990  } else if (modea==MTMODE_SELECTARG1) { \n\
991  rv.a = texel.a; \n\
992  } else if (modea==MTMODE_SELECTARG2) { \n\
993  rv.a = prevColour.a; \n\
994  } \n\
995  } \n\
996  if(func == MTFN_COMPLEMENT){ \n\
997  //rv = vec4(1.0,1.0,1.0,1.0) - rv; \n\
998  rv = vec4( vec3(1.0,1.0,1.0) - rv.rgb, rv.a); \n\
999  }else if(func == MTFN_ALPHAREPLICATE){ \n\
1000  rv = vec4(rv.a,rv.a,rv.a,rv.a); \n\
1001  } \n\
1002  prevColour = rv; \n\
1003 } \n\
1004 #endif //MTEX \n\
1005 #endif //TEX \n\
1006 #ifdef FILL \n\
1007 uniform vec4 HatchColour; \n\
1008 uniform bool hatched; uniform bool filled;\n\
1009 uniform vec2 HatchScale; \n\
1010 uniform vec2 HatchPct; \n\
1011 uniform int algorithm; \n\
1012 varying vec2 hatchPosition; \n\
1013 void fillPropCalc(inout vec4 prevColour, vec2 MCposition, int algorithm) { \n\
1014  vec4 colour; \n\
1015  vec2 position, useBrick; \n\
1016  \n\
1017  position = MCposition / HatchScale; \n\
1018  \n\
1019  if (algorithm == 0) {/* bricking */ \n\
1020  if (fract(position.y * 0.5) > 0.5) \n\
1021  position.x += 0.5; \n\
1022  } \n\
1023  \n\
1024  /* algorithm 1, 2 = no futzing required here */ \n\
1025  if (algorithm == 3) { /* positive diagonals */ \n\
1026  vec2 curpos = position; \n\
1027  position.x -= curpos.y; \n\
1028  } \n\
1029  \n\
1030  if (algorithm == 4) { /* negative diagonals */ \n\
1031  vec2 curpos = position; \n\
1032  position.x += curpos.y; \n\
1033  } \n\
1034  \n\
1035  if (algorithm == 6) { /* diagonal crosshatch */ \n\
1036  vec2 curpos = position; \n\
1037  if (fract(position.y) > 0.5) { \n\
1038  if (fract(position.x) < 0.5) position.x += curpos.y; \n\
1039  else position.x -= curpos.y; \n\
1040  } else { \n\
1041  if (fract(position.x) > 0.5) position.x += curpos.y; \n\
1042  else position.x -= curpos.y; \n\
1043  } \n\
1044  } \n\
1045  \n\
1046  position = fract(position); \n\
1047  \n\
1048  useBrick = step(position, HatchPct); \n\
1049  \n\
1050  if (filled) {colour = prevColour;} else { colour=vec4(0.,0.,0.,0); }\n\
1051  if (hatched) { \n\
1052  colour = mix(HatchColour, colour, useBrick.x * useBrick.y); \n\
1053  } \n\
1054  prevColour = colour; \n\
1055 } \n\
1056 #endif //FILL \n\
1057 #ifdef FOG \n\
1058 struct fogParams \n\
1059 { \n\
1060  vec4 fogColor; \n\
1061  float visibilityRange; \n\
1062  float fogScale; \n\
1063  int fogType; // 0 None, 1= FOGTYPE_LINEAR, 2 = FOGTYPE_EXPONENTIAL \n\
1064  // ifdefed int haveFogCoords; \n\
1065 }; \n\
1066 uniform fogParams fw_fogparams; \n\
1067 #endif //FOG \n\
1068  \n\
1069 /* PLUG-DECLARATIONS */ \n\
1070  \n\
1071 #ifdef HAS_GEOMETRY_SHADER \n\
1072 #define castle_vertex_eye castle_vertex_eye_geoshader \n\
1073 #define castle_normal_eye castle_normal_eye_geoshader \n\
1074 #endif \n\
1075  \n\
1076 varying vec4 castle_vertex_eye; \n\
1077 varying vec3 castle_normal_eye; \n\
1078 #ifdef LIT \n\
1079 #ifdef LITE \n\
1080 //per-fragment lighting ie phong \n\
1081 struct fw_MaterialParameters { \n\
1082  vec4 emission; \n\
1083  vec4 ambient; \n\
1084  vec4 diffuse; \n\
1085  vec4 specular; \n\
1086  float shininess; \n\
1087 }; \n\
1088 uniform fw_MaterialParameters fw_FrontMaterial; \n\
1089 #ifdef TWO \n\
1090 uniform fw_MaterialParameters fw_BackMaterial; \n\
1091 #endif //TWO \n\
1092 vec3 castle_ColorES; \n\
1093 #else //LITE \n\
1094 //per-vertex lighting - interpolated Emissive-specular \n\
1095 varying vec3 castle_ColorES; //emissive shininess term \n\
1096 #endif //LITE \n\
1097 #endif //LIT\n\
1098  \n\
1099 /* Wrapper for calling PLUG texture_coord_shift */ \n\
1100 vec2 texture_coord_shifted(in vec2 tex_coord) \n\
1101 { \n\
1102  /* PLUG: texture_coord_shift (tex_coord) */ \n\
1103  return tex_coord; \n\
1104 } \n\
1105  \n\
1106 vec4 matdiff_color; \n\
1107 void main(void) \n\
1108 { \n\
1109  vec4 fragment_color = vec4(1.0,1.0,1.0,1.0); \n\
1110  matdiff_color = castle_Color; \n\
1111  float castle_MaterialDiffuseAlpha = castle_Color.a; \n\
1112  \n\
1113  #ifdef LITE \n\
1114  //per-fragment lighting aka PHONG \n\
1115  //start over with the color, since we have material and lighting in here \n\
1116  castle_MaterialDiffuseAlpha = fw_FrontMaterial.diffuse.a; \n\
1117  matdiff_color = vec4(0,0,0,1.0); \n\
1118  castle_ColorES = fw_FrontMaterial.emission.rgb; \n\
1119  /* PLUG: add_light_contribution2 (matdiff_color, castle_ColorES, castle_vertex_eye, castle_normal_eye, fw_FrontMaterial.shininess) */ \n\
1120  #endif //LITE \n\
1121  \n\
1122  #ifdef LIT \n\
1123  #ifdef MATFIR \n\
1124  fragment_color.rgb = matdiff_color.rgb; \n\
1125  #endif //MATFIR \n\
1126  #endif //LIT \n\
1127  #ifdef UNLIT \n\
1128  fragment_color = castle_Color; \n\
1129  #endif //UNLIT \n\
1130  \n\
1131  #ifdef CPV \n\
1132  #ifdef CPVREP \n\
1133  fragment_color = cpv_Color; //CPV replaces mat.diffuse prior \n\
1134  fragment_color.a *= castle_MaterialDiffuseAlpha; \n\
1135  #else \n\
1136  fragment_color *= cpv_Color; //CPV modulates prior \n\
1137  #endif //CPVREP \n\
1138  #endif //CPV \n\
1139  \n\
1140  #ifdef TEX \n\
1141  #ifdef TEXREP \n\
1142  fragment_color = vec4(1.0,1.0,1.0,1.0); //texture replaces prior \n\
1143  #endif //TEXREP \n\
1144  #endif //TEX \n\
1145  \n\
1146  /* Fragment shader on mobile doesn't get a normal vector now, for speed. */ \n\
1147  //#define normal_eye_fragment castle_normal_eye //vec3(0.0) \n\
1148  #define normal_eye_fragment vec3(0.0) \n\
1149  \n\
1150  #ifdef FILL \n\
1151  fillPropCalc(matdiff_color, hatchPosition, algorithm); \n\
1152  #endif //FILL \n\
1153  \n\
1154  #ifdef LIT \n\
1155  #ifndef MATFIR \n\
1156  //modulate texture with mat.diffuse \n\
1157  fragment_color.rgb *= matdiff_color.rgb; \n\
1158  fragment_color.a *= castle_MaterialDiffuseAlpha; \n\
1159  #endif //MATFIR \n\
1160  fragment_color.rgb = clamp(fragment_color.rgb + castle_ColorES, 0.0, 1.0); \n\
1161  #endif //LIT \n\
1162  \n\
1163  /* PLUG: texture_apply (fragment_color, normal_eye_fragment) */ \n\
1164  /* PLUG: steep_parallax_shadow_apply (fragment_color) */ \n\
1165  /* PLUG: fog_apply (fragment_color, normal_eye_fragment) */ \n\
1166  \n\
1167  #undef normal_eye_fragment \n\
1168  \n\
1169  gl_FragColor = fragment_color; \n\
1170  \n\
1171  /* PLUG: fragment_end (gl_FragColor) */ \n\
1172 } \n";
1173 
1174 
1175 
1176 const char *getGenericVertex(void){
1177  return genericVertexGLES2; //genericVertexDesktop
1178 }
1179 const char *getGenericFragment(){
1180  return genericFragmentGLES2; //genericFragmentDesktop;
1181 }
1182 #include "../scenegraph/Component_Shape.h"
1183 
1184 static const GLchar *plug_fragment_end_anaglyph = "\
1185 void PLUG_fragment_end (inout vec4 finalFrag){ \n\
1186  float gray = dot(finalFrag.rgb, vec3(0.299, 0.587, 0.114)); \n\
1187  finalFrag = vec4(gray,gray,gray, finalFrag.a); \n\
1188 }\n";
1189 
1190 //TEXTURE 3D
1191 /*
1192  4 scenarios:
1193  1. GL has texture3D/EXT_texture3D/OES_texture3D
1194  2. GL no texture3D - emulate
1195  A. 3D image: source imagery is i) 3D image or ii) composed image with image layers all same size
1196  B. 2D layers: source imagery is composed image with z < 7 layers and layers can be different sizes
1197  1 2
1198  A texture3D tiled texture2D
1199  B multi texure2D multi texture2D
1200 
1201  for tiled texture2D, there are a few ways to do the tiles:
1202  a) vertical strip: nx x (ny * nz) - our first attempt
1203  layer 0 at top, and sequential layers follow down
1204  b) squarish tiled: ix = iy = ceil(sqrt(nz)); (nx*ix) x (ny*iy)
1205  there will be blank squares. Order:
1206  y-first layer order: fill column, first at top left, before advancing ix right
1207  (option: x-first layer order: fill row, first at top left, before advancing down iy)
1208 */
1209 
1210 // TILED METHOD FOR TEXTURE3D
1211 // texture3D emulator via TILED texture2D
1212 // reason for emulating: 2016 GLES2 via ANGLEPROJECT(gles emulator over DirectX on windows)
1213 // doesn't have Texture3D or Texture3DOES or Texture3DEXT.
1214 // reason for TILES: an oblong Y-STRIP approach exceded max texture size in Y (but had lots left in X)
1215 // desktop computer max_size (of 2D image in one dimension) 16384
1216 // android phone max_size 4096
1217 // and so would be resampled (blurry) in y and good in x
1218 // using tiles means room for more full z slices ie 256x256x256 == 4096x4096 == 16M,
1219 // 512x512x512 == 134M == 16384x16384/2, and therefore less blurry images
1220 // tiles start in upper left with z=0, increase in y,
1221 // then when hit ny tiles in a y strip, move right one tile, and restart at top
1222 // uniform tex3dTiles[3] = {nx,ny,z}
1223 // example ny = 4, nx = 3, z = 11
1224 // 1 5 9
1225 // 2 6 10
1226 // 3 7 11
1227 // 4 8
1228 //
1229 static const GLchar *plug_fragment_texture3D_apply_volume = "\n\
1230 vec4 texture3Demu0( sampler2D sampler, in vec3 texcoord3, in int magfilter){ \n\
1231  vec4 sample = vec4(0.0); \n\
1232  #ifdef TEX3D \n\
1233  //TILED method (vs Y strip method) \n\
1234  vec3 texcoord = texcoord3; \n\
1235  //texcoord.z = 1.0 - texcoord.z; //flip z from RHS to LHS\n\
1236  float depth = max(1.0,float(tex3dTiles[2])); \n\
1237  if(repeatSTR[0] == 0) texcoord.x = clamp(texcoord.x,0.0001,.9999); \n\
1238  else texcoord.x = mod(texcoord.x,1.0); \n\
1239  if(repeatSTR[1] == 0) texcoord.y = clamp(texcoord.y,0.0001,.9999); \n\
1240  else texcoord.y = mod(texcoord.y,1.0); \n\
1241  if(repeatSTR[2] == 0) texcoord.z = clamp(texcoord.z,0.0001,.9999); \n\
1242  else texcoord.z = mod(texcoord.z,1.0); \n\
1243  vec4 texel; \n\
1244  int izf = int(floor(texcoord.z*depth)); //floor z \n\
1245  int izc = int(ceil(texcoord.z*depth)); //ceiling z \n\
1246  izc = izc == tex3dTiles[2] ? izc - 1 : izc; //clamp int z \n\
1247  vec4 ftexel, ctexel; \n\
1248  \n\
1249  int nx = tex3dTiles[0]; //0-11 \n\
1250  int ny = tex3dTiles[1]; \n\
1251  float fnx = 1.0/float(nx); //.1\n\
1252  float fny = 1.0/float(ny); \n\
1253  int ix = izc / ny; //60/11=5\n\
1254  int ixny = ix * ny; //5*11=55\n\
1255  int iy = izc - ixny; //60-55=5 modulus remainder \n\
1256  float cix = float(ix); //5 \n\
1257  float ciy = float(iy); \n\
1258  float xxc = (cix + texcoord.s)*fnx; //(5 + .5)*.1 = .55\n\
1259  float yyc = (ciy + texcoord.t)*fny; \n\
1260  ix = izf / ny; \n\
1261  ixny = ix * ny; \n\
1262  iy = izf - ixny; //modulus remainder \n\
1263  float fix = float(ix); \n\
1264  float fiy = float(iy); \n\
1265  float xxf = (fix + texcoord.s)*fnx; \n\
1266  float yyf = (fiy + texcoord.t)*fny; \n\
1267  \n\
1268  vec2 ftexcoord, ctexcoord; //texcoord is 3D, ftexcoord and ctexcoord are 2D coords\n\
1269  ftexcoord.s = xxf; \n\
1270  ftexcoord.t = yyf; \n\
1271  ctexcoord.s = xxc; \n\
1272  ctexcoord.t = yyc; \n\
1273  ftexel = texture2D(sampler,ftexcoord.st); \n\
1274  ctexel = texture2D(sampler,ctexcoord.st); \n\
1275  float fraction = mod(texcoord.z*depth,1.0); \n\
1276  if(magfilter == 1) \n\
1277  texel = mix(ctexel,ftexel,1.0-fraction); //lerp GL_LINEAR \n\
1278  else \n\
1279  texel = ftexel; //fraction > .5 ? ctexel : ftexel; //GL_NEAREST \n\
1280  sample = texel; \n\
1281  #endif //TEX3D \n\
1282  return sample; \n\
1283 } \n\
1284 vec4 texture3Demu( sampler2D sampler, in vec3 texcoord3){ \n\
1285  //use uniform magfilter \n\
1286  return texture3Demu0( sampler, texcoord3, magFilter); \n\
1287 } \n\
1288 void PLUG_texture3D( inout vec4 sample, in vec3 texcoord3 ){ \n\
1289  sample = texture3Demu(fw_Texture_unit0,texcoord3); \n\
1290 } \n\
1291 void PLUG_texture_apply (inout vec4 finalFrag, in vec3 normal_eye_fragment ){ \n\
1292 \n\
1293  vec4 sample; \n\
1294  sample = texture3Demu(fw_Texture_unit0,fw_TexCoord[0]); \n\
1295  finalFrag *= sample; \n\
1296  \n\
1297 }\n";
1298 
1299 
1300 
1301 static const GLchar *plug_fragment_texture3Dlayer_apply = "\
1302 void PLUG_texture_apply (inout vec4 finalFrag, in vec3 normal_eye_fragment ){ \n\
1303 \n\
1304  #ifdef TEX3DLAY \n\
1305  vec3 texcoord = fw_TexCoord[0]; \n\
1306  texcoord.z = 1.0 - texcoord.z; //flip z from RHS to LHS\n\
1307  float depth = max(1.0,float(textureCount-1)); \n\
1308  float delta = 1.0/depth; \n\
1309  if(repeatSTR[0] == 0) texcoord.x = clamp(texcoord.x,0.0001,.9999); \n\
1310  else texcoord.x = mod(texcoord.x,1.0); \n\
1311  if(repeatSTR[1] == 0) texcoord.y = clamp(texcoord.y,0.0001,.9999); \n\
1312  else texcoord.y = mod(texcoord.y,1.0); \n\
1313  if(repeatSTR[2] == 0) texcoord.z = clamp(texcoord.z,0.0001,.9999); \n\
1314  else texcoord.z = mod(texcoord.z,1.0); \n\
1315  int flay = int(floor(texcoord.z*depth)); \n\
1316  int clay = int(ceil(texcoord.z*depth)); \n\
1317  vec4 ftexel, ctexel; \n\
1318  //flay = 0; \n\
1319  //clay = 1; \n\
1320  if(flay == 0) ftexel = texture2D(fw_Texture_unit0,texcoord.st); \n\
1321  if(clay == 0) ctexel = texture2D(fw_Texture_unit0,texcoord.st); \n\
1322  if(flay == 1) ftexel = texture2D(fw_Texture_unit1,texcoord.st); \n\
1323  if(clay == 1) ctexel = texture2D(fw_Texture_unit1,texcoord.st); \n\
1324  if(flay == 2) ftexel = texture2D(fw_Texture_unit2,texcoord.st); \n\
1325  if(clay == 2) ctexel = texture2D(fw_Texture_unit2,texcoord.st); \n\
1326  if(flay == 3) ftexel = texture2D(fw_Texture_unit3,texcoord.st); \n\
1327  if(clay == 3) ctexel = texture2D(fw_Texture_unit3,texcoord.st); \n\
1328  float fraction = mod(texcoord.z*depth,1.0); \n\
1329  vec4 texel; \n\
1330  if(magFilter == 1) \n\
1331  texel = mix(ctexel,ftexel,(1.0-fraction)); //lerp GL_LINEAR \n\
1332  else \n\
1333  texel = fraction > .5 ? ctexel : ftexel; //GL_NEAREST \n\
1334  finalFrag *= texel; \n\
1335  #endif //TEX3DLAY \n\
1336  \n\
1337 }\n";
1338 
1339 //MULTITEXTURE
1340 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/texturing.html#MultiTexture
1341  /* PLUG: texture_apply (fragment_color, normal_eye_fragment) */
1342 static const GLchar *plug_fragment_texture_apply = "\
1343 void PLUG_texture_apply (inout vec4 finalFrag, in vec3 normal_eye_fragment ){ \n\
1344 \n\
1345  #ifdef MTEX \n\
1346  vec4 source; \n\
1347  int isource,iasource, mode; \n\
1348  //finalFrag = texture2D(fw_Texture_unit0, fw_TexCoord[0].st) * finalFrag; \n\
1349  if(textureCount>0){ \n\
1350  if(fw_Texture_mode0[0] != MTMODE_OFF) { \n\
1351  isource = fw_Texture_source0[0]; //castle-style dual sources \n\
1352  iasource = fw_Texture_source0[1]; \n\
1353  if(isource == MT_DEFAULT) source = finalFrag; \n\
1354  else if(isource == MTSRC_DIFFUSE) source = matdiff_color; \n\
1355  else if(isource == MTSRC_SPECULAR) source = vec4(castle_ColorES.rgb,1.0); \n\
1356  else if(isource == MTSRC_FACTOR) source = mt_Color; \n\
1357  if(iasource != 0){ \n\
1358  if(iasource == MT_DEFAULT) source.a = finalFrag.a; \n\
1359  else if(iasource == MTSRC_DIFFUSE) source.a = matdiff_color.a; \n\
1360  else if(iasource == MTSRC_SPECULAR) source.a = 1.0; \n\
1361  else if(iasource == MTSRC_FACTOR) source.a = mt_Color.a; \n\
1362  } \n\
1363  finalColCalc(source,fw_Texture_mode0[0],fw_Texture_mode0[1],fw_Texture_function0, fw_Texture_unit0,fw_TexCoord[0].st); \n\
1364  finalFrag = source; \n\
1365  } \n\
1366  } \n\
1367  if(textureCount>1){ \n\
1368  if(fw_Texture_mode1[0] != MTMODE_OFF) { \n\
1369  isource = fw_Texture_source1[0]; //castle-style dual sources \n\
1370  iasource = fw_Texture_source1[1]; \n\
1371  if(isource == MT_DEFAULT) source = finalFrag; \n\
1372  else if(isource == MTSRC_DIFFUSE) source = matdiff_color; \n\
1373  else if(isource == MTSRC_SPECULAR) source = vec4(castle_ColorES.rgb,1.0); \n\
1374  else if(isource == MTSRC_FACTOR) source = mt_Color; \n\
1375  if(iasource != 0){ \n\
1376  if(iasource == MT_DEFAULT) source.a = finalFrag.a; \n\
1377  else if(iasource == MTSRC_DIFFUSE) source.a = matdiff_color.a; \n\
1378  else if(iasource == MTSRC_SPECULAR) source.a = 1.0; \n\
1379  else if(iasource == MTSRC_FACTOR) source.a = mt_Color.a; \n\
1380  } \n\
1381  finalColCalc(source,fw_Texture_mode1[0],fw_Texture_mode1[1],fw_Texture_function1, fw_Texture_unit1,fw_TexCoord[1].st); \n\
1382  finalFrag = source; \n\
1383  } \n\
1384  } \n\
1385  if(textureCount>2){ \n\
1386  if(fw_Texture_mode2[0] != MTMODE_OFF) { \n\
1387  isource = fw_Texture_source2[0]; //castle-style dual sources \n\
1388  iasource = fw_Texture_source2[1]; \n\
1389  if(isource == MT_DEFAULT) source = finalFrag; \n\
1390  else if(isource == MTSRC_DIFFUSE) source = matdiff_color; \n\
1391  else if(isource == MTSRC_SPECULAR) source = vec4(castle_ColorES.rgb,1.0); \n\
1392  else if(isource == MTSRC_FACTOR) source = mt_Color; \n\
1393  if(iasource != 0){ \n\
1394  if(iasource == MT_DEFAULT) source.a = finalFrag.a; \n\
1395  else if(iasource == MTSRC_DIFFUSE) source.a = matdiff_color.a; \n\
1396  else if(iasource == MTSRC_SPECULAR) source.a = 1.0; \n\
1397  else if(iasource == MTSRC_FACTOR) source.a = mt_Color.a; \n\
1398  } \n\
1399  finalColCalc(source,fw_Texture_mode2[0],fw_Texture_mode2[1],fw_Texture_function2,fw_Texture_unit2,fw_TexCoord[2].st); \n\
1400  finalFrag = source; \n\
1401  } \n\
1402  } \n\
1403  if(textureCount>3){ \n\
1404  if(fw_Texture_mode3[0] != MTMODE_OFF) { \n\
1405  isource = fw_Texture_source3[0]; //castle-style dual sources \n\
1406  iasource = fw_Texture_source3[1]; \n\
1407  if(isource == MT_DEFAULT) source = finalFrag; \n\
1408  else if(isource == MTSRC_DIFFUSE) source = matdiff_color; \n\
1409  else if(isource == MTSRC_SPECULAR) source = vec4(castle_ColorES.rgb,1.0); \n\
1410  else if(isource == MTSRC_FACTOR) source = mt_Color; \n\
1411  if(iasource != 0){ \n\
1412  if(iasource == MT_DEFAULT) source.a = finalFrag.a; \n\
1413  else if(iasource == MTSRC_DIFFUSE) source.a = matdiff_color.a; \n\
1414  else if(iasource == MTSRC_SPECULAR) source.a = 1.0; \n\
1415  else if(iasource == MTSRC_FACTOR) source.a = mt_Color.a; \n\
1416  } \n\
1417  finalColCalc(source,fw_Texture_mode3[0],fw_Texture_mode3[1],fw_Texture_function3,fw_Texture_unit3,fw_TexCoord[3].st); \n\
1418  finalFrag = source; \n\
1419  } \n\
1420  } \n\
1421  #else //MTEX \n\
1422  /* ONE TEXTURE */ \n\
1423  #ifdef CUB \n\
1424  finalFrag = textureCube(fw_Texture_unit0, fw_TexCoord[0]) * finalFrag; \n\
1425  #else //CUB \n\
1426  finalFrag = texture2D(fw_Texture_unit0, fw_TexCoord[0].st) * finalFrag; \n\
1427  #endif //CUB \n\
1428  #endif //MTEX \n\
1429  \n\
1430 }\n";
1431 
1432 
1433 //add_light_contribution (castle_Color, castle_vertex_eye, castle_normal_eye, castle_MaterialShininess)
1434 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/lighting.html#Lightingequations
1435 // simplified thoery: lightOut = emissive + f(light_in,material,light_eqn)
1436 // ADS: Ambient + Diffuse + Specular
1437 // http://www.matrix44.net/cms/notes/opengl-3d-graphics/the-ads-lighting-model
1438 // http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter05.html
1439 // incoming eyeposition and eyenormal are of the surface vertex and normal
1440 // .. in the view/eye coordinate system (so eye is at 0,0,0 and eye direction is 0,0,-1
1441 
1442 #ifdef OLDCODE
1443 static const GLchar *plug_vertex_lighting_matemissive = "\n\
1444 void PLUG_add_light_contribution (inout vec4 vertexcolor, in vec4 myPosition, in vec3 myNormal, in float shininess ) {\n\
1445  vertexcolor.rgb += fw_FrontMaterial.emissive.rgb; \n\
1446 ";
1447 #endif //OLDCODE
1448 
1449 static const GLchar *plug_vertex_lighting_ADSLightModel = "\n\
1450 /* use ADSLightModel here the ADS colour is returned from the function. */ \n\
1451 void PLUG_add_light_contribution2 (inout vec4 vertexcolor, inout vec3 specularcolor, in vec4 myPosition, in vec3 myNormal, in float shininess ) { \n\
1452  //working in eye space: eye is at 0,0,0 looking generally in direction 0,0,-1 \n\
1453  //myPosition, myNormal - of surface vertex, in eyespace \n\
1454  //vertexcolor - diffuse+ambient -will be replaced or modulated by texture color \n\
1455  //specularcolor - specular+emissive or non-diffuse (emissive added outside this function) \n\
1456  //algo: uses Blinn-Phong specular reflection: half-vector pow(N*H,shininess) \n\
1457  int i; \n\
1458  vec4 diffuse = vec4(0., 0., 0., 0.); \n\
1459  vec4 ambient = vec4(0., 0., 0., 0.); \n\
1460  vec4 specular = vec4(0., 0., 0., 1.); \n\
1461  vec3 N = normalize (myNormal); \n\
1462  \n\
1463  vec3 E = -normalize(myPosition.xyz); \n \
1464  vec4 matdiffuse = vec4(1.0,1.0,1.0,1.0); \n\
1465  float myAlph = 0.0;\n\
1466  \n\
1467  fw_MaterialParameters myMat = fw_FrontMaterial; \n\
1468  \n\
1469  /* back Facing materials - flip the normal and grab back materials */ \n\
1470  bool backFacing = (dot(N,E) < 0.0); \n\
1471  if (backFacing) { \n\
1472  N = -N; \n\
1473  #ifdef TWO \n\
1474  myMat = fw_BackMaterial; \n\
1475  #endif //TWO \n\
1476  } \n\
1477  \n\
1478  myAlph = myMat.diffuse.a; \n\
1479  //if(useMatDiffuse) \n\
1480  matdiffuse = myMat.diffuse; \n\
1481  \n\
1482  /* apply the lights to this material */ \n\
1483  /* weird but ANGLE needs constant loop */ \n\
1484  for (i=0; i<MAX_LIGHTS; i++) {\n\
1485  if(i < lightcount) { \n\
1486  vec4 myLightDiffuse = fw_LightSource[i].diffuse; \n\
1487  vec4 myLightAmbient = fw_LightSource[i].ambient; \n\
1488  vec4 myLightSpecular = fw_LightSource[i].specular; \n\
1489  vec4 myLightPosition = fw_LightSource[i].position; \n\
1490  int myLightType = lightType[i]; \n\
1491  vec3 myLightDir = fw_LightSource[i].spotDirection.xyz; \n\
1492  vec3 VP; /* vector of light direction and distance */ \n\
1493  VP = myLightPosition.xyz - myPosition.xyz; \n\
1494  vec3 L = myLightDir; /*directional light*/ \n\
1495  if(myLightType < 2) /*point and spot*/ \n\
1496  L = normalize(VP); \n\
1497  float NdotL = max(dot(N, L), 0.0); //Lambertian diffuse term \n\
1498  /*specular reflection models, phong or blinn-phong*/ \n\
1499  //#define PHONG 1 \n\
1500  #ifdef PHONG \n\
1501  //Phong \n\
1502  vec3 R = normalize(-reflect(L,N)); \n\
1503  float RdotE = max(dot(R,E),0.0); \n\
1504  float specbase = RdotE; \n\
1505  float specpow = .3 * myMat.shininess; //assume shini tuned to blinn, adjust for phong \n\
1506  #else //PHONG \n\
1507  //Blinn-Phong \n\
1508  vec3 H = normalize(L + E); //halfvector\n\
1509  float NdotH = max(dot(N,H),0.0); \n\
1510  float specbase = NdotH; \n\
1511  float specpow = myMat.shininess; \n\
1512  #endif //PHONG \n\
1513  float powerFactor = 0.0; /* for light dropoff */ \n\
1514  if (specbase > 0.0) { \n\
1515  powerFactor = pow(specbase,specpow); \n\
1516  /* tone down the power factor if myMat.shininess borders 0 */ \n\
1517  if (myMat.shininess < 1.0) { \n\
1518  powerFactor *= myMat.shininess; \n\
1519  } \n\
1520  } \n\
1521  \n\
1522  if (myLightType==1) { \n\
1523  /* SpotLight */ \n\
1524  float spotDot, multiplier; \n\
1525  float spotAttenuation = 0.0; \n\
1526  float attenuation; /* computed attenuation factor */ \n\
1527  float D; /* distance to vertex */ \n\
1528  D = length(VP); \n\
1529  attenuation = 1.0/(fw_LightSource[i].Attenuations.x + (fw_LightSource[i].Attenuations.y * D) + (fw_LightSource[i].Attenuations.z *D*D)); \n\
1530  multiplier = 0.0; \n\
1531  spotDot = dot (-L,myLightDir); \n\
1532  /* check against spotCosCutoff */ \n\
1533  if (spotDot > fw_LightSource[i].spotCutoff) { \n\
1534  //?? what was this: spotAttenuation = pow(spotDot,fw_LightSource[i].spotExponent); \n\
1535  if(spotDot > fw_LightSource[i].spotBeamWidth) { \n\
1536  multiplier = 1.0; \n\
1537  } else { \n\
1538  multiplier = (spotDot - fw_LightSource[i].spotCutoff)/(fw_LightSource[i].spotBeamWidth - fw_LightSource[i].spotCutoff); \n\
1539  } \n\
1540  } \n\
1541  //attenuation *= spotAttenuation; \n\
1542  attenuation *= multiplier; \n\
1543  /* diffuse light computation */ \n\
1544  diffuse += NdotL* matdiffuse*myLightDiffuse * attenuation; \n\
1545  /* ambient light computation */ \n\
1546  ambient += myMat.ambient*myLightAmbient; \n\
1547  /* specular light computation */ \n\
1548  specular += myLightSpecular * powerFactor * attenuation; \n\
1549  \n\
1550  } else if (myLightType == 2) { \n\
1551  /* DirectionalLight */ \n\
1552  /* Specular light computation */ \n\
1553  specular += myMat.specular *myLightSpecular*powerFactor; \n\
1554  /* diffuse light computation */ \n\
1555  diffuse += NdotL*matdiffuse*myLightDiffuse; \n\
1556  /* ambient light computation */ \n\
1557  ambient += myMat.ambient*myLightAmbient; \n\
1558  } else { \n\
1559  /* PointLight */ \n\
1560  float attenuation = 0.0; /* computed attenuation factor */ \n\
1561  float D = length(VP); /* distance to vertex */ \n\
1562  /* are we within range? */ \n\
1563  if (D <= fw_LightSource[i].lightRadius) { \n\
1564  /* this is actually the SFVec3f attenuation field */ \n\
1565  attenuation = 1.0/(fw_LightSource[i].Attenuations.x + (fw_LightSource[i].Attenuations.y * D) + (fw_LightSource[i].Attenuations.z *D*D)); \n\
1566  /* diffuse light computation */ \n\
1567  diffuse += NdotL* matdiffuse*myLightDiffuse * attenuation; \n\
1568  /* ambient light computation */ \n\
1569  ambient += myMat.ambient*myLightAmbient; \n\
1570  /* specular light computation */ \n\
1571  attenuation *= (myMat.shininess/128.0); \n\
1572  specular += myLightSpecular * powerFactor * attenuation; \n\
1573  } \n\
1574  } \n\
1575  } \n\
1576  } \n\
1577  vertexcolor = clamp(vec4(vec3(ambient + diffuse ) + vertexcolor.rgb ,myAlph), 0.0, 1.0); \n\
1578  specularcolor = clamp(specular.rgb + specularcolor, 0.0, 1.0); \n\
1579 } \n\
1580 ";
1581 
1582 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/lighting.html#t-foginterpolant
1583 // PLUG: fog_apply (fragment_color, normal_eye_fragment)
1584 static const GLchar *plug_fog_apply = "\
1585 void PLUG_fog_apply (inout vec4 finalFrag, in vec3 normal_eye_fragment ){ \n\
1586  float ff = 1.0; \n\
1587  float depth = abs(castle_vertex_eye.z/castle_vertex_eye.w); \n\
1588  if(fw_fogparams.fogType > 0){ \n\
1589  ff = 0.0; \n\
1590  if(fw_fogparams.fogType == 1){ //FOGTYPE_LINEAR \n\
1591  if(depth < fw_fogparams.visibilityRange) \n\
1592  ff = (fw_fogparams.visibilityRange-depth)/fw_fogparams.visibilityRange; \n\
1593  } else { //FOGTYPE_EXPONENTIAL \n\
1594  if(depth < fw_fogparams.visibilityRange){ \n\
1595  ff = exp(-depth/(fw_fogparams.visibilityRange -depth) ); \n\
1596  ff = clamp(ff, 0.0, 1.0); \n\
1597  } \n\
1598  } \n\
1599  finalFrag = mix(finalFrag,fw_fogparams.fogColor,1.0 - ff); \n\
1600  } \n\
1601 } \n\
1602 ";
1603 
1604 static const GLchar *vertex_plug_clip_apply = "\
1605 #ifdef CLIP \n\
1606 #define FW_MAXCLIPPLANES 4 \n\
1607 uniform int fw_nclipplanes; \n\
1608 uniform vec4 fw_clipplanes[FW_MAXCLIPPLANES]; \n\
1609 varying float fw_ClipDistance[FW_MAXCLIPPLANES]; \n\
1610  \n\
1611 void PLUG_vertex_object_space (in vec4 vertex_object, in vec3 normal_object){ \n\
1612  for ( int i=0; i<fw_nclipplanes; i++ ) \n\
1613  fw_ClipDistance[i] = dot( fw_clipplanes[i], vertex_object); \n\
1614 } \n\
1615 #endif //CLIP \n\
1616 ";
1617 
1618 static const GLchar *frag_plug_clip_apply = "\
1619 #ifdef CLIP \n\
1620 #define FW_MAXCLIPPLANES 4 \n\
1621 uniform int fw_nclipplanes; \n\
1622 varying float fw_ClipDistance[FW_MAXCLIPPLANES]; \n\
1623 void PLUG_fog_apply (inout vec4 finalFrag, in vec3 normal_eye_fragment ){ \n\
1624  for(int i=0;i<fw_nclipplanes;i++) { \n\
1625  //if(normal_eye_fragment.z > fw_ClipDistance[i]) discard; \n\
1626  if(fw_ClipDistance[i] < 0.0) discard; \n\
1627  } \n\
1628 } \n\
1629 #endif //CLIP \n\
1630 ";
1631 
1632 #if defined(GL_ES_VERSION_2_0)
1633 static int isMobile = TRUE;
1634 #else
1635 static int isMobile = FALSE;
1636 #endif
1637 
1638 #define DESIRE(whichOne,zzz) ((whichOne & zzz)==zzz)
1639 int getSpecificShaderSourceCastlePlugs (const GLchar **vertexSource, const GLchar **fragmentSource, shaderflagsstruct whichOne)
1640 {
1641  //for building the Builtin (similar to fixed-function pipeline, except from shader parts)
1642  //in OpenGL_Utils.c L.2553 set usingCastlePlugs = 1 to get in here.
1643  //whichone - a bitmask of shader requirements, one bit for each requirement, so shader permutation can be built
1644 
1645  int retval, unique_int;
1646  char *CompleteCode[3];
1647  char *vs, *fs;
1648  retval = FALSE;
1649  if(whichOne.usershaders ) //& USER_DEFINED_SHADER_MASK)
1650  return retval; //not supported yet as of Aug 9, 2016
1651  retval = TRUE;
1652 
1653  //generic
1654  vs = strdup(getGenericVertex());
1655  fs = strdup(getGenericFragment());
1656 
1657  CompleteCode[SHADERPART_VERTEX] = vs;
1658  CompleteCode[SHADERPART_GEOMETRY] = NULL;
1659  CompleteCode[SHADERPART_FRAGMENT] = fs;
1660 
1661  // what we really have here: UberShader with CastlePlugs
1662  // UberShader: one giant shader peppered with #ifdefs, and you add #defines at the top for permutations
1663  // CastlePlugs: allows users to add effects on to uberShader with PLUGs
1664  // - and internally, we can do a few permutations with PLUGs too
1665 
1666  if(isMobile){
1667  AddVersion(SHADERPART_VERTEX, 100, CompleteCode); //lower precision floats
1668  AddVersion(SHADERPART_FRAGMENT, 100, CompleteCode); //lower precision floats
1669  AddDefine(SHADERPART_FRAGMENT,"MOBILE",CompleteCode); //lower precision floats
1670  }else{
1671  //desktop, emulating GLES2
1672  AddVersion(SHADERPART_VERTEX, 110, CompleteCode); //lower precision floats
1673  AddVersion(SHADERPART_FRAGMENT, 110, CompleteCode); //lower precision floats
1674  }
1675 
1676  unique_int = 0; //helps generate method name PLUG_xxx_<unique_int> to avoid clash when multiple PLUGs supplied for same PLUG point
1677  //Add in:
1678  //Lit
1679  //Fog
1680  //analglyph
1681  if(DESIRE(whichOne.base,WANT_ANAGLYPH))
1682  Plug(SHADERPART_FRAGMENT,plug_fragment_end_anaglyph,CompleteCode,&unique_int); //works, converts frag to gray
1683  //color per vertex
1684  if DESIRE(whichOne.base,COLOUR_MATERIAL_SHADER) {
1685  AddDefine(SHADERPART_VERTEX,"CPV",CompleteCode);
1686  AddDefine(SHADERPART_FRAGMENT,"CPV",CompleteCode);
1687  if(DESIRE(whichOne.base,CPV_REPLACE_PRIOR)){
1688  AddDefine(SHADERPART_VERTEX,"CPVREP",CompleteCode);
1689  AddDefine(SHADERPART_FRAGMENT,"CPVREP",CompleteCode);
1690  }
1691  }
1692  //material appearance
1693  //2 material appearance
1694  //phong vs gourard
1695  if(DESIRE(whichOne.base,MATERIAL_APPEARANCE_SHADER) || DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER)){
1696  //if(isLit)
1697  if(DESIRE(whichOne.base,MAT_FIRST)){
1698  //strict table 17-3 with no other modulation means Texture > CPV > mat.diffuse > (111)
1699  AddDefine(SHADERPART_VERTEX,"MATFIR",CompleteCode);
1700  AddDefine(SHADERPART_FRAGMENT,"MATFIR",CompleteCode);
1701  }
1702  if(DESIRE(whichOne.base,SHADINGSTYLE_PHONG) && !DESIRE(whichOne.base,HAVE_LINEPOINTS_COLOR)){
1703  //when we say phong in freewrl, we really mean per-fragment lighting
1704  AddDefine(SHADERPART_FRAGMENT,"LIT",CompleteCode);
1705  AddDefine(SHADERPART_FRAGMENT,"LITE",CompleteCode); //add some lights
1706  Plug(SHADERPART_FRAGMENT,plug_vertex_lighting_ADSLightModel,CompleteCode,&unique_int); //use lights
1707 
1708  if(DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER))
1709  AddDefine(SHADERPART_FRAGMENT,"TWO",CompleteCode);
1710  //but even if we mean per-fragment, for another dot product per fragment we can upgrade
1711  //from blinn-phong to phong and get the real phong reflection model
1712  //(although dug9 can't tell the difference):
1713  AddDefine(SHADERPART_FRAGMENT,"PHONG",CompleteCode);
1714  }else{
1715  AddDefine(SHADERPART_VERTEX,"LIT",CompleteCode);
1716  AddDefine(SHADERPART_FRAGMENT,"LIT",CompleteCode);
1717  //lines and points
1718  if( DESIRE(whichOne.base,HAVE_LINEPOINTS_COLOR) ) {
1719  AddDefine(SHADERPART_VERTEX,"LINE",CompleteCode);
1720  }else{
1721  AddDefine(SHADERPART_VERTEX,"LITE",CompleteCode); //add some lights
1722  Plug(SHADERPART_VERTEX,plug_vertex_lighting_ADSLightModel,CompleteCode,&unique_int); //use lights
1723  if(DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER))
1724  AddDefine(SHADERPART_VERTEX,"TWO",CompleteCode);
1725  }
1726  }
1727  }
1728  //textureCoordinategen
1729  //cubemap texure
1730  //one tex appearance
1731  //multi tex appearance
1732  //cubemap tex
1733  /* http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/lighting.html#Lightingon
1734  "The Material's transparency field modulates the alpha in the texture. Hence,
1735  a transparency of 0 will result in an alpha equal to that of the texture.
1736  A transparency of 1 will result in an alpha of 0 regardless of the value in the texture."
1737  That doesn't seem to me to be what browsers Octaga, InstantReality, or Cortona are doing,
1738  and its not what table 17-3 and the Lighting equation say is happening.
1739  In the table, alpha is never 'modulated' ie there's never an alpha= AT * (1-TM) term.
1740  - freewrl version 3 and vivaty do modulate.
1741  I've put a define to set if you don't want modulation ie table 17-3.
1742  If you do want to modulate ie the above quote "to modulate", comment out the define
1743  I put a mantis issue to web3d.org for clarification Aug 16, 2016
1744  */
1745 
1746  if(DESIRE(whichOne.base,HAVE_UNLIT_COLOR)){
1747  AddDefine(SHADERPART_VERTEX,"UNLIT",CompleteCode);
1748  AddDefine(SHADERPART_FRAGMENT,"UNLIT",CompleteCode);
1749  }
1750  if (DESIRE(whichOne.base,ONE_TEX_APPEARANCE_SHADER) ||
1751  DESIRE(whichOne.base,HAVE_TEXTURECOORDINATEGENERATOR) ||
1752  DESIRE(whichOne.base,HAVE_CUBEMAP_TEXTURE) ||
1753  DESIRE(whichOne.base,MULTI_TEX_APPEARANCE_SHADER)) {
1754  AddDefine(SHADERPART_VERTEX,"TEX",CompleteCode);
1755  AddDefine(SHADERPART_FRAGMENT,"TEX",CompleteCode);
1756  if(DESIRE(whichOne.base,HAVE_TEXTURECOORDINATEGENERATOR) )
1757  AddDefine(SHADERPART_VERTEX,"TGEN",CompleteCode);
1758  if(DESIRE(whichOne.base,TEX3D_SHADER)){
1759  //in theory, if the texcoordgen "COORD" and TextureTransform3D are set in scenefile
1760  // and working properly in freewrl, then don't need TEX3D for that node in VERTEX shader
1761  // which is using tex3dbbox (shape->_extent reworked) to get vertex coords in 0-1 range
1762  // x Sept 4, 2016 either TextureTransform3D or CoordinateGenerator "COORD" isn't working right for Texture3D
1763  // so we're using the bbox method
1764  //vertex str texture coords computed same for both volume and layered tex3d
1765  AddDefine(SHADERPART_VERTEX,"TEX3D",CompleteCode);
1766  AddDefine(SHADERPART_FRAGMENT,"TEX3D",CompleteCode);
1767  //fragment part different:
1768  if(DESIRE(whichOne.base,TEX3D_LAYER_SHADER)){
1769  //up to 6 textures, with lerp between floor,ceil textures
1770  AddDefine(SHADERPART_FRAGMENT,"TEX3DLAY",CompleteCode);
1771  Plug(SHADERPART_FRAGMENT,plug_fragment_texture3Dlayer_apply,CompleteCode,&unique_int);
1772  }else{
1773  //TEX3D_VOLUME_SHADER
1774  //AddDefine(SHADERPART_FRAGMENT,"TEX3D",CompleteCode);
1775  Plug(SHADERPART_FRAGMENT,plug_fragment_texture3D_apply_volume,CompleteCode,&unique_int);
1776  }
1777  }else{
1778  if(DESIRE(whichOne.base,HAVE_CUBEMAP_TEXTURE)){
1779  AddDefine(SHADERPART_VERTEX,"CUB",CompleteCode);
1780  AddDefine(SHADERPART_FRAGMENT,"CUB",CompleteCode);
1781  } else if(DESIRE(whichOne.base,MULTI_TEX_APPEARANCE_SHADER)){
1782  AddDefine(SHADERPART_VERTEX,"MTEX",CompleteCode);
1783  AddDefine(SHADERPART_FRAGMENT,"MTEX",CompleteCode);
1784  }
1785  if(DESIRE(whichOne.base,TEXTURE_REPLACE_PRIOR) )
1786  AddDefine(SHADERPART_FRAGMENT,"TEXREP",CompleteCode);
1787  if(DESIRE(whichOne.base,TEXALPHA_REPLACE_PRIOR))
1788  AddDefine(SHADERPART_VERTEX,"TAREP",CompleteCode);
1789 
1790  Plug(SHADERPART_FRAGMENT,plug_fragment_texture_apply,CompleteCode,&unique_int);
1791 
1792  //if(texture has alpha ie channels == 2 or 4) then vertex diffuse = 111 and fragment diffuse*=texture
1793  //H: we currently assume image alpha, and maybe fill the alpha channel with (1-material.transparency)?
1794  //AddDefine(SHADERPART_VERTEX,"TAT",CompleteCode);
1795  //AddDefine(SHADERPART_FRAGMENT,"TAT",CompleteCode);
1796  }
1797  }
1798 
1799  //fill properties / hatching
1800  if(DESIRE(whichOne.base,FILL_PROPERTIES_SHADER)) {
1801  AddDefine(SHADERPART_VERTEX,"FILL",CompleteCode);
1802  AddDefine(SHADERPART_FRAGMENT,"FILL",CompleteCode);
1803  }
1804  //FOG
1805  if(DESIRE(whichOne.base,FOG_APPEARANCE_SHADER)){
1806  AddDefine(SHADERPART_VERTEX,"FOG",CompleteCode);
1807  AddDefine(SHADERPART_FRAGMENT,"FOG",CompleteCode);
1808  if(DESIRE(whichOne.base,HAVE_FOG_COORDS))
1809  AddDefine(SHADERPART_VERTEX,"FOGCOORD",CompleteCode);
1810  Plug(SHADERPART_FRAGMENT,plug_fog_apply,CompleteCode,&unique_int);
1811  }
1812  //CLIPPLANE
1813  //FOG
1814  if(DESIRE(whichOne.base,CLIPPLANE_SHADER)){
1815  AddDefine(SHADERPART_VERTEX,"CLIP",CompleteCode);
1816  Plug(SHADERPART_VERTEX,vertex_plug_clip_apply,CompleteCode,&unique_int);
1817  AddDefine(SHADERPART_FRAGMENT,"CLIP",CompleteCode);
1818  Plug(SHADERPART_FRAGMENT,frag_plug_clip_apply,CompleteCode,&unique_int);
1819  }
1820  if(DESIRE(whichOne.base,PARTICLE_SHADER)){
1821  AddDefine(SHADERPART_VERTEX,"PARTICLE",CompleteCode);
1822  }
1823  //EFFECTS - castle game engine effect nodes X3D_Effect with plugs applied here
1824  EnableEffects(CompleteCode,&unique_int);
1825 
1826  // stripUnusedDefines(CompleteCode);
1827  // http://freecode.com/projects/unifdef/ example: unifdef -UTEX -UGMTEX shader.vs > out.vs will strip the TEX and MTEX sections out
1828 
1829 
1830  *fragmentSource = CompleteCode[SHADERPART_FRAGMENT]; //original_fragment; //fs;
1831  *vertexSource = CompleteCode[SHADERPART_VERTEX]; //original_vertex; //vs;
1832  return retval;
1833 }
1834 
1835 // START MIT, VOLUME RENDERING >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1836 
1837 /* Generic GLSL vertex shader, used on OpenGL ES. */
1838 static const GLchar *volumeVertexGLES2 = " \n\
1839 uniform mat4 fw_ModelViewMatrix; \n\
1840 uniform mat4 fw_ProjectionMatrix; \n\
1841 attribute vec4 fw_Vertex; \n\
1842  \n\
1843 /* PLUG-DECLARATIONS */ \n\
1844  \n\
1845 varying vec4 castle_vertex_eye; \n\
1846 varying vec4 castle_Color; \n\
1847  \n\
1848 void main(void) \n\
1849 { \n\
1850  vec4 vertex_object = fw_Vertex; \n\
1851  vec3 normal_object = vec3(0.0); \n\
1852  /* PLUG: vertex_object_space (vertex_object, normal_object) */ \n\
1853  castle_vertex_eye = fw_ModelViewMatrix * vertex_object; \n\
1854  \n\
1855  castle_Color = vec4(1.0,.5,.5,1.0); \n\
1856  \n\
1857  gl_Position = fw_ProjectionMatrix * castle_vertex_eye; \n\
1858  \n\
1859 } \n\
1860 ";
1861 
1862 
1863 
1864 
1865 
1866 
1867 
1868 /* Generic GLSL fragment shader, used on OpenGL ES. */
1869 static const GLchar *volumeFragmentGLES2 = " \n\
1870 /* DEFINES */ \n\
1871 #ifdef MOBILE \n\
1872 //precision highp float; \n\
1873 precision mediump float; \n\
1874 #endif //MOBILE \n\
1875  \n\
1876  vec4 HeatMapColor(float value, float minValue, float maxValue) \n\
1877 { \n\
1878  //used for debugging. If min=0,max=1 then magenta is 0, blue,green,yellow, red is 1 \n\
1879  vec4 ret; \n\
1880  int HEATMAP_COLORS_COUNT; \n\
1881  vec4 colors[6]; \n\
1882  HEATMAP_COLORS_COUNT = 6; \n\
1883  colors[0] = vec4(0.32, 0.00, 0.32, 1.0); \n\
1884  colors[1] = vec4( 0.00, 0.00, 1.00, 1.00); \n\
1885  colors[2] = vec4(0.00, 1.00, 0.00, 1.00); \n\
1886  colors[3] = vec4(1.00, 1.00, 0.00, 1.00); \n\
1887  colors[4] = vec4(1.00, 0.60, 0.00, 1.00); \n\
1888  colors[5] = vec4(1.00, 0.00, 0.00, 1.00); \n\
1889  float ratio=(float(HEATMAP_COLORS_COUNT)-1.0)*clamp((value-minValue)/(maxValue-minValue),0.0,1.0); \n\
1890  int indexMin=int(floor(ratio)); \n\
1891  int indexMax= indexMin+1 < HEATMAP_COLORS_COUNT-1 ? indexMin+1 : HEATMAP_COLORS_COUNT-1; \n\
1892  ret = mix(colors[indexMin], colors[indexMax], ratio-float(indexMin)); \n\
1893  if(value < minValue) ret = vec4(0.0,0.0,0.0,1.0); \n\
1894  if(value > maxValue) ret = vec4(1.0,1.0,1.0,1.0); \n\
1895  return ret; \n\
1896 } \n\
1897 vec4 debug_color; \n\
1898 float hash( float n ) \n\
1899 { \n\
1900  return fract(sin(n)*43758.5453); \n\
1901 } \n\
1902 float noise( vec3 xyz ) \n\
1903 { \n\
1904  // The noise function returns a value in the range -1.0f -> 1.0f \n\
1905  vec3 p = floor(xyz); \n\
1906  vec3 f = fract(xyz); \n\
1907  \n\
1908  f = f*f*(3.0-2.0*f); \n\
1909  float n = p.x + p.y*57.0 + 113.0*p.z; \n\
1910  \n\
1911  return mix(mix(mix( hash(n+0.0), hash(n+1.0),f.x), \n\
1912  mix( hash(n+57.0), hash(n+58.0),f.x),f.y), \n\
1913  mix(mix( hash(n+113.0), hash(n+114.0),f.x), \n\
1914  mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z); \n\
1915 } \n\
1916 vec3 noise3( in vec3 xyz, in float range ){ \n\
1917  vec3 rxyz = vec3(xyz); \n\
1918  rxyz.x += noise(xyz)*range; \n\
1919  rxyz.y += noise(xyz)*range; \n\
1920  rxyz.z += noise(xyz)*range; \n\
1921  return rxyz; \n\
1922 } \n\
1923  \n\
1924 varying vec4 castle_vertex_eye; \n\
1925 varying vec4 castle_Color; \n\
1926 uniform mat4 fw_ModelViewProjInverse; \n\
1927 //uniform float fw_FocalLength; \n\
1928 uniform vec4 fw_viewport; \n\
1929 uniform vec3 fw_dimensions; \n\
1930 //uniform vec3 fw_RayOrigin; \n\
1931 uniform sampler2D fw_Texture_unit0; \n\
1932 uniform sampler2D fw_Texture_unit1; \n\
1933 uniform sampler2D fw_Texture_unit2; \n\
1934 uniform sampler2D fw_Texture_unit3; \n\
1935 #ifdef TEX3D \n\
1936 uniform int tex3dTiles[3]; \n\
1937 uniform int repeatSTR[3]; \n\
1938 uniform int magFilter; \n\
1939 #endif //TEX3D \n\
1940 #ifdef SEGMENT \n\
1941 uniform int fw_nIDs; \n\
1942 uniform int fw_enableIDs[10]; \n\
1943 uniform int fw_surfaceStyles[2]; \n\
1944 uniform int fw_nStyles; \n\
1945 vec4 texture3Demu( sampler2D sampler, in vec3 texcoord3); \n\
1946 vec4 texture3Demu0( sampler2D sampler, in vec3 texcoord3, int magfilter); \n\
1947 bool inEnabledSegment(in vec3 texcoords, inout int jstyle){ \n\
1948  bool inside = true; \n\
1949  jstyle = 1; //DEFAULT \n\
1950  vec4 segel = texture3Demu0(fw_Texture_unit1,texcoords,0); \n\
1951  //convert from GL_FLOAT 0-1 to int 0-255 \n\
1952  //Q. is there a way to do int images in GLES2? \n\
1953  int ID = int(floor(segel.a * 255.0 + .1)); \n\
1954  //debug_color = HeatMapColor(float(ID),0.0,5.0); \n\
1955  //debug_color.a = .2; \n\
1956  if(ID < fw_nIDs){ \n\
1957  //specs: The indices of this array corresponds to the segment identifier. \n\
1958  inside = fw_enableIDs[ID] == 0 ? false : true; \n\
1959  } \n\
1960  if(inside){ \n\
1961  int kstyle = fw_nStyles-1; \n\
1962  kstyle = ID < fw_nStyles ? ID : kstyle; \n\
1963  jstyle = fw_surfaceStyles[kstyle]; \n\
1964  jstyle = jstyle == 1 ? 0 : jstyle; \n\
1965  } \n\
1966  return inside; \n\
1967 } \n\
1968 #endif //SEGMENT \n\
1969 #ifdef ISO \n\
1970 uniform float fw_stepSize; \n\
1971 uniform float fw_tolerance; \n\
1972 uniform float fw_surfaceVals[]; \n\
1973 uniform int fw_nVals; \n\
1974 uniform int fw_surfaceStyles[]; \n\
1975 uniform int fw_nStyles; \n\
1976 #endif //ISO \n\
1977  \n\
1978 struct Ray { \n\
1979  vec3 Origin; \n\
1980  vec3 Dir; \n\
1981 }; \n\
1982 struct AABB { \n\
1983  vec3 Min; \n\
1984  vec3 Max; \n\
1985 }; \n\
1986 bool IntersectBox(Ray r, AABB aabb, out float t0, out float t1) \n\
1987 { \n\
1988  vec3 invR = 1.0 / r.Dir; \n\
1989  vec3 tbot = invR * (aabb.Min-r.Origin); \n\
1990  vec3 ttop = invR * (aabb.Max-r.Origin); \n\
1991  vec3 tmin = min(ttop, tbot); \n\
1992  vec3 tmax = max(ttop, tbot); \n\
1993  vec2 t = max(tmin.xx, tmin.yz); \n\
1994  t0 = max(t.x, t.y); \n\
1995  t = min(tmax.xx, tmax.yz); \n\
1996  t1 = min(t.x, t.y); \n\
1997  return t0 <= t1; \n\
1998 } \n\
1999 /* PLUG-DECLARATIONS */ \n\
2000  \n\
2001 vec3 fw_TexCoord[1]; \n\
2002 #ifdef CLIP \n\
2003 #define FW_MAXCLIPPLANES 4 \n\
2004 uniform int fw_nclipplanes; \n\
2005 uniform vec4 fw_clipplanes[FW_MAXCLIPPLANES]; \n\
2006 bool clip (in vec3 vertex_object){ \n\
2007  bool iclip = false; \n\
2008  for ( int i=0; i<fw_nclipplanes; i++ ) { \n\
2009  if( dot( fw_clipplanes[i], vec4(vertex_object,1.0)) < 0.0) \n\
2010  iclip = true; \n\
2011  } \n\
2012  return iclip; \n\
2013 } \n\
2014 #endif //CLIP \n\
2015 vec3 vertex_eye; \n\
2016 vec3 normal_eye; \n\
2017 vec4 raysum; \n\
2018 void main(void) \n\
2019 { \n\
2020  debug_color = vec4(0.0); \n\
2021  float maxDist = length(fw_dimensions); //1.414214; //sqrt(2.0); \n\
2022  int numSamples = 128; \n\
2023  float fnumSamples = float(numSamples); \n\
2024  float stepSize = maxDist/fnumSamples; \n\
2025  float densityFactor = 5.0/fnumSamples; //.88; // 1.0=normal H3D, .5 see deeper \n\
2026  \n\
2027  vec4 fragment_color; \n\
2028  //vec4 raysum; \n\
2029  vec3 rayDirection; \n\
2030  //convert window to frustum \n\
2031  rayDirection.xy = 2.0 * (gl_FragCoord.xy - fw_viewport.xy) / fw_viewport.zw - vec2(1.0); \n\
2032  rayDirection.z = 0.0; \n\
2033  vec3 rayOrigin; // = fw_RayOrigin; \n\
2034  //the equivalent of gluUnproject \n\
2035  //by unprojecting 2 points on ray here, this should also work with ortho viewpoint \n\
2036  vec4 ray4 = vec4(rayDirection,1.0); \n\
2037  vec4 org4 = ray4; \n\
2038  //if I back up the ray origin by -1.0 the front plane clipping works properly \n\
2039  ray4.z = 0.0; //1.0; \n\
2040  org4.z = -1.0; //0.0; \n\
2041  ray4 = fw_ModelViewProjInverse * ray4; \n\
2042  org4 = fw_ModelViewProjInverse * org4; \n\
2043  ray4 /= ray4.w; \n\
2044  org4 /= org4.w; \n\
2045  rayDirection = normalize(ray4.xyz - org4.xyz); \n\
2046  rayOrigin = org4.xyz; \n\
2047  \n\
2048  Ray eye = Ray( rayOrigin, rayDirection); \n\
2049  vec3 half_dimensions = fw_dimensions * .5; \n\
2050  vec3 minus_half_dimensions = half_dimensions * -1.0; \n\
2051  AABB aabb = AABB(minus_half_dimensions,half_dimensions); \n\
2052  \n\
2053  float tnear, tfar; \n\
2054  IntersectBox(eye, aabb, tnear, tfar); \n\
2055  if (tnear < 0.0) tnear = 0.0; \n\
2056  vec3 rayStart = eye.Origin + eye.Dir * tnear; \n\
2057  vec3 rayStop = eye.Origin + eye.Dir * tfar; \n\
2058  // Perform the ray marching: \n\
2059  vec3 pos = rayStart; \n\
2060  vec3 step = normalize(rayStop-rayStart) * stepSize; \n\
2061  float totaltravel = distance(rayStop, rayStart); \n\
2062  float travel = totaltravel; \n\
2063  float T = 1.0; \n\
2064  vec3 Lo = vec3(0.0); \n\
2065  normal_eye = rayDirection; \n\
2066  vec3 pos2 = pos; \n\
2067  // Transform from object space to texture coordinate space: \n\
2068  pos2 = (pos2+half_dimensions)/fw_dimensions; \n\
2069  pos2 = clamp(pos2,0.001,.999); \n\
2070  raysum = vec4(0.0); \n\
2071  float depth = 0.0; \n\
2072  float lastdensity; \n\
2073  float lastdensity_iso; \n\
2074  \n\
2075  for (int i=0; i < numSamples; ++i) { \n\
2076  //raysum = HeatMapColor(travel,0.0,2.0); \n\
2077  //break; \n\
2078  // ...lighting and absorption stuff here... \n\
2079  pos2 = pos; \n\
2080  vertex_eye = pos2; \n\
2081  // Transform from object space to texture coordinate space: \n\
2082  pos2 = (pos2+half_dimensions)/fw_dimensions; \n\
2083  //pos2.z = 1.0 - pos2.z; //RHS to LHS \n\
2084  pos2 = clamp(pos2,0.001,.999); \n\
2085  vec3 texcoord3 = pos2; \n\
2086  bool iclip = false; \n\
2087  #ifdef CLIP \n\
2088  iclip = clip(vertex_eye); //clip(totaltravel - travel); \n\
2089  #endif //CLIP \n\
2090  if(!iclip) { \n\
2091  fragment_color = vec4(1.0,0.0,1.0,1.0); //do I need a default? seems not \n\
2092  /* PLUG: texture3D ( fragment_color, texcoord3) */ \n\
2093  #ifdef SEGMENT \n\
2094  int jstyle = 1; \n\
2095  if(inEnabledSegment(texcoord3,jstyle)){ \n\
2096  #endif //SEGMENT \n\
2097  //assuming we had a scalar input image and put L into .a, \n\
2098  // and computed gradient and put in .rgb : \n\
2099  float density = fragment_color.a; //recover the scalar value \n\
2100  vec3 gradient = fragment_color.rgb - vec3(.5,.5,.5); //we added 127 to (-127 to 127) in CPU gradient computation\n\
2101  //vec4 voxel = vec4(density,density,density,density); //this is where the black visual voxels come from\n\
2102  vec4 voxel = vec4(density,density,density,density); //this is where the black visual voxels come from\n\
2103  \n\
2104  #ifdef ISO \n\
2105  if(i==0){ \n\
2106  lastdensity = density; \n\
2107  lastdensity_iso = 0.0; \n\
2108  } \n\
2109  int MODE = fw_nVals == 1 ? 1 : 3; \n\
2110  MODE = fw_stepSize != 0.0 && MODE == 1 ? 2 : 1; \n\
2111  #ifdef ISO_MODE3 \n\
2112  if(MODE == 3){ \n\
2113  for(int i=0;i<fw_nVals;i++){ \n\
2114  float iso = fw_surfaceVals[i]; \n\
2115  if( sign( density - iso) != sign( lastdensity - iso) && length(gradient) > fw_tolerance ){ \n\
2116  voxel.a = 1.0; \n\
2117  int jstyle = min(i,fw_nStyles-1); \n\
2118  jstyle = fw_surfaceStyles[jstyle]; \n\
2119  if(jstyle == 1){ \n\
2120  /* PLUG: voxel_apply_DEFAULT (voxel, gradient) */ \n\
2121  } else if(jstyle == 2) { \n\
2122  /* PLUG: voxel_apply_OPACITY (voxel, gradient) */ \n\
2123  } else if(jstyle == 3) { \n\
2124  /* PLUG: voxel_apply_BLENDED (voxel, gradient) */ \n\
2125  } else if(jstyle == 4) { \n\
2126  /* PLUG: voxel_apply_BOUNDARY (voxel, gradient) */ \n\
2127  } else if(jstyle == 5) { \n\
2128  /* PLUG: voxel_apply_CARTOON (voxel, gradient) */ \n\
2129  } else if(jstyle == 6) { \n\
2130  /* PLUG: voxel_apply_DEFAULT (voxel, gradient) */ \n\
2131  } else if(jstyle == 7) { \n\
2132  /* PLUG: voxel_apply_EDGE (voxel, gradient) */ \n\
2133  } else if(jstyle == 8) { \n\
2134  /* PLUG: voxel_apply_PROJECTION (voxel, gradient) */ \n\
2135  } else if(jstyle == 9) { \n\
2136  /* PLUG: voxel_apply_SHADED (voxel, gradient) */ \n\
2137  } else if(jstyle == 10) { \n\
2138  /* PLUG: voxel_apply_SILHOUETTE (voxel, gradient) */ \n\
2139  } else if(jstyle == 11) { \n\
2140  /* PLUG: voxel_apply_TONE (voxel, gradient) */ \n\
2141  } \n\
2142  } else { \n\
2143  voxel = vec4(0.0); //similar to discard \n\
2144  } \n\
2145  } \n\
2146  lastdensity = density; \n\
2147  } \n\
2148  #else //ISO_MODE3 \n\
2149  if(MODE == 1){ \n\
2150  float iso = fw_surfaceVals[0]; \n\
2151  if( sign( density - iso) != sign( lastdensity - iso) && length(gradient) > fw_tolerance ){ \n\
2152  //debug_color = HeatMapColor(iso,0.0,.3); \n\
2153  voxel.a = 1.0; \n\
2154  /* PLUG: voxel_apply (voxel, gradient) */ \n\
2155  } else { \n\
2156  voxel = vec4(0.0); //similar to discard \n\
2157  } \n\
2158  lastdensity = density; \n\
2159  } else if(MODE == 2){ \n\
2160  float iso = fw_surfaceVals[0]; \n\
2161  float density_iso = density / fw_stepSize; \n\
2162  if( sign( density_iso - iso) != sign( lastdensity_iso - iso) && length(gradient) > fw_tolerance ){ \n\
2163  voxel.a = 1.0; \n\
2164  /* PLUG: voxel_apply (voxel, gradient) */ \n\
2165  } else { \n\
2166  voxel = vec4(0.0); //similar to discard \n\
2167  } \n\
2168  lastdensity = density; \n\
2169  lastdensity_iso = density_iso; \n\
2170  } \n\
2171  #endif //ISO_MODE3 \n\
2172  #else //ISO \n\
2173  #ifdef SEGMENT \n\
2174  //debug_color = HeatMapColor(float(jstyle),1.0,12.0); \n\
2175  //debug_color.a = .2; \n\
2176  if(jstyle == 1){ \n\
2177  /* PLUG: voxel_apply_DEFAULT (voxel, gradient) */ \n\
2178  } else if(jstyle == 2) { \n\
2179  /* PLUG: voxel_apply_OPACITY (voxel, gradient) */ \n\
2180  } else if(jstyle == 3) { \n\
2181  /* PLUG: voxel_apply_BLENDED (voxel, gradient) */ \n\
2182  } else if(jstyle == 4) { \n\
2183  /* PLUG: voxel_apply_BOUNDARY (voxel, gradient) */ \n\
2184  } else if(jstyle == 5) { \n\
2185  /* PLUG: voxel_apply_CARTOON (voxel, gradient) */ \n\
2186  } else if(jstyle == 6) { \n\
2187  /* PLUG: voxel_apply_DEFAULT (voxel, gradient) */ \n\
2188  } else if(jstyle == 7) { \n\
2189  /* PLUG: voxel_apply_EDGE (voxel, gradient) */ \n\
2190  } else if(jstyle == 8) { \n\
2191  /* PLUG: voxel_apply_PROJECTION (voxel, gradient) */ \n\
2192  } else if(jstyle == 9) { \n\
2193  /* PLUG: voxel_apply_SHADED (voxel, gradient) */ \n\
2194  } else if(jstyle == 10) { \n\
2195  /* PLUG: voxel_apply_SILHOUETTE (voxel, gradient) */ \n\
2196  } else if(jstyle == 11) { \n\
2197  /* PLUG: voxel_apply_TONE (voxel, gradient) */ \n\
2198  } \n\
2199  #else //SEGMENT \n\
2200  //non-iso rendering styles \n\
2201  //void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) \n\
2202  /* PLUG: voxel_apply (voxel, gradient) */ \n\
2203  #endif //SEGMENT \n\
2204  #endif //ISO \n\
2205  density = voxel.a; \n\
2206  //debug_color = HeatMapColor(densityFactor,0.134,.135); \n\
2207  T = (1.0 - raysum.a); \n\
2208  raysum.a += density * T; \n\
2209  raysum.rgb += voxel.rgb * T * density; \n\
2210  if(raysum.a > .99) { \n\
2211  break; \n\
2212  } \n\
2213  #ifdef SEGMENT \n\
2214  } //if inEnabledSegment \n\
2215  #endif //SEGMENT \n\
2216  } //iclip \n\
2217  travel -= stepSize; \n\
2218  depth += stepSize; \n\
2219  if(travel <= 0.0) break; \n\
2220  pos += step; \n\
2221  \n\
2222  } \n\
2223  //void PLUG_ray_apply (inout vec4 raysum) \n\
2224  /* PLUG: ray_apply (raysum) */ \n\
2225  if(true) gl_FragColor = raysum; \n\
2226  else gl_FragColor = debug_color; \n\
2227 } \n\
2228 ";
2229 
2230 
2231 //void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) {
2232 
2233 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#OpacityMapVolumeStyle
2234 // opacity with intensity == intensity lookup/transferFunction
2235 
2236 static const GLchar *plug_voxel_DEFAULT = "\
2237 void voxel_apply_DEFAULT (inout vec4 voxel, inout vec3 gradient) { \n\
2238  float alpha = voxel.a; \n\
2239  //voxel.a = voxel.r; \n\
2240  //voxel.rgb = vec3(alpha); \n\
2241 } \n\
2242 void PLUG_voxel_apply_DEFAULT (inout vec4 voxel, inout vec3 gradient) { \n\
2243  voxel_apply_DEFAULT(voxel,gradient); \n\
2244 } \n\
2245 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2246  voxel_apply_DEFAULT(voxel,gradient); \n\
2247 } \n\
2248 ";
2249 
2250 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#OpacityMapVolumeStyle
2251 static const GLchar *plug_voxel_OPACITY = "\
2252 uniform int fw_opacTexture; \n\
2253 //uniform sampler2D fw_Texture_unit3; \n\
2254 void voxel_apply_OPACITY (inout vec4 voxel, inout vec3 gradient) { \n\
2255  if(fw_opacTexture == 1){ \n\
2256  vec4 lookup_color; \n\
2257  float lum = voxel.r; \n\
2258  vec2 texcoord = vec2(lum,0.0); \n\
2259  //this is too simple for the lookups in the specs \n\
2260  //http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#t-transferFunctionTextureCoordinateMapping \n\
2261  lookup_color = texture2D(fw_Texture_unit3,texcoord); \n\
2262  voxel.rgb = lookup_color.rgb; \n\
2263  voxel.a = lum; \n\
2264  }else{ \n\
2265  //like default \n\
2266  float alpha = voxel.a; \n\
2267  voxel.a = voxel.r; \n\
2268  voxel.rgb = vec3(alpha); \n\
2269  } \n\
2270 } \n\
2271 void PLUG_voxel_apply_OPACITY (inout vec4 voxel, inout vec3 gradient) { \n\
2272  voxel_apply_OPACITY(voxel, gradient); \n\
2273 } \n\
2274 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2275  voxel_apply_OPACITY(voxel, gradient); \n\
2276 } \n\
2277 ";
2278 
2279 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#BlendedVolumeStyle
2280 static const GLchar *plug_voxel_BLENDED = "\
2281 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2282 } \n\
2283 ";
2284 
2285 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#BoundaryEnhancementVolumeStyle
2286 static const GLchar *plug_voxel_BOUNDARY = "\n\
2287 uniform float fw_boundaryOpacity; \n\
2288 uniform float fw_retainedOpacity; \n\
2289 uniform float fw_opacityFactor; \n\
2290 void voxel_apply_BOUNDARY (inout vec4 voxel, inout vec3 gradient) { \n\
2291  float magnitude = length(gradient); \n\
2292  float factor = (fw_retainedOpacity + fw_boundaryOpacity*pow(magnitude,fw_opacityFactor) ); \n\
2293  voxel.a = voxel.a * factor; \n\
2294  //debug_color = HeatMapColor(factor,0.0,1.0); \n\
2295 } \n\
2296 void PLUG_voxel_apply_BOUNDARY (inout vec4 voxel, inout vec3 gradient) { \n\
2297  voxel_apply_BOUNDARY(voxel, gradient); \n\
2298 } \n\
2299 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2300  voxel_apply_BOUNDARY(voxel, gradient); \n\
2301 } \n\
2302 ";
2303 
2304 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#CartoonVolumeStyle
2305 static const GLchar *plug_voxel_CARTOON = "\n\
2306 uniform int fw_colorSteps; \n\
2307 uniform vec4 fw_orthoColor; \n\
2308 uniform vec4 fw_paraColor; \n\
2309 void voxel_apply_CARTOON (inout vec4 voxel, inout vec3 gradient) { \n\
2310  float len = length(gradient); \n\
2311  if(len > 0.01) { \n\
2312  vec3 ng = normalize(gradient); \n\
2313  float ndotv = dot(normal_eye,ng); \n\
2314  if(ndotv > 0.01 && voxel.a > 0.0) { \n\
2315  ndotv = floor(ndotv/float(fw_colorSteps))*float(fw_colorSteps); \n\
2316  vec4 color = mix(fw_orthoColor,fw_paraColor,ndotv); \n\
2317  //voxel.rgb = color.rgb*voxel.a; \n\
2318  voxel.rgb = color.rgb; \n\
2319  } else { \n\
2320  voxel = vec4(0.0); //similar to discard \n\
2321  } \n\
2322  } else { \n\
2323  voxel = vec4(0.0); //similar to discard \n\
2324  } \n\
2325 } \n\
2326 void PLUG_voxel_apply_CARTOON (inout vec4 voxel, inout vec3 gradient) { \n\
2327  voxel_apply_CARTOON(voxel, gradient); \n\
2328 } \n\
2329 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2330  voxel_apply_CARTOON(voxel, gradient); \n\
2331 } \n\
2332 ";
2333 
2334 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#ComposedVolumeStyle
2335 static const GLchar *plug_voxel_COMPOSED = "\
2336 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2337 } \n\
2338 ";
2339 
2340 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#EdgeEnhancementVolumeStyle
2341 static const GLchar *plug_voxel_EDGE = "\
2342 uniform float fw_cosGradientThreshold; \n\
2343 uniform vec4 fw_edgeColor; \n\
2344 void voxel_apply_EDGE (inout vec4 voxel, inout vec3 gradient) { \n\
2345  float len = length(gradient); \n\
2346  if(len > 0.01) { \n\
2347  vec3 ng = normalize(gradient); \n\
2348  float ndotv = abs(dot(normal_eye,ng)); \n\
2349  if( ndotv < fw_cosGradientThreshold ) { \n\
2350  voxel = mix(voxel,fw_edgeColor,1.0 -ndotv); \n\
2351  } \n\
2352  } \n\
2353 } \n\
2354 void PLUG_voxel_apply_EDGE (inout vec4 voxel, inout vec3 gradient) { \n\
2355  voxel_apply_EDGE(voxel, gradient); \n\
2356 } \n\
2357 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2358  voxel_apply_EDGE(voxel, gradient); \n\
2359 } \n\
2360 ";
2361 
2362 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#ProjectionVolumeStyle
2363 static const GLchar *plug_voxel_PROJECTION = "\n\
2364 uniform float fw_intensityThreshold; \n\
2365 uniform int fw_projType; \n\
2366 float MAXPROJ = 0.0; \n\
2367 float MINPROJ = 1.0; \n\
2368 float AVEPROJ = 0.0; \n\
2369 float LMIP = 0.0; \n\
2370 vec4 RGBAPROJ; \n\
2371 int PROJCOUNT = 0; \n\
2372 void voxel_apply_PROJECTION (inout vec4 voxel, inout vec3 gradient) { \n\
2373  PROJCOUNT++; \n\
2374  float cval = length(voxel.rgb); \n\
2375  if(fw_projType == 1){ \n\
2376  //MIN \n\
2377  if(cval < MINPROJ){ \n\
2378  MINPROJ = cval; \n\
2379  RGBAPROJ = voxel; \n\
2380  } \n\
2381  }else if(fw_projType == 2){ \n\
2382  //MAX \n\
2383  if(fw_intensityThreshold > 0.0){ \n\
2384  //LMIP \n\
2385  if(LMIP == 0.0) { \n\
2386  LMIP = cval; \n\
2387  RGBAPROJ = voxel; \n\
2388  } \n\
2389  } else { \n\
2390  //MIP \n\
2391  if(cval > MAXPROJ){ \n\
2392  MAXPROJ = cval; \n\
2393  RGBAPROJ = voxel; \n\
2394  } \n\
2395  } \n\
2396  }else if(fw_projType==3){ \n\
2397  //AVERAGE \n\
2398  AVEPROJ += cval; \n\
2399  RGBAPROJ += voxel; \n\
2400  } \n\
2401 } \n\
2402 void PLUG_voxel_apply_PROJECTION (inout vec4 voxel, inout vec3 gradient) { \n\
2403  voxel_apply_PROJECTION(voxel, gradient); \n\
2404 } \n\
2405 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2406  voxel_apply_PROJECTION(voxel, gradient); \n\
2407 } \n\
2408 void PLUG_ray_apply (inout vec4 raysum) { \n\
2409  float value = 0.0; \n\
2410  vec4 color = vec4(1.0); \n\
2411  if(fw_projType == 1){ \n\
2412  //MIN \n\
2413  value = MINPROJ; \n\
2414  color = RGBAPROJ; \n\
2415  }else if(fw_projType == 2){ \n\
2416  //MAX \n\
2417  if(fw_intensityThreshold > 0.0){ \n\
2418  //LMIP \n\
2419  value = LMIP; \n\
2420  color = RGBAPROJ; \n\
2421  } else { \n\
2422  //MIP \n\
2423  value = MAXPROJ; \n\
2424  color = RGBAPROJ; \n\
2425  } \n\
2426  }else if(fw_projType==3){ \n\
2427  //AVERAGE \n\
2428  value = AVEPROJ / float(PROJCOUNT); \n\
2429  color = RGBAPROJ / float(PROJCOUNT); \n\
2430  } \n\
2431  //raysum.rgb = color.rgb * color.a; \n\
2432  //raysum.a = color.a; \n\
2433  \n\
2434  raysum.rgb = vec3(value,value,value); \n\
2435 // raysum.a = 1.0 - value; \n\
2436  //raysum.a = value;\n\
2437  //raysum.a = color.a; \n\
2438  //raysum = color; \n\
2439 } \n\
2440 ";
2441 
2442 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#ShadedVolumeStyle
2443 static const GLchar *plug_voxel_SHADED = "\
2444 #ifdef LITE \n\
2445 #define MAX_LIGHTS 8 \n\
2446 uniform int lightcount; \n\
2447 //uniform float lightRadius[MAX_LIGHTS]; \n\
2448 uniform int lightType[MAX_LIGHTS];//ANGLE like this \n\
2449 struct fw_LightSourceParameters { \n\
2450  vec4 ambient; \n\
2451  vec4 diffuse; \n\
2452  vec4 specular; \n\
2453  vec4 position; \n\
2454  vec4 halfVector; \n\
2455  vec4 spotDirection; \n\
2456  float spotBeamWidth; \n\
2457  float spotCutoff; \n\
2458  vec3 Attenuations; \n\
2459  float lightRadius; \n\
2460 }; \n\
2461 \n\
2462 uniform fw_LightSourceParameters fw_LightSource[MAX_LIGHTS] /* gl_MaxLights */ ;\n\
2463 #endif //LITE \n\
2464  \n\
2465 #ifdef FOG \n\
2466 struct fogParams \n\
2467 { \n\
2468  vec4 fogColor; \n\
2469  float visibilityRange; \n\
2470  float fogScale; \n\
2471  int fogType; // 0 None, 1= FOGTYPE_LINEAR, 2 = FOGTYPE_EXPONENTIAL \n\
2472  // ifdefed int haveFogCoords; \n\
2473 }; \n\
2474 uniform fogParams fw_fogparams; \n\
2475 #endif //FOG \n\
2476 #ifdef LIT \n\
2477 #ifdef LITE \n\
2478 //per-fragment lighting ie phong \n\
2479 struct fw_MaterialParameters { \n\
2480  vec4 emission; \n\
2481  vec4 ambient; \n\
2482  vec4 diffuse; \n\
2483  vec4 specular; \n\
2484  float shininess; \n\
2485 }; \n\
2486 uniform fw_MaterialParameters fw_FrontMaterial; \n\
2487 #ifdef TWO \n\
2488 uniform fw_MaterialParameters fw_BackMaterial; \n\
2489 #endif //TWO \n\
2490 vec3 castle_ColorES; \n\
2491 #else //LITE \n\
2492 //per-vertex lighting - interpolated Emissive-specular \n\
2493 varying vec3 castle_ColorES; //emissive shininess term \n\
2494 #endif //LITE \n\
2495 #endif //LIT\n\
2496 uniform int fw_phase; \n\
2497 uniform int fw_lighting; \n\
2498 uniform int fw_shadows; \n\
2499 void voxel_apply_SHADED (inout vec4 voxel, inout vec3 gradient) { \n\
2500  float len = length(gradient); \n\
2501  vec3 ng = vec3(0.0); \n\
2502  if(len > 0.0) \n\
2503  ng = normalize(gradient); \n\
2504  vec4 color = vec4(1.0); \n\
2505  #ifdef LIT \n\
2506  vec3 castle_ColorES = fw_FrontMaterial.specular.rgb; \n\
2507  color.rgb = fw_FrontMaterial.diffuse.rgb; \n\
2508  #else //LIT \n\
2509  color.rgb = vec3(0,0,0.0,0.0); \n\
2510  vec3 castle_ColorES = vec3(0.0,0.0,0.0); \n\
2511  #endif //LIT \n\
2512  // void add_light_contribution2(inout vec4 vertexcolor, inout vec3 specularcolor, in vec4 myPosition, in vec3 myNormal, in float shininess ); \n\
2513  vec4 vertex_eye4 = vec4(vertex_eye,1.0); \n\
2514  /* PLUG: add_light_contribution2 (color, castle_ColorES, vertex_eye4, ng, fw_FrontMaterial.shininess) */ \n\
2515  // voxel.rgb = color.rgb; \n\
2516  color.rgb = mix(color.rgb,castle_ColorES,dot(ng,normal_eye)); \n\
2517  voxel.rgb = color.rgb; \n\
2518  //voxel.rgb = voxel.rgb * color.rgb; \n\
2519 } \n\
2520 void PLUG_voxel_apply_SHADED (inout vec4 voxel, inout vec3 gradient) { \n\
2521  voxel_apply_SHADED(voxel, gradient); \n\
2522 } \n\
2523 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2524  voxel_apply_SHADED(voxel, gradient); \n\
2525 } \n\
2526 ";
2527 
2528 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#SilhouetteEnhancementVolumeStyle
2529 static const GLchar *plug_voxel_SILHOUETTE = "\n\
2530 uniform float fw_BoundaryOpacity; \n\
2531 uniform float fw_RetainedOpacity; \n\
2532 uniform float fw_Sharpness; \n\
2533 void voxel_apply_SILHOUETTE (inout vec4 voxel, inout vec3 gradient) { \n\
2534  float len = length(gradient); \n\
2535  if(len > 0.01) { \n\
2536  vec3 ng = normalize(gradient); \n\
2537  float ndotv = abs(dot(ng,normal_eye)); \n\
2538  float factor = (fw_RetainedOpacity + fw_BoundaryOpacity*pow(1.0 - ndotv,fw_Sharpness)); \n\
2539  //float factor = (fw_RetainedOpacity + pow(fw_BoundaryOpacity*(1.0 - ndotv),fw_Sharpness)); \n\
2540  //debug_color = HeatMapColor(factor,0.0,1.0); \n\
2541  voxel.a = voxel.a * factor; \n\
2542  } \n\
2543 } \n\
2544 void PLUG_voxel_apply_SILHOUETTE (inout vec4 voxel, inout vec3 gradient) { \n\
2545  voxel_apply_SILHOUETTE(voxel, gradient); \n\
2546 } \n\
2547 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2548  voxel_apply_SILHOUETTE(voxel, gradient); \n\
2549 } \n\
2550 ";
2551 
2552 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#ToneMappedVolumeStyle
2553 static const GLchar *plug_voxel_TONE = "\
2554 uniform vec4 fw_coolColor; \n\
2555 uniform vec4 fw_warmColor; \n\
2556 void voxel_apply_TONE (inout vec4 voxel, inout vec3 gradient) { \n\
2557  float len = length(gradient); \n\
2558  if(len > 0.0) { \n\
2559  vec3 color; \n\
2560  vec3 ng = normalize(gradient); \n\
2561  //vec3 L = normalize(vec3(-.707,-.707,.707)); \n\
2562  float cc = (1.0 + dot(normal_eye,ng))*.5; \n\
2563  //float cc = (1.0 + dot(L,ng))*.5; \n\
2564  //debug_color = HeatMapColor(cc,0.0,1.0); \n\
2565  color = mix(fw_coolColor.rgb,fw_warmColor.rgb,cc); \n\
2566  voxel = vec4(color,voxel.a); \n\
2567  } else { \n\
2568  voxel.a = 0.0; \n\
2569  //debug_color = vec4(0.0); \n\
2570  } \n\
2571 } \n\
2572 void PLUG_voxel_apply_TONE (inout vec4 voxel, inout vec3 gradient) { \n\
2573  voxel_apply_TONE(voxel, gradient); \n\
2574 } \n\
2575 void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
2576  voxel_apply_TONE(voxel, gradient); \n\
2577 } \n\
2578 ";
2579 
2580 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#BlendedVolumeStyle
2581 // blended (BlendedVolumeStyle) works (was interpreted and implemented by dug9, Oct 2016)
2582 // by rendering 2 volumedatas to 2 fbo textures, then running
2583 // this shader to blend the 2 fbo textures and spit out fragments just
2584 // where the box is. Use with the regular volume Vertex shader so
2585 // only frags over the box show, and so we get box depth for depth blending
2586 // with the main scene
2587 static const GLchar *volumeBlendedFragmentGLES2 = " \n\
2588 /* DEFINES */ \n\
2589 #ifdef MOBILE \n\
2590 //precision highp float; \n\
2591 precision mediump float; \n\
2592 #endif //MOBILE \n\
2593  vec4 HeatMapColor(float value, float minValue, float maxValue) \n\
2594 { \n\
2595  //used for debugging. If min=0,max=1 then magenta is 0, blue,green,yellow, red is 1 \n\
2596  vec4 ret; \n\
2597  int HEATMAP_COLORS_COUNT; \n\
2598  vec4 colors[6]; \n\
2599  HEATMAP_COLORS_COUNT = 6; \n\
2600  colors[0] = vec4(0.32, 0.00, 0.32, 1.0); \n\
2601  colors[1] = vec4( 0.00, 0.00, 1.00, 1.00); \n\
2602  colors[2] = vec4(0.00, 1.00, 0.00, 1.00); \n\
2603  colors[3] = vec4(1.00, 1.00, 0.00, 1.00); \n\
2604  colors[4] = vec4(1.00, 0.60, 0.00, 1.00); \n\
2605  colors[5] = vec4(1.00, 0.00, 0.00, 1.00); \n\
2606  float ratio=(float(HEATMAP_COLORS_COUNT)-1.0)*clamp((value-minValue)/(maxValue-minValue),0.0,1.0); \n\
2607  int indexMin=int(floor(ratio)); \n\
2608  int indexMax= indexMin+1 < HEATMAP_COLORS_COUNT-1 ? indexMin+1 : HEATMAP_COLORS_COUNT-1; \n\
2609  ret = mix(colors[indexMin], colors[indexMax], ratio-float(indexMin)); \n\
2610  if(value < minValue) ret = vec4(0.0,0.0,0.0,1.0); \n\
2611  if(value > maxValue) ret = vec4(1.0,1.0,1.0,1.0); \n\
2612  return ret; \n\
2613 } \n\
2614 vec4 debug_color; \n\
2615  \n\
2616 uniform vec4 fw_viewport; \n\
2617 uniform sampler2D fw_Texture_unit0; \n\
2618 uniform sampler2D fw_Texture_unit1; \n\
2619 uniform sampler2D fw_Texture_unit2; \n\
2620 uniform sampler2D fw_Texture_unit3; \n\
2621 uniform float fw_iwtc1; \n\
2622 uniform float fw_iwtc2; \n\
2623 uniform int fw_iwtf1; \n\
2624 uniform int fw_iwtf2; \n\
2625 uniform int fw_haveTransfers; \n\
2626 vec3 weightcolor( in vec3 color, in int func, in float wt, in float ov, in float oblend, in sampler2D table){ \n\
2627  vec3 ret; \n\
2628  if(func == 1){ \n\
2629  ret = color * wt; \n\
2630  }else if(func == 2){ \n\
2631  ret = color * ov; \n\
2632  }else if(func == 3){ \n\
2633  ret = color * oblend; \n\
2634  }else if(func == 4){ \n\
2635  ret = color * (1.0 - oblend); \n\
2636  }else if(func == 5){ \n\
2637  vec2 texcoord = color.rg;\n\
2638  ret = color * texture2D(table,texcoord).r; \n\
2639  } \n\
2640  return ret; \n\
2641 } \n\
2642 float weightalpha( in float alpha, in int func, in float wt, in float ov, in float oblend, in sampler2D table){ \n\
2643  float ret; \n\
2644  if(func == 1){ \n\
2645  ret = alpha * wt; \n\
2646  }else if(func == 2){ \n\
2647  ret = alpha * ov; \n\
2648  }else if(func == 3){ \n\
2649  ret = alpha * oblend; \n\
2650  }else if(func == 4){ \n\
2651  ret = alpha * (1.0 - oblend); \n\
2652  }else if(func == 5){ \n\
2653  vec2 texcoord = vec2(alpha,0);\n\
2654  ret = alpha * texture2D(table,texcoord).r; \n\
2655  } \n\
2656  return ret; \n\
2657 } \n\
2658 void main(void) \n\
2659 { \n\
2660  vec2 fc = (gl_FragCoord.xy - fw_viewport.xy) / fw_viewport.zw; \n\
2661  vec4 frag0 = texture2D(fw_Texture_unit0,fc); \n\
2662  vec4 frag1 = texture2D(fw_Texture_unit1,fc); \n\
2663  vec3 cv = frag0.rgb; \n\
2664  float ov = frag0.a; \n\
2665  vec3 cblend = frag1.rgb; \n\
2666  float oblend = frag1.a; \n\
2667  vec3 cvw, cbw; \n\
2668  float ovw, obw; \n\
2669  cvw = weightcolor(cv,fw_iwtf1,fw_iwtc1,ov,oblend,fw_Texture_unit2); \n\
2670  ovw = weightalpha(ov,fw_iwtf1,fw_iwtc1,ov,oblend,fw_Texture_unit2); \n\
2671  cbw = weightcolor(cblend,fw_iwtf2,fw_iwtc2,ov,oblend,fw_Texture_unit3); \n\
2672  obw = weightalpha(oblend,fw_iwtf2,fw_iwtc2,ov,oblend,fw_Texture_unit3); \n\
2673  vec3 cg = clamp( cvw + cbw, 0.0, 1.0); \n\
2674  float og = clamp(ovw + obw, 0.0, 1.0); \n\
2675  \n\
2676  gl_FragColor = vec4(cg,og); \n\
2677 } \n\
2678 ";
2679 
2680 
2681 const char *getVolumeVertex(void){
2682  return volumeVertexGLES2; //genericVertexDesktop
2683 }
2684 const char *getVolumeFragment(){
2685  return volumeFragmentGLES2; //genericFragmentDesktop;
2686 }
2687 int getSpecificShaderSourceVolume (const GLchar **vertexSource, const GLchar **fragmentSource, shaderflagsstruct whichOne)
2688 {
2689  //for building the Builtin (similar to fixed-function pipeline, except from shader parts)
2690  //in OpenGL_Utils.c L.2553 set usingCastlePlugs = 1 to get in here.
2691  //whichone - a bitmask of shader requirements, one bit for each requirement, so shader permutation can be built
2692 
2693  int retval, unique_int;
2694  unsigned int volflags;
2695  unsigned char volflag[7];
2696  int kflags,i,k;
2697  char *CompleteCode[3];
2698  char *vs, *fs;
2699  retval = FALSE;
2700  if(whichOne.usershaders ) //& USER_DEFINED_SHADER_MASK)
2701  return retval; //not supported yet as of Aug 9, 2016
2702  retval = TRUE;
2703 
2704  //generic
2705  vs = strdup(getVolumeVertex());
2706  fs = strdup(getVolumeFragment());
2707 
2708  CompleteCode[SHADERPART_VERTEX] = vs;
2709  CompleteCode[SHADERPART_GEOMETRY] = NULL;
2710  if(whichOne.volume == SHADERFLAGS_VOLUME_STYLE_BLENDED << 4){
2711  CompleteCode[SHADERPART_FRAGMENT] = STRDUP(volumeBlendedFragmentGLES2);
2712 
2713  }else{
2714  CompleteCode[SHADERPART_FRAGMENT] = fs;
2715  }
2716 
2717  // what we really have here: UberShader with CastlePlugs
2718  // UberShader: one giant shader peppered with #ifdefs, and you add #defines at the top for permutations
2719  // CastlePlugs: allows users to add effects on to uberShader with PLUGs
2720  // - and internally, we can do a few permutations with PLUGs too
2721 
2722  if(isMobile){
2723  AddVersion(SHADERPART_VERTEX, 100, CompleteCode); //lower precision floats
2724  AddVersion(SHADERPART_FRAGMENT, 100, CompleteCode); //lower precision floats
2725  AddDefine(SHADERPART_FRAGMENT,"MOBILE",CompleteCode); //lower precision floats
2726  }else{
2727  //desktop, emulating GLES2
2728  AddVersion(SHADERPART_VERTEX, 110, CompleteCode); //lower precision floats
2729  AddVersion(SHADERPART_FRAGMENT, 110, CompleteCode); //lower precision floats
2730  }
2731 
2732  if(whichOne.volume == SHADERFLAGS_VOLUME_STYLE_BLENDED << 4){
2733  *fragmentSource = CompleteCode[SHADERPART_FRAGMENT]; //original_fragment; //fs;
2734  *vertexSource = CompleteCode[SHADERPART_VERTEX]; //original_vertex; //vs;
2735  return retval;
2736  }
2737 
2738  unique_int = 0; //helps generate method name PLUG_xxx_<unique_int> to avoid clash when multiple PLUGs supplied for same PLUG
2739 
2740  //if(DESIRE(whichOne.volume,TEX3D_SHADER)){
2741  AddDefine(SHADERPART_FRAGMENT,"TEX3D",CompleteCode);
2742  Plug(SHADERPART_FRAGMENT,plug_fragment_texture3D_apply_volume,CompleteCode,&unique_int); //uses TILED
2743  //}
2744 
2745  if(DESIRE(whichOne.volume,SHADERFLAGS_VOLUME_DATA_BASIC)){
2746  AddDefine(SHADERPART_FRAGMENT,"BASIC",CompleteCode);
2747  }
2748  if(DESIRE(whichOne.volume,SHADERFLAGS_VOLUME_DATA_ISO)){
2749  AddDefine(SHADERPART_FRAGMENT,"ISO",CompleteCode);
2750  if(DESIRE(whichOne.volume,SHADERFLAGS_VOLUME_DATA_ISO_MODE3)){
2751  AddDefine(SHADERPART_FRAGMENT,"ISO_MODE3",CompleteCode);
2752  }
2753  }
2754  if(DESIRE(whichOne.volume,SHADERFLAGS_VOLUME_DATA_SEGMENT)){
2755  AddDefine(SHADERPART_FRAGMENT,"SEGMENT",CompleteCode);
2756  }
2757  if(DESIRE(whichOne.base,CLIPPLANE_SHADER)){
2758  AddDefine(SHADERPART_FRAGMENT,"CLIP",CompleteCode);
2759  // we use a special function in frag for clip for volume
2760  }
2761 
2762  //unsigned int 32 bits - 4 for basic, leaves 28/4 = max 7 styles
2763  //work from left to right (the order declared), skip any 0/null/empties
2764  volflags = whichOne.volume;
2765  // this was just here, but is defined above. volflag[7];
2766  kflags = 0;
2767  for(i=0;i<7;i++){
2768  int iflag = (volflags >> (7-i)*4) & 0xF;
2769  if(iflag){
2770  volflag[kflags] = iflag;
2771  kflags++;
2772  }
2773  }
2774  //now volflag[] is in the order declared with no 0s/nulls
2775  for(k=0;k<kflags;k++){
2776  switch(volflag[k]){
2777  case SHADERFLAGS_VOLUME_STYLE_DEFAULT:
2778  AddDefine(SHADERPART_FRAGMENT,"DEFAULT",CompleteCode);
2779  Plug(SHADERPART_FRAGMENT,plug_voxel_DEFAULT,CompleteCode,&unique_int);
2780  break;
2781  case SHADERFLAGS_VOLUME_STYLE_OPACITY:
2782  AddDefine(SHADERPART_FRAGMENT,"OPACITY",CompleteCode);
2783  Plug(SHADERPART_FRAGMENT,plug_voxel_OPACITY,CompleteCode,&unique_int);
2784  break;
2785  case SHADERFLAGS_VOLUME_STYLE_BLENDED:
2786  AddDefine(SHADERPART_FRAGMENT,"BLENDED",CompleteCode);
2787  Plug(SHADERPART_FRAGMENT,plug_voxel_BLENDED,CompleteCode,&unique_int);
2788  break;
2789  case SHADERFLAGS_VOLUME_STYLE_BOUNDARY:
2790  AddDefine(SHADERPART_FRAGMENT,"BOUNDARY",CompleteCode);
2791  Plug(SHADERPART_FRAGMENT,plug_voxel_BOUNDARY,CompleteCode,&unique_int);
2792  break;
2793  case SHADERFLAGS_VOLUME_STYLE_CARTOON:
2794  AddDefine(SHADERPART_FRAGMENT,"CARTOON",CompleteCode);
2795  Plug(SHADERPART_FRAGMENT,plug_voxel_CARTOON,CompleteCode,&unique_int);
2796  break;
2797  case SHADERFLAGS_VOLUME_STYLE_COMPOSED:
2798  AddDefine(SHADERPART_FRAGMENT,"COMPOSED",CompleteCode);
2799  Plug(SHADERPART_FRAGMENT,plug_voxel_COMPOSED,CompleteCode,&unique_int);
2800  break;
2801  case SHADERFLAGS_VOLUME_STYLE_EDGE:
2802  AddDefine(SHADERPART_FRAGMENT,"EDGE",CompleteCode);
2803  Plug(SHADERPART_FRAGMENT,plug_voxel_EDGE,CompleteCode,&unique_int);
2804  break;
2805  case SHADERFLAGS_VOLUME_STYLE_PROJECTION:
2806  AddDefine(SHADERPART_FRAGMENT,"PROJECTION",CompleteCode);
2807  Plug(SHADERPART_FRAGMENT,plug_voxel_PROJECTION,CompleteCode,&unique_int);
2808  break;
2809  case SHADERFLAGS_VOLUME_STYLE_SHADED:
2810  AddDefine(SHADERPART_FRAGMENT,"SHADED",CompleteCode);
2811  Plug(SHADERPART_FRAGMENT,plug_voxel_SHADED,CompleteCode,&unique_int);
2812  //if you want a plug within a plug, then if you include the higher level
2813  // plug first, then the lower level plug should find its tartget in the CompleteCode
2814  AddDefine(SHADERPART_FRAGMENT,"LIT",CompleteCode);
2815  AddDefine(SHADERPART_FRAGMENT,"LITE",CompleteCode);
2816  Plug(SHADERPART_FRAGMENT,plug_vertex_lighting_ADSLightModel,CompleteCode,&unique_int);
2817  break;
2818  case SHADERFLAGS_VOLUME_STYLE_SILHOUETTE:
2819  AddDefine(SHADERPART_FRAGMENT,"SILHOUETTE",CompleteCode);
2820  Plug(SHADERPART_FRAGMENT,plug_voxel_SILHOUETTE,CompleteCode,&unique_int);
2821  break;
2822  case SHADERFLAGS_VOLUME_STYLE_TONE:
2823  AddDefine(SHADERPART_FRAGMENT,"TONE",CompleteCode);
2824  Plug(SHADERPART_FRAGMENT,plug_voxel_TONE,CompleteCode,&unique_int);
2825  break;
2826  default:
2827  //if 0, just skip
2828  break;
2829  }
2830  }
2831 
2832 
2833  //shader doesn't compile?
2834  //in visual studio, this is a good place to get the composed shader source, then paste into
2835  // an editor that has line numbers, to get to the ERROR line
2836  *fragmentSource = CompleteCode[SHADERPART_FRAGMENT]; //original_fragment; //fs;
2837  *vertexSource = CompleteCode[SHADERPART_VERTEX]; //original_vertex; //vs;
2838  return retval;
2839 
2840 }
2841 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< END MIT, VOLUME RENDERING
Definition: Vector.h:36