FreeWRL/FreeX3D  3.0.0
Component_ProgrammableShaders.c
1 /*
2 
3 
4 X3D Programmable Shaders Component
5 
6 */
7 
8 
9 /****************************************************************************
10  This file is part of the FreeWRL/FreeX3D Distribution.
11 
12  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
13 
14  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
15  it under the terms of the GNU Lesser Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  GNU General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
26 ****************************************************************************/
27 
28 
29 
30 /* Mapping X3D types to shaders
31 
32 Notes:
33  If the shader variable is not defined AND used in the shader, you will get an error on initialization
34  via X3D. Even if it is defined as a Uniform variable, if it does not exist in the shader, it will not
35  be able to be initialized, and thus the shader interface will return an error.
36 
37 X3D type GLSL type Initialize Route In Route Out
38 -------------------------------------------------------------------------------------------------
39 FIELDTYPE_SFFloat GL_FLOAT YES YES
40 FIELDTYPE_MFFloat GL_FLOAT YES YES
41 FIELDTYPE_SFRotation GL_FLOAT_VEC4 YES YES
42 FIELDTYPE_MFRotation GL_FLOAT_VEC4 YES YES
43 FIELDTYPE_SFVec3f GL_FLOAT_VEC3 YES YES
44 FIELDTYPE_MFVec3f GL_FLOAT_VEC3 YES YES
45 FIELDTYPE_SFBool GL_BOOL YES YES
46 FIELDTYPE_MFBool GL_BOOL YES YES
47 FIELDTYPE_SFInt32 GL_INT YES YES
48 FIELDTYPE_MFInt32 GL_INT YES YES
49 FIELDTYPE_SFNode
50 FIELDTYPE_MFNode --
51 FIELDTYPE_SFColor GL_FLOAT_VEC3 YES YES
52 FIELDTYPE_MFColor GL_FLOAT_VEC3 YES YES
53 FIELDTYPE_SFColorRGBA GL_FLOAT_VEC4 YES YES
54 FIELDTYPE_MFColorRGBA GL_FLOAT_VEC4 YES YES
55 FIELDTYPE_SFTime GL_FLOAT YES(float) YES(float)
56 FIELDTYPE_MFTime
57 FIELDTYPE_SFString --
58 FIELDTYPE_MFString --
59 FIELDTYPE_SFVec2f GL_FLOAT_VEC2 YES YES
60 FIELDTYPE_MFVec2f GL_FLOAT_VEC2 YES YES
61 FIELDTYPE_SFImage
62 FIELDTYPE_FreeWRLPTR --
63 FIELDTYPE_SFVec3d GL_FLOAT_VEC3 YES(float) YES(float)
64 FIELDTYPE_MFVec3d
65 FIELDTYPE_SFDouble GL_FLOAT YES(float) YES(float)
66 FIELDTYPE_MFDouble
67 FIELDTYPE_SFMatrix3f
68 FIELDTYPE_MFMatrix3f
69 FIELDTYPE_SFMatrix3d
70 FIELDTYPE_MFMatrix3d
71 FIELDTYPE_SFMatrix4f
72 FIELDTYPE_MFMatrix4f
73 FIELDTYPE_SFMatrix4d
74 FIELDTYPE_MFMatrix4d
75 FIELDTYPE_SFVec2d GL_FLOAT_2 YES(float) YES(float)
76 FIELDTYPE_MFVec2d
77 FIELDTYPE_SFVec4f GL_FLOAT_VEC4 YES YES
78 FIELDTYPE_MFVec4f
79 FIELDTYPE_SFVec4d GL_FLOAT_VEC4 YES(float) YES(float)
80 FIELDTYPE_MFVec4d
81 */
82 
83 #include <config.h>
84 #include <system.h>
85 #include <display.h>
86 #include <internal.h>
87 
88 #include <libFreeWRL.h>
89 
90 #include "../vrml_parser/Structs.h"
91 #include "../vrml_parser/CRoutes.h"
92 #include "../main/headers.h"
93 #include "../vrml_parser/CParseGeneral.h"
94 #include "../lib/scenegraph/Vector.h"
95 
96 #include "../world_script/JScript.h"
97 #include "../world_script/CScripts.h"
98 #include "../vrml_parser/CFieldDecls.h"
99 #include "../opengl/OpenGL_Utils.h"
100 #include "../scenegraph/Component_Shape.h"
101 #include "../opengl/Textures.h"
102 #include "Component_ProgrammableShaders.h"
103 #include "../scenegraph/RenderFuncs.h"
104 
105 
106 
107 #define MAX_EFFECTS 32
109  Stack *effect_stack;
110  int effectCount;
111 
113 void *Component_ProgrammableShaders_constructor(){
114  void *v = MALLOCV(sizeof(struct pComponent_ProgrammableShaders));
115  memset(v,0,sizeof(struct pComponent_ProgrammableShaders));
116  return v;
117 }
118 void Component_ProgrammableShaders_init(struct tComponent_ProgrammableShaders *t){
119  //public
120  //private
121  t->prv = Component_ProgrammableShaders_constructor();
122  {
124  p->effect_stack = newStack(struct X3D_Node*);
125  p->effectCount = 0;
126  }
127 }
128 void Component_ProgrammableShaders_clear(struct tComponent_ProgrammableShaders *t){
129  //public
131 
132  deleteVector(struct X3D_Node*,p->effect_stack);
133 }
134 
135 
136 
137 
138 /* we do support older versions of shaders; but not all info logs are printed if we
139  have OpenGL prior to 2.0 */
140 
141 #define SUPPORT_GLSL_ONLY \
142  if (strcmp(node->language->strptr,"GLSL")) { \
143  ConsoleMessage ("Shaders: support only GLSL shading language, got :%s:, skipping...",node->language->strptr); \
144  node->isValid = FALSE; \
145  }
146 
147 // local structure for passing args to threaded shader compiler functions.
148 struct myArgs {
149  struct X3D_Node *node;
150  ttglobal tg;
151 };
152 
153 
154 
155 #define LOCATE_SHADER_PARTS(myNodeType, myField) \
156  for (i=0; i<node->myField.n; i++) { \
157  struct X3D_##myNodeType *prog; \
158  prog = (struct X3D_##myNodeType *) node->myField.p[i]; \
159  vertShaderSource[i] = NULL; \
160  fragShaderSource[i] = NULL; \
161  \
162  if (prog!=NULL) { \
163  if (prog->_nodeType == NODE_##myNodeType) { \
164  /* compile this program */ \
165  \
166  if (!((strcmp (prog->type->strptr,"VERTEX")) && (strcmp(prog->type->strptr,"FRAGMENT")))) { \
167  char *myText = NULL; /* pointer to text to send in */ \
168  char *cptr; /* returned caracter pointer pointer */ \
169  \
170  cptr = prog->url.p[0]->strptr; /*shader_initCodeFromMFUri(&prog->url);*/ \
171  if (cptr == NULL) { \
172  ConsoleMessage ("error reading url for :%s:",stringNodeType(NODE_##myNodeType)); \
173  myText = "";\
174  } else { myText = cptr; \
175 \
176  /* assign this text to VERTEX or FRAGMENT buffers */ \
177  if (!strcmp(prog->type->strptr,"VERTEX")) { \
178  vertShaderSource[i] = STRDUP(myText); \
179  haveVertShaderText = TRUE; \
180  } else { \
181  fragShaderSource[i] = STRDUP(myText); \
182  haveFragShaderText = TRUE; \
183  } \
184  /* printf ("Shader text for type %s is %s\n",prog->type->strptr,myText); */ \
185  /*FREE_IF_NZ(cptr);*/ }\
186  } else { \
187  ConsoleMessage ("%s, invalid Type, got \"%s\"",stringNodeType(NODE_##myNodeType), prog->type->strptr); \
188  node->isValid = FALSE; \
189  } \
190  } else { \
191  ConsoleMessage ("Shader, expected \"%s\", got \"%s\"",stringNodeType(NODE_##myNodeType), stringNodeType(prog->_nodeType)); \
192  node->isValid = FALSE; \
193  } \
194  } \
195  }
196 
197 
198 /* do type checking of shader and field variables when initializing interface */
199 static int shader_checkType(struct FieldDecl * myField,
200  GLuint myShader, GLint myUniform, char *namePtr) {
201  int retval = FALSE;
202 
203  /* check the type, if we are OpenGL 2.0 or above */
204 
205  GLsizei len = 0;
206  GLint size = 0;
207  GLenum type = 0;
208  GLchar ch[100];
209 
210  retval = FALSE;
211  ch[0] = '\0';
212  {
213  int i;
214  int gp;
215  glGetProgramiv(myShader,GL_ACTIVE_UNIFORMS,&gp);
216  //ConsoleMessage ("in shader %d, we have %d uniforms, looking for name :%s:",myShader,gp,namePtr);
217  for (i=0; i<gp; i++) {
218  glGetActiveUniform(myShader,i,(GLsizei)90,&len,&size,&type,ch);
219  //ConsoleMessage(" ....Uniform %d is name :%s: len %d size %d type %d",i,ch,len,size,type);
220  if (strcmp(ch,namePtr)==0) {
221  //ConsoleMessage ("names match, breaking");
222  break;
223  }
224  }
225  }
226  glGetActiveUniform(myShader,myUniform,(GLsizei)90,&len,&size,&type,ch);
227 
228  //printf ("glGetActiveUniform for myShader %d, myVar %d, len %d size %d type %x ch %s\n",
229  //myShader,myUniform, len, size,type, ch);
230 
231  /* verify that the X3D fieldType matches the Shader type */
232  switch (fieldDecl_getType(myField)) {
233  case FIELDTYPE_SFFloat: retval = type == GL_FLOAT; break;
234  case FIELDTYPE_MFFloat: retval = type == GL_FLOAT; break;
235  case FIELDTYPE_SFRotation: retval = type == GL_FLOAT_VEC4; break;
236  case FIELDTYPE_MFRotation: retval = type == GL_FLOAT_VEC4; break;
237  case FIELDTYPE_SFVec3f: retval = type == GL_FLOAT_VEC3; break;
238  case FIELDTYPE_MFVec3f: retval = type == GL_FLOAT_VEC3; break;
239  case FIELDTYPE_MFInt32:
240  case FIELDTYPE_SFInt32: retval = type == GL_INT; break;
241  case FIELDTYPE_MFBool:
242  case FIELDTYPE_SFBool: retval = type == GL_BOOL; break;
243  case FIELDTYPE_SFNode: break;
244  case FIELDTYPE_MFNode: break;
245  case FIELDTYPE_SFColor: retval = type == GL_FLOAT_VEC3; break;
246  case FIELDTYPE_MFColor: retval = type == GL_FLOAT_VEC3; break;
247  case FIELDTYPE_SFColorRGBA: retval = type == GL_FLOAT_VEC4; break;
248  case FIELDTYPE_MFColorRGBA: retval = type == GL_FLOAT_VEC4; break;
249  case FIELDTYPE_SFTime: retval = type == GL_FLOAT; break;
250  case FIELDTYPE_MFTime: break;
251  case FIELDTYPE_SFString: break;
252  case FIELDTYPE_MFString: break;
253  case FIELDTYPE_SFVec2f: retval = type == GL_FLOAT_VEC2; break;
254  case FIELDTYPE_MFVec2f: retval = type == GL_FLOAT_VEC2; break;
255  case FIELDTYPE_SFImage: break;
256  case FIELDTYPE_FreeWRLPTR: break;
257  case FIELDTYPE_SFVec3d: retval = type == GL_FLOAT_VEC3; break;
258  case FIELDTYPE_MFVec3d: break;
259  case FIELDTYPE_SFDouble: retval = type == GL_FLOAT; break;
260  case FIELDTYPE_MFDouble: break;
261  case FIELDTYPE_SFMatrix3f: break;
262  case FIELDTYPE_MFMatrix3f: break;
263  case FIELDTYPE_SFMatrix3d: break;
264  case FIELDTYPE_MFMatrix3d: break;
265  case FIELDTYPE_SFMatrix4f: break;
266  case FIELDTYPE_MFMatrix4f: break;
267  case FIELDTYPE_SFMatrix4d: break;
268  case FIELDTYPE_MFMatrix4d: break;
269  case FIELDTYPE_SFVec2d: retval = type == GL_FLOAT_VEC2; break;
270  case FIELDTYPE_MFVec2d: break;
271  case FIELDTYPE_SFVec4f: retval = type == GL_FLOAT_VEC4; break;
272  case FIELDTYPE_MFVec4f: break;
273  case FIELDTYPE_SFVec4d: retval = type == GL_FLOAT_VEC4; break;
274  case FIELDTYPE_MFVec4d: break;
275  }
276 
277  /* did we have an error? */
278 
279  if (!retval) {
280  ConsoleMessage ("Shader type check: X3D type and shader type not compatible for variable :%s:",ch);
281 #define VERBOSE
282 #ifdef VERBOSE
283  printf ("shaderCheck mode %d (%s) type %d (%s) name %d\n",fieldDecl_getAccessType(myField),
284  stringPROTOKeywordType(fieldDecl_getAccessType(myField)),
285  fieldDecl_getType(myField), stringFieldtypeType(fieldDecl_getType(myField)),
286  fieldDecl_getIndexName(myField));
287 
288  printf ("len %d size %d type %d ch %s\n",len,size,type,ch);
289  switch (type) {
290 
291  case GL_FLOAT: printf ("GL_FLOAT\n"); break;
292  case GL_FLOAT_VEC2: printf ("GL_FLOAT_VEC2\n"); break;
293  case GL_FLOAT_VEC3: printf ("GL_FLOAT_VEC3\n"); break;
294  case GL_FLOAT_VEC4: printf ("GL_FLOAT_VEC4\n"); break;
295  case GL_INT: printf ("GL_INT\n"); break;
296  case GL_INT_VEC2: printf ("GL_INT_VEC2\n"); break;
297  case GL_INT_VEC3: printf ("GL_INT_VEC3\n"); break;
298  case GL_INT_VEC4: printf ("GL_INT_VEC4\n"); break;
299  case GL_BOOL: printf ("GL_BOOL\n"); break;
300  case GL_BOOL_VEC2: printf ("GL_BOOL_VEC2\n"); break;
301  case GL_BOOL_VEC3: printf ("GL_BOOL_VEC3\n"); break;
302  case GL_BOOL_VEC4: printf ("GL_BOOL_VEC4\n"); break;
303  case GL_FLOAT_MAT2: printf ("GL_FLOAT_MAT2\n"); break;
304  case GL_FLOAT_MAT3: printf ("GL_FLOAT_MAT3\n"); break;
305  case GL_FLOAT_MAT4: printf ("GL_FLOAT_MAT4\n"); break;
306 /*
307  case GL_FLOAT_MAT2x3: printf ("GL_FLOAT_MAT2x3\n"); break;
308  case GL_FLOAT_MAT2x4: printf ("GL_FLOAT_MAT2x4\n"); break;
309  case GL_FLOAT_MAT3x2: printf ("GL_FLOAT_MAT3x2\n"); break;
310  case GL_FLOAT_MAT3x4: printf ("GL_FLOAT_MAT3x4\n"); break;
311  case GL_FLOAT_MAT4x2: printf ("GL_FLOAT_MAT4x2\n"); break;
312  case GL_FLOAT_MAT4x3: printf ("GL_FLOAT_MAT4x3\n"); break;
313  case GL_SAMPLER_1D: printf ("GL_SAMPLER_1D\n"); break;
314  case GL_SAMPLER_3D: printf ("GL_SAMPLER_3D\n"); break;
315  case GL_SAMPLER_1D_SHADOW: printf ("GL_SAMPLER_1D_SHADOW\n"); break;
316  case GL_SAMPLER_2D_SHADOW: printf ("GL_SAMPLER_2D_SHADOW\n"); break;
317 */
318  case GL_SAMPLER_2D: printf ("GL_SAMPLER_2D\n"); break;
319  case GL_SAMPLER_CUBE: printf ("GL_SAMPLER_CUBE\n"); break;
320 default :{printf ("not decoded yet, probably a matrix type\n");}
321  }
322 #endif
323  }
324  return retval;
325 }
326 #undef VERBOSE
327 
328 
329 /* fieldDecl_getshaderVariableID(myf), fieldDecl_getValue(myf)); */
330 static void sendValueToShader(struct ScriptFieldDecl* myField) {
331  GLint shaderVariable = fieldDecl_getshaderVariableID(myField->fieldDecl);
332 
333  #ifdef SHADERVERBOSE
334  printf ("sendValueToShader... ft %s\n",stringFieldtypeType(fieldDecl_getType(myField->fieldDecl)));
335  printf ("shaderVariableID is %d\n",shaderVariable);
336  #endif
337 
338  /* either not defined in the shader, OR not used in the shader so it is stripped by glsl compiler */
339  if (shaderVariable == INT_ID_UNDEFINED) return;
340 
341 
342  switch (fieldDecl_getType(myField->fieldDecl)) {
343 
344 #define SF_FLOATS_TO_SHADER(ttt,ty1,ty2) \
345  case FIELDTYPE_SF##ty1: \
346  GLUNIFORM##ttt##FV(shaderVariable, 1, myField->value.sf##ty2.c); \
347  break;
348 
349 #define SF_DOUBLES_TO_SHADER(ttt,ty1,ty2) \
350  case FIELDTYPE_SF##ty1: {float val[4]; int i; \
351  for (i=0; i<ttt; i++) { val[i] = (float) (myField->value.sf##ty2.c[i]); } \
352  GLUNIFORM##ttt##FV(shaderVariable, 1, val); \
353  break; }
354 
355 #define SF_FLOAT_TO_SHADER(ty1,ty2) \
356  case FIELDTYPE_SF##ty1: \
357  GLUNIFORM1F(shaderVariable, myField->value.sf##ty2); \
358  break;
359 
360 #define SF_DOUBLE_TO_SHADER(ty1,ty2) \
361  case FIELDTYPE_SF##ty1: {float val = myField->value.sf##ty2; \
362  GLUNIFORM1F(shaderVariable, val); \
363  break; }
364 
365 #define MF_FLOATS_TO_SHADER(ttt,ty1,ty2) \
366  case FIELDTYPE_MF##ty1: \
367  GLUNIFORM##ttt##FV(shaderVariable, myField->value.mf##ty2.n, (float *)myField->value.mf##ty2.p); \
368  break;
369 
370 
371 #define SF_INTS_TO_SHADER(ty1,ty2) \
372  case FIELDTYPE_SF##ty1: \
373  GLUNIFORM1I(shaderVariable, myField->value.sf##ty2); \
374  break;
375 
376 #define MF_INTS_TO_SHADER(ty1,ty2) \
377  case FIELDTYPE_MF##ty1: \
378  GLUNIFORM1IV(shaderVariable, (GLsizei) myField->value.mf##ty2.n, (const GLint *)myField->value.mf##ty2.p); \
379  break;
380 
381 
382  SF_FLOAT_TO_SHADER(Float,float)
383  SF_DOUBLE_TO_SHADER(Double,float)
384  SF_DOUBLE_TO_SHADER(Time,float)
385 
386  SF_FLOATS_TO_SHADER(2,Vec2f,vec2f)
387  SF_FLOATS_TO_SHADER(3,Vec3f,vec3f)
388  SF_FLOATS_TO_SHADER(3,Color,color)
389  SF_FLOATS_TO_SHADER(4,ColorRGBA,colorrgba)
390  SF_FLOATS_TO_SHADER(4,Rotation,rotation)
391  SF_FLOATS_TO_SHADER(4,Vec4f,vec4f)
392  SF_DOUBLES_TO_SHADER(2,Vec2d, vec2d)
393  SF_DOUBLES_TO_SHADER(3,Vec3d, vec3d)
394  SF_DOUBLES_TO_SHADER(4,Vec4d, vec4d)
395 
396  MF_FLOATS_TO_SHADER(1,Float,float)
397 
398  MF_FLOATS_TO_SHADER(2,Vec2f,vec2f)
399  MF_FLOATS_TO_SHADER(3,Color,color)
400  MF_FLOATS_TO_SHADER(3,Vec3f,vec3f)
401  MF_FLOATS_TO_SHADER(4,ColorRGBA,colorrgba)
402  MF_FLOATS_TO_SHADER(4,Rotation,rotation)
403 
404  SF_INTS_TO_SHADER(Bool,bool)
405  SF_INTS_TO_SHADER(Int32,int32)
406  MF_INTS_TO_SHADER(Bool,bool)
407  MF_INTS_TO_SHADER(Int32,int32)
408 
409 
410  //MF_FLOATS_TO_SHADER(4,Vec4f,vec4f)
411 
412  //SF_VECS_TO_SHADER(9,Matrix3f, matrix3f)
413  //SF_VECS_TO_SHADER(16,Matrix4f, matrix4f)
414 
415  case FIELDTYPE_SFNode:
416  case FIELDTYPE_SFImage:
417  case FIELDTYPE_FreeWRLPTR:
418  case FIELDTYPE_SFString:
419  case FIELDTYPE_SFMatrix3d:
420  case FIELDTYPE_SFMatrix4d:
421 
422 
423  case FIELDTYPE_MFNode:
424  case FIELDTYPE_MFTime:
425  case FIELDTYPE_MFString:
426  case FIELDTYPE_MFDouble:
427  case FIELDTYPE_MFVec3d:
428  case FIELDTYPE_MFMatrix3f:
429  case FIELDTYPE_MFMatrix3d:
430  case FIELDTYPE_MFMatrix4f:
431  case FIELDTYPE_MFMatrix4d:
432  case FIELDTYPE_MFVec2d:
433  case FIELDTYPE_MFVec4d:
434  default : printf ("can not send a shader variable of %s yet\n",stringFieldtypeType(fieldDecl_getType(myField->fieldDecl)));
435  }
436 }
437 
438 /* Routing - sending a value to a shader - we get passed the routing table entry number
439 Note: Effect and EffectPart do not route-update their uniforms here.
440 Reason: Effect/EffectPart can be composed into many compiled base shader permutations,
441  so they are updated from fieldvalues in child_shape
442 more...
443 2016 - added Effect and EffectPart to our bifurcated system of shaders:
444 1. ubershader
445 1a. base shaders - normal shaders for normal rendering of appearance, no shader nodes of any type involved
446  - mostly does in GLES2 what desktop opengl 3+ does, except
447  -- shader permutations are formed by what what gl features are needed for each Appearance
448  -- Effect plug stubs are pre-positioned
449  - there's no way to directly route to base shaders, so no route-updating done here
450 1b. Effect/EffectPart nodes - new in 2016, makes base shaders + effects 'composable' into shader permutations
451  - not in web3d specs, although being discussed for future spec versions ie 4+
452  - Appearance m:1 compiled shader 1:1 base shader 1:m Effect/EffectPart
453  - compiled shader permutations are cached so if another Shape needs the same permutation, it re-uses the compiled
454  Appearance m:1 compiled_shader
455  - and when an Effect is on the transform stack instead of in Appearance scope,
456  then it gets composed into multiple shaders:
457  specific-Effect/EffectPart 1:m Appearance / compiled shader
458  therefore routing to an Effect/EffectPart would/could require setting uniforms in many compiled shaders
459  so updating uniforms in response to route-updating an Effect field is done per shape/appearance scope
460  in child_shape() {... update_effect_uniforms(); ...}
461 1c. VolumeRendering component uses a separate set of base shaders with no EffectPlugs, but with permutations
462  - no way to directly route to underlying shaders, so route-updating of uniforms not done here
463 
464 2. user shaders: web3d specs Programmable Shadeers component
465  http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/shaders.html
466  user shader 1:1 compiled shader 1:1 Appearance 1:m Shape
467  a user shader replaces the entire base shader+effect in Appearance
468  if you route-update a field on a user shader, you only need to find one instance of the compiled shader
469  and update the uniform in that compiled shader
470  H: you can cache the compiled shader number in the user shader node (unconfirmed)
471  H: you can cache uniform variable IDs / offsets / compiled-shader-uniform-location
472  in the user-shader-node user-field, for faster access
473  uniform_location = fieldDecl_getshaderVariableID(...)
474  first time using the compiled shader in child_shape,
475  you can check shader._initialized and if FALSE, update all the uniforms
476  and set _initialized = TRUE
477 
478 */
479 void getField_ToShader(struct X3D_Node *node, int toOffset, union anyVrml *toAny, int type) {
480  // update the compiled shader uniform when routing to a user shader
481  struct Shader_Script *myObj[2];
482  int numObjs = 1;
483  int to_counter;
484  int fromFieldID;
485  struct Vector* parents;
486  int i,j;
487  GLfloat* sourceData;
488  GLuint currentShader = 0;
489  shaderflagsstruct shaderflags;
490  struct CRStruct *CRoutes = getCRoutes();
491  struct CRjsnameStruct *JSparamnames = getJSparamnames();
492 
493  memset(&shaderflags,0,sizeof(shaderflagsstruct));
494 
495  // ProgramShaders have fields for each ShaderProgram field, and we can have a couple of fields
496  // here. Thus myObj* has more than one pointer.
497 
498  // use the currently running shader
499  //ConsoleMessage ("getFieldToShader, node %s, num %d",stringNodeType(node->_nodeType),num);
500  //ConsoleMessage ("nodes have %d parents",vectorSize(node->_parentVector));
501  parents = node->_parentVector;
502  i = 0;
503  while(i < vectorSize(parents)){
504  //for (i=0; i<vectorSize(node->_parentVector); i++) {
505  struct X3D_Appearance *ap = vector_get(struct X3D_Appearance *,parents, i);
506  //ConsoleMessage ("and, parent is type %s",stringNodeType(ap->_nodeType));
507  if( ap->_nodeType == NODE_Proto) ap = vector_get(struct X3D_Appearance *,ap->_parentVector, 0);
508  if (ap->_nodeType == NODE_Appearance) {
509  for (j=0; j<vectorSize(ap->_parentVector); j++) {
510  struct X3D_Shape *sh = vector_get(struct X3D_Shape *, ap->_parentVector, j);
511  //ConsoleMessage ("and parent of appearance is %s",stringNodeType(sh->_nodeType));
512  if (sh->_nodeType == NODE_Shape) {
513  //currentShader = X3D_SHAPE(sh)->_shaderflags_usershaders; //_shaderTableEntry;
514  shaderflags.base = sh->_shaderflags_base;
515  shaderflags.effects = sh->_shaderflags_effects;
516  shaderflags.usershaders = sh->_shaderflags_usershaders;
517  }
518  }
519  }
520  i++;
521  if(ap->_nodeType == NODE_ProgramShader){
522  //need to go up one more level
523  parents = ap->_parentVector;
524  i = 0;
525  }
526  }
527 
528  //if (currentShader == 0) {
529  if(!shaderflags.base && !shaderflags.usershaders){
530  ConsoleMessage("."); //loading
531  //ConsoleMessage ("%s","error finding associated Shape node for Shade node");
532  return;
533  }
534 
535  // turning shader on...
536  //ConsoleMessage ("calling getMyShader here wrwe");
537  //shaderflags.usershaders = currentShader;
538  enableGlobalShader(getMyShaders(shaderflags)); //currentShader));
539 
540  myObj[0] = NULL;
541  myObj[1] = NULL;
542 
544  //for (to_counter = 0; to_counter < CRoutes[num].tonode_count; to_counter++) {
545  // CRnodeStruct *to_ptr = NULL;
546 
547  // to_ptr = &(CRoutes[num].tonodes[to_counter]);
548  // fromFieldID = to_ptr->foffset;
549  // //printf ("getField_ToShader, num %d, foffset %d to a %s\n",num,fromFieldID,stringNodeType(to_ptr->routeToNode->_nodeType));
550 
551  //switch (to_ptr->routeToNode->_nodeType) {
552  numObjs = 1;
553  switch(node->_nodeType){
554  case NODE_ComposedShader:
555  myObj[0] = (struct Shader_Script *)(X3D_COMPOSEDSHADER(node)->_shaderUserDefinedFields);
556  break;
557  //case NODE_Effect:
558  // myObj[0] = (struct Shader_Script *)(X3D_EFFECT(node)->_shaderUserDefinedFields);
559  // break;
560  case NODE_PackagedShader:
561  myObj[0] = (struct Shader_Script *)(X3D_PACKAGEDSHADER(node)->_shaderUserDefinedFields);
562  break;
563  case NODE_ProgramShader:{
564  //feb 2015, dug9: I don't think we should be routing to ProgramShader, rather directly to its contained ShaderPrograms
565  int i;
566  for (i=0; i<X3D_PROGRAMSHADER(node)->programs.n; i++) {
567  struct X3D_ShaderProgram *ps = X3D_SHADERPROGRAM(X3D_PROGRAMSHADER(node)->programs.p[i]);
568  // trying this Hopefully we only have a Fragment and a Vertex
569  if (i<2) {
570  myObj[i] = (struct Shader_Script *)ps->_shaderUserDefinedFields;
571  numObjs = i;
572  }
573  }
574  break;}
575  case NODE_ShaderProgram:
576  //feb 2015, dug9: new - I think we should route here
577  myObj[0] = (struct Shader_Script *)(X3D_SHADERPROGRAM(node)->_shaderUserDefinedFields);
578  break;
579  default: {
580  ConsoleMessage ("getField_ToShader, unhandled type??");
581  return;
582  }
583  }
584  /* we have the struct Shader_Script; go through the fields and find the correct one */
585 
586 
587  /*
588  printf ("Shader_Script has node of %u ",myObj->ShaderScriptNode);
589  printf ("of type %s ",stringNodeType(myObj->ShaderScriptNode->_nodeType));
590  printf ("and has %d as a vector size ",vectorSize(myObj->fields));
591  if (myObj->loaded) printf ("locked and loaded "); else printf ("needs loading, I guess ");
592  printf ("\n");
593  */
594 
595  /* is there any fields? */
596  if (myObj[0] == NULL) return;
597 
598  /* this script should be loaded... if not, wait until it is */
599  for (i=0; i<numObjs; i++) {
600  if (!myObj[i]->loaded) {
601  /* ConsoleMessage ("ShaderProgram should be loaded, hmmm"); */
602  return;
603  }
604  }
605 
606  //printf ("going through fields.... have %d fields\n",vectorSize(myObj->fields));
607  for (j=0; j<numObjs; j++) {
608  struct ScriptFieldDecl* toField;
609  toField = vector_get(struct ScriptFieldDecl*, myObj[j]->fields, toOffset);
610  fromFieldID = fieldDecl_getshaderVariableID(toField->fieldDecl);
611 
612  for(i=0; i!=vectorSize(myObj[j]->fields); ++i) {
613  GLint shaderVariable;
614  struct ScriptFieldDecl* curField;
615  struct FieldDecl * myf;
616 
617  /* initialization */
618  curField = vector_get(struct ScriptFieldDecl*, myObj[j]->fields, i);
619  myf = curField->fieldDecl;
620  shaderVariable = fieldDecl_getshaderVariableID(myf);
621 
622  //printf ("for field %d, shaderVariable %d\n",i,shaderVariable);
623 
624 
625  //printf ("curField %d name %d type %d ",i,
626  // fieldDecl_getIndexName(myf), fieldDecl_getType(myf));
627  //printf ("fieldDecl mode %d (%s) type %d (%s) name %d\n",
628  // fieldDecl_getAccessType(myf),
629  // stringPROTOKeywordType(fieldDecl_getAccessType(myf)),
630  // fieldDecl_getType(myf), stringFieldtypeType(fieldDecl_getType(myf)),
631  // fieldDecl_getIndexName(myf));
632  //printf ("comparing fromFieldID %d and name %d\n",fromFieldID, fieldDecl_getIndexName(myf));
633  //printf (" types %d, %d\n",JSparamnames[fromFieldID].type,fieldDecl_getType(myf));
634  //printf (" shader ascii name is %s\n",fieldDecl_getShaderScriptName(curField->fieldDecl));
635 
636 
637 
638  if (fromFieldID == fieldDecl_getShaderScriptIndex(myf)) {
639 
640  //printf (" field match, %d==%d\n",fromFieldID, fieldDecl_getIndexName(myf));
641  //printf (" types %d, %d\n",JSparamnames[fromFieldID].type,fieldDecl_getType(myf));
642  //printf (" shaderVariableID is %d\n",fieldDecl_getShaderVariableID(myf));
643 
644 
645 
646  /* ok, here we have the Shader_Script, the field offset, and the entry */
647 
648  //sourceData = offsetPointer_deref(GLfloat *,CRoutes[num].routeFromNode, CRoutes[num].fnptr);
649  sourceData = &toAny->sffloat;
650  //printf("[[%f]]",*sourceData);
651 
652 #define ROUTE_SF_FLOAT_TO_SHADER(ty1) \
653  case FIELDTYPE_SF##ty1: \
654  GLUNIFORM1F(shaderVariable, *((float*)sourceData)); \
655  break;
656 
657 #define ROUTE_SF_DOUBLE_TO_SHADER(ty1) \
658  case FIELDTYPE_SF##ty1: {float val = (float) *((double *)sourceData); \
659  GLUNIFORM1F(shaderVariable, val); \
660  break; }
661 
662 #define ROUTE_SF_INTS_TO_SHADER(ty1) \
663  case FIELDTYPE_SF##ty1: \
664  GLUNIFORM1I(shaderVariable, *((int*)sourceData)); \
665  break;
666 
667 #define ROUTE_SF_FLOATS_TO_SHADER(ttt,ty1) \
668  case FIELDTYPE_SF##ty1: \
669  GLUNIFORM##ttt##FV(shaderVariable, 1, (float*)sourceData); \
670  break;
671 
672 #define ROUTE_SF_DOUBLES_TO_SHADER(ttt,ty1) \
673  case FIELDTYPE_SF##ty1: {float val[4]; int i; double *fp = (double*)sourceData; \
674  for (i=0; i<ttt; i++) { val[i] = (float) (*fp); fp++; } \
675  GLUNIFORM##ttt##FV(shaderVariable, 1, val); \
676  break; }
677 
678 
679 #define ROUTE_MF_FLOATS_TO_SHADER(ttt,ty1) \
680  case FIELDTYPE_MF##ty1: { struct Multi_##ty1 *sd = (struct Multi_##ty1*) sourceData; \
681  printf ("MF_FLOATS_TO_SHADER, sv %d, sd->n %d\n",shaderVariable,sd->n); \
682  GLUNIFORM##ttt##FV(shaderVariable, sd->n, (const GLfloat *)sd->p); \
683  break; }
684 
685 #define ROUTE_MF_INTS_TO_SHADER(ttt,ty1) \
686  case FIELDTYPE_MF##ty1: { struct Multi_##ty1 *sd = (struct Multi_##ty1*) sourceData; \
687  GLUNIFORM##ttt##IV(shaderVariable, sd->n, (const GLint *)sd->p); \
688  break; }
689 
690 
691 
692  /* send in the correct parameters */
693  switch (JSparamnames[fromFieldID].type) {
694  ROUTE_SF_FLOAT_TO_SHADER(Float)
695  ROUTE_SF_DOUBLE_TO_SHADER(Double)
696  ROUTE_SF_DOUBLE_TO_SHADER(Time)
697  ROUTE_SF_INTS_TO_SHADER(Bool)
698  ROUTE_SF_INTS_TO_SHADER(Int32)
699 
700  ROUTE_SF_FLOATS_TO_SHADER(2,Vec2f)
701  ROUTE_SF_FLOATS_TO_SHADER(3,Vec3f)
702  ROUTE_SF_FLOATS_TO_SHADER(3,Color)
703  ROUTE_SF_FLOATS_TO_SHADER(4,ColorRGBA)
704  ROUTE_SF_FLOATS_TO_SHADER(4,Rotation)
705  ROUTE_SF_FLOATS_TO_SHADER(4,Vec4f)
706  ROUTE_SF_DOUBLES_TO_SHADER(2,Vec2d)
707  ROUTE_SF_DOUBLES_TO_SHADER(3,Vec3d)
708  ROUTE_SF_DOUBLES_TO_SHADER(4,Vec4d)
709 
710  ROUTE_MF_FLOATS_TO_SHADER(1,Float)
711  ROUTE_MF_FLOATS_TO_SHADER(2,Vec2f)
712  ROUTE_MF_FLOATS_TO_SHADER(3,Color)
713  ROUTE_MF_FLOATS_TO_SHADER(3,Vec3f)
714  ROUTE_MF_FLOATS_TO_SHADER(4,ColorRGBA)
715  ROUTE_MF_FLOATS_TO_SHADER(4,Rotation)
716 
717  ROUTE_MF_INTS_TO_SHADER(1,Bool)
718  ROUTE_MF_INTS_TO_SHADER(1,Int32)
719 
720 
721 
722  case FIELDTYPE_SFNode:
723  case FIELDTYPE_MFNode:
724  case FIELDTYPE_MFTime:
725  case FIELDTYPE_SFString:
726  case FIELDTYPE_MFString:
727  case FIELDTYPE_SFImage:
728  case FIELDTYPE_FreeWRLPTR:
729  case FIELDTYPE_MFVec3d:
730  case FIELDTYPE_MFDouble:
731  case FIELDTYPE_SFMatrix3f:
732  case FIELDTYPE_MFMatrix3f:
733  case FIELDTYPE_SFMatrix3d:
734  case FIELDTYPE_MFMatrix3d:
735  case FIELDTYPE_SFMatrix4f:
736  case FIELDTYPE_MFMatrix4f:
737  case FIELDTYPE_SFMatrix4d:
738  case FIELDTYPE_MFMatrix4d:
739  case FIELDTYPE_MFVec2d:
740  case FIELDTYPE_MFVec4d:
741  ConsoleMessage ("shader field type %s not routable yet",stringFieldtypeType(JSparamnames[fromFieldID].type));
742  break;
743  default: {
744  ConsoleMessage ("shader field type %s not routable yet",stringFieldtypeType(JSparamnames[fromFieldID].type));
745  }
746  }
747  }
748  }
749  }
750  finishedWithGlobalShader();
751  //}
752 }
753 
754 
755 /* send fields to a shader; expect either a ShaderProgram, or a ComposedShader */
756 static void send_fieldToShader (GLuint myShader, struct X3D_Node *node) {
757  size_t i;
758 
759  struct Shader_Script* me = NULL;
760  struct CRjsnameStruct *JSparamnames = getJSparamnames();
761 
762  if (node->_nodeType==NODE_ShaderProgram) me = (struct Shader_Script *) X3D_SHADERPROGRAM(node)->_shaderUserDefinedFields;
763  else if (node->_nodeType == NODE_ComposedShader) me = (struct Shader_Script *) X3D_COMPOSEDSHADER(node)->_shaderUserDefinedFields;
764  else if (node->_nodeType == NODE_Effect) me = (struct Shader_Script *) X3D_EFFECT(node)->_shaderUserDefinedFields;
765  else {
766  printf ("send_fieldToShader, expected a ShaderProgram or ComposedShader, got %s\n",
767  stringNodeType(node->_nodeType));
768  return;
769  }
770 
771 
772  #ifdef SHADERVERBOSE
773  printf ("Shader_Script has node of %p ",me->ShaderScriptNode);
774  printf ("of type %s ",stringNodeType(me->ShaderScriptNode->_nodeType));
775  printf ("and has %d as a vector size ",vectorSize(me->fields));
776  if (me->loaded) printf ("locked and loaded "); else printf ("needs loading, I guess ");
777  printf ("\n");
778  #endif
779 
780  /* lets look for, and tie in, textures */
781  /* we make X3D_Texture0 = 0; X3D_Texture1=1, etc */
782  for (i=0; i<MAX_MULTITEXTURE; i++) {
783  char myShaderTextureName[200];
784  GLint myVar;
785 
786  sprintf (myShaderTextureName,"X3D_Texture%d",(int) i);
787  myVar = GET_UNIFORM(myShader,myShaderTextureName);
788  if (myVar != INT_ID_UNDEFINED) {
789  /* printf ("for texture %s, we got %d\n", myShaderTextureName,myVar); */
790  GLUNIFORM1I(myVar,(int) i);
791  }
792  }
793 
794  /* is there any fields? */
795  if (me == NULL) return;
796 
797  /* this script should NOT be loaded... or so we thought but now we have Effects which we route to,
798  and fieldvalues need to be re-sent when they change */
799  //if (me->loaded) ConsoleMessage ("ShaderProgram is flagged as being loaded, hmmm");
800 
801 
802  for(i=0; i!=vectorSize(me->fields); ++i) {
803  GLint myVar;
804  struct ScriptFieldDecl* curField;
805  struct FieldDecl * myf;
806  char *namePtr;
807 
808  /* initialization */
809  myVar = -1;
810  curField = vector_get(struct ScriptFieldDecl*, me->fields, i);
811  myf = curField->fieldDecl;
812  namePtr = fieldDecl_getShaderScriptName(myf);
813 
814 
815 
816  #ifdef SHADERVERBOSE
817  printf ("looking for field name %s...\n",namePtr);
818  printf("fieldDecl mode %d (%s) type %d (%s) name %d\n",myf->PKWmode,
819  stringPROTOKeywordType(myf->PKWmode), myf->fieldType, stringFieldtypeType(myf->fieldType),myf->lexerNameIndex);
820  #endif
821 
822  /* ask the shader for its handle for this variable */
823 
824  /* try Uniform */
825  //printf ("looking to get_Uniform for shader %d, variable :%s:\n",myShader, namePtr);
826  myVar = GET_UNIFORM(myShader,namePtr);
827  //myVar = GET_UNIFORM(myShader,fieldDecl_getShaderScriptName(myf));
828  if (myVar == INT_ID_UNDEFINED) {
829  if (GET_ATTRIB(myShader,fieldDecl_getShaderScriptName(myf)) != INT_ID_UNDEFINED)
830  ConsoleMessage ("Shader variable :%s: is declared as an attribute; we can not do much with this",fieldDecl_getShaderScriptName(myf));
831  else
832  ConsoleMessage ("Shader variable :%s: is either not declared or not used in the shader program",fieldDecl_getShaderScriptName(myf));
833  }
834 
835  /* do the types of the field variable, and the shader variable match? */
836  shader_checkType(myf,myShader,myVar,namePtr);
837 
838 
839  /* save the variable object for this variable */
840  fieldDecl_setshaderVariableID(myf,myVar);
841 
842  if ((fieldDecl_getAccessType(myf)==PKW_initializeOnly) || (fieldDecl_getAccessType(myf)==PKW_inputOutput)) {
843  sendValueToShader(curField);
844  }
845 
846  }
847 
848  /* done the loading of this shader part */
849  me->loaded = TRUE;
850 }
851 #undef SHADERVERBOSE
852 
853 
854 /* on load of shader, send along any initial field values in the X3D file to the Shader */
855 /* we can have shaders like:
856 
857 ComposedShader {
858  field SFFloat blubber 0.5
859  field SFVec3f decis 0.96 0.44 0.22
860  language "GLSL" parts [
861  ShaderPart { type "VERTEX" url "toon.vs" }
862  ShaderPart { type "FRAGMENT" url "toon.fs" }
863  ] }
864 
865 ProgramShader {
866  language "GLSL" programs [
867  ShaderProgram {
868  field SFFloat blubber 0.5
869  type "VERTEX" url "toon.vs" }
870  ShaderProgram {
871  field SFVec3f decis 0.96 0.44 0.22
872  type "FRAGMENT" url "toon.fs" }
873  ] }
874 
875 Note the differing location of the fields...
876 
877 */
878 
879 
880 void sendInitialFieldsToShader(struct X3D_Node * node) {
881  int i;
882  GLuint myShader;
883 
884 
885  myShader = getAppearanceProperties()->currentShaderProperties->myShaderProgram;
886 
887  //ConsoleMessage ("sendInitialFieldsToShader - have to get parents shader id");
888  switch (node->_nodeType) {
889  case NODE_ProgramShader: {
890 
891  /* anything to do here? */
892  for (i=0; i<X3D_PROGRAMSHADER(node)->programs.n; i++) {
893  #ifdef SHADERVERBOSE
894  printf ("ProgramShader, activate %d isSelected %d isValid %d TRUE %d FALSE %d\n",
895  X3D_PROGRAMSHADER(node)->activate,X3D_PROGRAMSHADER(node)->isSelected,
896  X3D_PROGRAMSHADER(node)->isValid, TRUE, FALSE);
897  //printf ("runningShader %d, myShader %d\n",getAppearanceProperties()->currentShader, X3D_PROGRAMSHADER(node)->__shaderIDS.p[0]);
898  #endif
899 
900  struct X3D_ShaderProgram *part = X3D_SHADERPROGRAM(X3D_PROGRAMSHADER(node)->programs.p[i]);
901 
902  #ifdef SHADERVERBOSE
903  printf ("sendInitial, have part %p\n",part);
904  #endif
905 
906  send_fieldToShader(myShader, X3D_NODE(part));
907  }
908  X3D_PROGRAMSHADER(node)->_initialized = TRUE;
909  break;
910  }
911 
912 
913  case NODE_ComposedShader: {
914  /* anything to do here? */
915  send_fieldToShader(myShader, X3D_NODE(node));
916  X3D_COMPOSEDSHADER(node)->_initialized = TRUE;
917  break;
918  }
919  //2017: effects aren't part of usershaders, just the normal shaders
920  //case NODE_Effect: {
921  // /* anything to do here? */
922  // send_fieldToShader(myShader, X3D_NODE(node));
923  // //X3D_EFFECT(node)->_initialized = TRUE;
924  // break;
925  // }
926  }
927 }
928 
929 /* the Shader is now ready for action, tell the associated Shape(s) to
930  recompile */
931 static void tellShapeNodeToRecompile (struct X3D_Node *node) {
932  int i;
933  //ConsoleMessage ("tellShapeNodeToRecompile, node %s",stringNodeType(node->_nodeType));
934 
935  if (node->_nodeType == NODE_Shape) {
936  node->_change++;
937  } else {
938  for (i=0; i<vectorSize(node->_parentVector); i++) {
939  struct X3D_Node * parent = vector_get(struct X3D_Node*, node->_parentVector, i);
940  //ConsoleMessage ("sending update back up to the parent %d, %s",i,stringNodeType(parent->_nodeType));
941  if (parent == NULL) return;
942  tellShapeNodeToRecompile(parent);
943  }
944  }
945 }
946 
947 /*********************************************************************/
948 enum{
949  LOADER_INITIAL_STATE=0,
950  LOADER_REQUEST_RESOURCE,
951  LOADER_FETCHING_RESOURCE,
952  LOADER_PROCESSING,
953  LOADER_LOADED,
954  LOADER_COMPILED,
955  LOADER_STABLE,
956 };
957 
958 static void *thread_compile_ComposedShader(void *args) {
959 
960  struct X3D_ComposedShader *node;
961  ttglobal tg;
962  /* an array of text pointers, should contain shader source */
963  GLchar **vertShaderSource;
964  GLchar **fragShaderSource;
965  int i;
966  struct myArgs *inArgs;
967 
968  /* do we have anything to compile? */
969  int haveVertShaderText;
970  int haveFragShaderText;
971 
972  inArgs = (struct myArgs *) args;
973 
974  node = X3D_COMPOSEDSHADER(inArgs->node);
975  tg = inArgs->tg;
976  FREE_IF_NZ(args);
977 
978  fwl_setCurrentHandle(tg,__FILE__,__LINE__);
979 
980  /* initialization */
981  haveVertShaderText = FALSE;
982  haveFragShaderText = FALSE;
983 
984 #ifdef SHADERVERBOSE
985  ConsoleMessage("called compile_ComposedShader(%p)\n",(void *)node);
986 #endif
987 
988  // might be set in appearance already
989  if (node->_shaderUserNumber == -1) node->_shaderUserNumber = getNextFreeUserDefinedShaderSlot();
990 
991  if (node->_shaderUserNumber < 0) {
992  ConsoleMessage ("out of user defined shader slots - can not run");
993  MARK_NODE_COMPILED
994  return NULL;
995  }
996 
997  vertShaderSource = MALLOC(GLchar **, sizeof(GLchar*) * node->parts.n);
998  fragShaderSource = MALLOC(GLchar **, sizeof(GLchar*) * node->parts.n);
999 
1000  /* set this up... set it to FALSE if there are problems */
1001  node->isValid = TRUE;
1002 
1003  /* we support only GLSL here */
1004  SUPPORT_GLSL_ONLY
1005 
1006  /* ok so far, go through the parts */
1007  //LOCATE_SHADER_PARTS(ShaderPart,parts)
1008 
1009  //#define LOCATE_SHADER_PARTS(myNodeType, myField)
1010  for (i=0; i<node->parts.n; i++) {
1011  struct X3D_ShaderPart *prog;
1012  prog = (struct X3D_ShaderPart *) node->parts.p[i];
1013  vertShaderSource[i] = NULL;
1014  fragShaderSource[i] = NULL;
1015 
1016  if (prog!=NULL) {
1017  if (prog->_nodeType == NODE_ShaderPart) {
1018  /* compile this program */
1019 
1020  if (!((strcmp (prog->type->strptr,"VERTEX")) && (strcmp(prog->type->strptr,"FRAGMENT")))) {
1021  char *myText = NULL; /* pointer to text to send in */
1022  char *cptr; /* returned caracter pointer pointer */
1023 
1024  cptr = prog->url.p[0]->strptr; /*shader_initCodeFromMFUri(&prog->url);*/
1025  if (cptr == NULL) {
1026  ConsoleMessage ("error reading url for :%s:",stringNodeType(NODE_ShaderPart));
1027  myText = "";
1028  } else {
1029  myText = cptr;
1030  /* assign this text to VERTEX or FRAGMENT buffers */
1031  if (!strcmp(prog->type->strptr,"VERTEX")) {
1032  vertShaderSource[i] = STRDUP(myText);
1033  haveVertShaderText = TRUE;
1034  } else {
1035  fragShaderSource[i] = STRDUP(myText);
1036  haveFragShaderText = TRUE;
1037  }
1038  /* printf ("Shader text for type %s is %s\n",prog->type->strptr,myText); */
1039  /*FREE_IF_NZ(cptr);*/
1040  }
1041  } else {
1042  ConsoleMessage ("%s, invalid Type, got \"%s\"",stringNodeType(NODE_ShaderPart), prog->type->strptr);
1043  node->isValid = FALSE;
1044  }
1045  } else {
1046  ConsoleMessage ("Shader, expected \"%s\", got \"%s\"",stringNodeType(NODE_ShaderPart), stringNodeType(prog->_nodeType));
1047  node->isValid = FALSE;
1048  }
1049  }
1050  }
1051 
1052  //if (haveFragShaderText) ConsoleMessage ("have frag shader text");
1053  // if (haveVertShaderText) ConsoleMessage ("have vert shader text");
1054 
1055  /*
1056  ConsoleMessage("parts count %d",node->parts.n);
1057  {int i;
1058  for (i=0; i<node->parts.n; i++) {
1059  if (vertShaderSource[i] != NULL) printf ("shaderVertexText %d is %s\n",i,vertShaderSource[i]);
1060  if (fragShaderSource[i] != NULL) printf ("shaderFragmentText %d is %s\n",i,fragShaderSource[i]);
1061  }
1062  }
1063  */
1064 
1065  //ConsoleMessage ("whew, past that part");
1066 
1067  if (node->isValid) {
1068  //ConsoleMessage ("shader node is Valid and shaderUserNumber is %d",node->_shaderUserNumber);
1069  sendShaderTextToEngine(node->_shaderUserNumber,node->parts.n,vertShaderSource,fragShaderSource);
1070  } else {
1071  ConsoleMessage ("shader node is NOT valid");
1072  FREE_IF_NZ(vertShaderSource);
1073  FREE_IF_NZ(fragShaderSource);
1074  }
1075 
1076  MARK_NODE_COMPILED
1077  ZERO_THREAD(node->_shaderLoadThread);
1078  node->_retrievedURLData = (haveFragShaderText && haveVertShaderText);
1079  // tell the parents that this node has updated its info
1080  tellShapeNodeToRecompile(X3D_NODE(node));
1081  return NULL;
1082 }
1083 
1084 
1085 
1086 
1087 
1088 static void *thread_compile_ProgramShader (void *args){
1089  ttglobal tg;
1090  struct X3D_ProgramShader *node;
1091 
1092  /* an array of text pointers, should contain shader source */
1093  GLchar **vertShaderSource;
1094  GLchar **fragShaderSource;
1095  int i, node_isValid;
1096  struct myArgs *inArgs;
1097 
1098  /* do we have anything to compile? */
1099  int haveVertShaderText;
1100  int haveFragShaderText;
1101 
1102  inArgs = (struct myArgs *) args;
1103  node = X3D_PROGRAMSHADER(inArgs->node);
1104  tg = inArgs->tg;
1105  FREE_IF_NZ(args);
1106 
1107  fwl_setCurrentHandle(tg,__FILE__,__LINE__);
1108  /* initialization */
1109  haveVertShaderText = FALSE;
1110  haveFragShaderText = FALSE;
1111 
1112  // might be set in appearance already
1113  if (node->_shaderUserNumber == -1) node->_shaderUserNumber = getNextFreeUserDefinedShaderSlot();
1114 
1115  if (node->_shaderUserNumber < 0) {
1116  ConsoleMessage ("out of user defined shader slots - can not run");
1117  //feb2015 MARK_NODE_COMPILED
1118  return NULL;
1119  }
1120 
1121 
1122  vertShaderSource = MALLOC(GLchar **, sizeof(GLchar*) * node->programs.n);
1123  fragShaderSource = MALLOC(GLchar **, sizeof(GLchar*) * node->programs.n);
1124 
1125  /* set this up... set it to FALSE if there are problems */
1126  node->isValid = FALSE; //TRUE;
1127  node_isValid = TRUE;
1128 
1129  /* we support only GLSL here */
1130  //SUPPORT_GLSL_ONLY
1131 //#define SUPPORT_GLSL_ONLY
1132  if (strcmp(node->language->strptr,"GLSL")) {
1133  ConsoleMessage ("Shaders: support only GLSL shading language, got :%s:, skipping...",node->language->strptr);
1134  node_isValid = FALSE;
1135  }
1136 
1137 
1138  /* ok so far, go through the programs */
1139  if(0){
1140  LOCATE_SHADER_PARTS(ShaderProgram,programs)
1141  }else{
1142 //#define LOCATE_SHADER_PARTS(myNodeType, myField)
1143  if(node_isValid)
1144  for (i=0; i<node->programs.n; i++) {
1145  struct X3D_ShaderProgram *prog;
1146  prog = (struct X3D_ShaderProgram *) node->programs.p[i];
1147  vertShaderSource[i] = NULL;
1148  fragShaderSource[i] = NULL;
1149 
1150  if (prog!=NULL) {
1151  if (prog->_nodeType == NODE_ShaderProgram) {
1152  /* compile this program */
1153  if (!((strcmp (prog->type->strptr,"VERTEX")) && (strcmp(prog->type->strptr,"FRAGMENT")))) {
1154  char *myText = NULL; /* pointer to text to send in */
1155  char *cptr; /* returned caracter pointer pointer */
1156  cptr = prog->url.p[0]->strptr; /*shader_initCodeFromMFUri(&prog->url);*/
1157  if (cptr == NULL) {
1158  ConsoleMessage ("error reading url for :%s:",stringNodeType(NODE_ShaderProgram));
1159  myText = "";
1160  } else {
1161  myText = cptr;
1162  /* assign this text to VERTEX or FRAGMENT buffers */
1163  if (!strcmp(prog->type->strptr,"VERTEX")) {
1164  vertShaderSource[i] = STRDUP(myText);
1165  haveVertShaderText = TRUE;
1166  } else {
1167  fragShaderSource[i] = STRDUP(myText);
1168  haveFragShaderText = TRUE;
1169  }
1170  /* printf ("Shader text for type %s is %s\n",prog->type->strptr,myText); */
1171  //FREE_IF_NZ(cptr);
1172  }
1173  } else {
1174  ConsoleMessage ("%s, invalid Type, got \"%s\"",stringNodeType(NODE_ShaderProgram), prog->type->strptr);
1175  node_isValid = FALSE;
1176  }
1177  } else {
1178  ConsoleMessage ("Shader, expected \"%s\", got \"%s\"",stringNodeType(NODE_ShaderProgram), stringNodeType(prog->_nodeType));
1179  node_isValid = FALSE;
1180  }
1181  }
1182  }
1183 
1184  }
1185 
1186 
1187  if (node_isValid) {
1188  sendShaderTextToEngine(node->_shaderUserNumber,node->programs.n,vertShaderSource,fragShaderSource);
1189  } else {
1190  FREE_IF_NZ(vertShaderSource);
1191  FREE_IF_NZ(fragShaderSource);
1192  }
1193 
1194  MARK_NODE_COMPILED
1195  ZERO_THREAD(node->_shaderLoadThread);
1196  node->_retrievedURLData = (haveFragShaderText && haveVertShaderText);
1197  // tell the parents that this node has updated its info
1198  tellShapeNodeToRecompile(X3D_NODE(node));
1199  node->isValid = node_isValid;
1200  return NULL;
1201 }
1202 
1203 
1204 static int shader_initCode(struct X3D_ShaderProgram *node, char* buffer){
1205  node->url.p[0]->strptr = STRDUP(buffer); //something else -in rexources?- seems to free buffer so we copy here
1206  node->url.n = 1;
1207  return TRUE;
1208 }
1209 
1210 bool parser_process_res_SHADER(resource_item_t *res)
1211 {
1212  //s_list_t *l;
1213  openned_file_t *of;
1214  struct X3D_ShaderProgram* ss;
1215  char *buffer;
1216 
1217  buffer = NULL;
1218 
1219  switch (res->type) {
1220  case rest_invalid:
1221  return FALSE;
1222  break;
1223 
1224  case rest_string:
1225  buffer = res->URLrequest;
1226  break;
1227  case rest_url:
1228  case rest_file:
1229  case rest_multi:
1230  //l = (s_list_t *) res->openned_files;
1231  //if (!l) {
1232  // /* error */
1233  // return FALSE;
1234  //}
1235 
1236  //of = ml_elem(l);
1237  of = res->openned_files;
1238  if (!of) {
1239  /* error */
1240  return FALSE;
1241  }
1242 
1243  buffer = (char*)of->fileData;
1244  break;
1245  }
1246 
1247  ss = (struct X3D_ShaderProgram *) res->whereToPlaceData;
1248 
1249  return shader_initCode(ss, buffer);
1250 }
1251 
1252 
1253 
1254 int shaderprogram_loaded(struct X3D_ShaderProgram *node)
1255 {
1256  resource_item_t *res;
1257  int retval = FALSE;
1258  switch (node->__loadstatus) {
1259  case LOADER_INITIAL_STATE: /* nothing happened yet */
1260 
1261  if (node->url.n == 0) {
1262  node->__loadstatus = LOADER_STABLE; /* a "do-nothing" approach */
1263  } else {
1264  //see if its plain text string
1265  char * sc = shader_initCodeFromMFUri(&node->url);
1266  if(sc){
1267  node->url.p[0]->strptr = sc; //wa re probably just putting it back where it came from, but in case 2nd part of multi, we promote to first part
1268  node->url.n = 1;
1269  node->__loadstatus = LOADER_LOADED;
1270  }else{
1271  res = resource_create_multi(&(node->url));
1272  res->media_type = resm_fshader;
1273  node->__loadstatus = LOADER_REQUEST_RESOURCE;
1274  node->__loadResource = res;
1275  }
1276  }
1277  break;
1278 
1279  case LOADER_REQUEST_RESOURCE:
1280  res = node->__loadResource;
1281  resource_identify(node->_parentResource, res);
1282  /* printf ("load_Inline, we have type %s status %s\n",
1283  resourceTypeToString(res->type), resourceStatusToString(res->status)); */
1284  res->actions = resa_download | resa_load; //not resa_parse which we do below
1285  resitem_enqueue(ml_new(res));
1286  //frontenditem_enqueue(ml_new(res));
1287  node->__loadstatus = LOADER_FETCHING_RESOURCE;
1288  break;
1289 
1290  case LOADER_FETCHING_RESOURCE:
1291  res = node->__loadResource;
1292  /* printf ("load_Inline, we have type %s status %s\n",
1293  resourceTypeToString(res->type), resourceStatusToString(res->status)); */
1294  // do we try the next url in the multi-url?
1295  if(res->complete){
1296  if (res->status == ress_loaded) {
1297  //determined during load process by resource_identify_type(): res->media_type = resm_vrml; //resm_unknown;
1298  res->whereToPlaceData = X3D_NODE(node);
1299  res->offsetFromWhereToPlaceData = 0;
1300  res->actions = resa_process;
1301  node->__loadstatus = LOADER_PROCESSING; // a "do-nothing" approach
1302  res->complete = FALSE;
1303  //send_resource_to_parser(res);
1304  //send_resource_to_parser_if_available(res);
1305  resitem_enqueue(ml_new(res));
1306  } else if ((res->status == ress_failed) || (res->status == ress_invalid)) {
1307  //no hope left
1308  printf ("resource failed to load\n");
1309  node->__loadstatus = LOADER_STABLE; // a "do-nothing" approach
1310  }
1311  }
1312  break;
1313 
1314  case LOADER_PROCESSING:
1315  res = node->__loadResource;
1316 
1317  //printf ("inline parsing.... %s\n",resourceStatusToString(res->status));
1318  //printf ("res complete %d\n",res->complete);
1319  if(res->complete){
1320  if (res->status == ress_parsed) {
1321  node->__loadstatus = LOADER_LOADED;
1322  }else{
1323  node->__loadstatus = LOADER_STABLE;
1324  }
1325  }
1326 
1327  break;
1328  case LOADER_STABLE:
1329  break;
1330  case LOADER_LOADED:
1331  case LOADER_COMPILED:
1332  retval = TRUE;
1333  }
1334  return retval;
1335 }
1336 int shaderprogram_compiled(struct X3D_ShaderProgram *node){
1337  return node->__loadstatus == LOADER_COMPILED;
1338 }
1339 
1340 int shaderprograms_loaded_but_not_compiled(struct Multi_Node *programs){
1341  int i, retval = TRUE;
1342  for(i=0;i<programs->n;i++){
1343  struct X3D_ShaderProgram *sp = (struct X3D_ShaderProgram*)programs->p[i];
1344  retval = retval && !shaderprogram_compiled(sp) && shaderprogram_loaded(sp);
1345  //retval = retval && shaderprogram_loaded(sp);
1346  }
1347  return retval;
1348 }
1349 void set_shaderprograms_compiled(struct Multi_Node *programs){
1350  int i;
1351  for(i=0;i<programs->n;i++){
1352  struct X3D_ShaderProgram *sp = (struct X3D_ShaderProgram*)programs->p[i];
1353  sp->__loadstatus = LOADER_COMPILED;
1354  }
1355 }
1356 void compile_ComposedShader (struct X3D_ComposedShader *node) {
1357  struct myArgs *args;
1358  ttglobal tg = gglobal();
1359  if(shaderprograms_loaded_but_not_compiled(&node->parts)){ //if all the program parts are downloaded and loaded but not compiled yet
1360  //set_shaderprograms_compiled(&node->parts);
1361  args = MALLOC(struct myArgs *, sizeof (struct myArgs));
1362  args->node = X3D_NODE(node);
1363  args->tg = tg;
1364  //before sept 22, 2016 - got both async and sync working, but if problems in future with uniforms not setting,
1365  // check child_shape to make sure user shader compiled before uniform initialization
1366  if(0){
1367  //asynchronous
1368  if (TEST_NULL_THREAD(node->_shaderLoadThread)) {
1369  pthread_create (&(node->_shaderLoadThread), NULL,
1370  &thread_compile_ComposedShader, (void *)args); //node);
1371  }
1372  }else{
1373  //synchronous
1374  thread_compile_ComposedShader(args);
1375  }
1376  set_shaderprograms_compiled(&node->parts);
1377  }
1378 }
1379 
1380 void compile_ProgramShader (struct X3D_ProgramShader *node) {
1381  struct myArgs *args;
1382  ttglobal tg = gglobal();
1383  if(shaderprograms_loaded_but_not_compiled(&node->programs)){ //if all the program parts are downloaded and loaded
1384  set_shaderprograms_compiled(&node->programs);
1385  args = MALLOC(struct myArgs *, sizeof (struct myArgs));
1386  args->node = X3D_NODE(node);
1387  args->tg = tg;
1388  if(1){
1389  //asynchronous - works
1390  if (TEST_NULL_THREAD(node->_shaderLoadThread)) {
1391  pthread_create (&(node->_shaderLoadThread), NULL,
1392  &thread_compile_ProgramShader, (void *)args);
1393  }
1394  }else{
1395  //synchronous - doesn't work
1396  thread_compile_ProgramShader(args);
1397  FREE_IF_NZ(args);
1398  }
1399  }
1400 }
1401 
1402 void compile_PackagedShader (struct X3D_PackagedShader *node) {
1403  ConsoleMessage ("found PackagedShader, do not support this structure, as we support only GLSL");
1404  node->isValid = FALSE;
1405  MARK_NODE_COMPILED
1406 }
1407 
1408 
1409 /*****************************************************************/
1410 void render_ComposedShader (struct X3D_ComposedShader *node) {
1411  COMPILE_IF_REQUIRED
1412  if (node->isValid) setUserShaderNode(X3D_NODE(node));
1413 }
1414 void render_PackagedShader (struct X3D_PackagedShader *node) {
1415  COMPILE_IF_REQUIRED
1416 }
1417 
1418 void render_ProgramShader (struct X3D_ProgramShader *node) {
1419  COMPILE_IF_REQUIRED
1420  if (node->isValid)
1421  setUserShaderNode(X3D_NODE(node));
1422 }
1423 
1424 // castle compositing shader effects system
1425 // http://castle-engine.sourceforge.net/compositing_shaders.php
1426 // thanks to Michalis Kamburelis for permission to implement in freewrl/libfreewrl
1427 // Effect node is like ComposedShader,
1428 // EffectPart node is like ShaderPart
1429 
1430 int getNextFreeEffectSlot() {
1431  int rv;
1432  ttglobal tg = gglobal();
1433  ppComponent_ProgrammableShaders p = (ppComponent_ProgrammableShaders)tg->Component_ProgrammableShaders.prv;
1434 
1435  p->effectCount++;
1436  if (p->effectCount == MAX_EFFECTS) return -1;
1437 
1438  rv = p->effectCount;
1439  //printf("getNextFreeEffectSlot %d\n",rv);
1440  return rv;
1441 }
1442 
1443 void compile_Effect (struct X3D_Effect *node) {
1444  //printf("compile_effect not implemented\n");
1445  int i, is_valid;
1446  //struct myArgs *args;
1447  ttglobal tg = gglobal();
1448 
1449  is_valid = TRUE;
1450  for(i=0;i<node->parts.n;i++){
1451  is_valid = is_valid && shaderprogram_loaded(X3D_SHADERPROGRAM(node->parts.p[i]));
1452  }
1453  node->isValid = is_valid;
1454  if(node->isValid) MARK_NODE_COMPILED
1455 }
1456 static int effect_stack_count = 0;
1457 shaderflagsstruct getShaderFlags();
1458 void pushShaderFlags(shaderflagsstruct flags);
1459 void popShaderFlags();
1460 
1461 void sib_prep_Effect (struct X3D_Node *parent, struct X3D_Node *sibAffector) {
1462  //unsigned int shaderflags;
1463  shaderflagsstruct shaderflags;
1464  struct X3D_Effect *node;
1465  ttglobal tg = gglobal();
1466  ppComponent_ProgrammableShaders p = (ppComponent_ProgrammableShaders)tg->Component_ProgrammableShaders.prv;
1467  node = (struct X3D_Effect*)sibAffector;
1468  COMPILE_IF_REQUIRED
1469  //unlike user shaders, we don't compile Effects - they are pasted into the ubershader which is compiled
1470  // from Shape, so we put them on a stack/queue/list here so ubershader can paste them all
1471  if(node->isValid){
1472  //push effect onto effect stack, with unique effect bit mask
1473  effect_stack_count++;
1474  //printf("sib_prep_effect not implemented %d\n",effect_stack_count);
1475  if (node->_shaderUserNumber == -1) node->_shaderUserNumber = getNextFreeEffectSlot();
1476 
1477  shaderflags = getShaderFlags();
1478  shaderflags.effects |= 1L << node->_shaderUserNumber;
1479  pushShaderFlags(shaderflags);
1480  stack_push(struct X3D_Node*,p->effect_stack,sibAffector);
1481  }
1482 
1483 }
1484 void sib_fin_Effect (struct X3D_Node *parent, struct X3D_Node *sibAffector) {
1485  struct X3D_Effect *node;
1486  ttglobal tg = gglobal();
1487  ppComponent_ProgrammableShaders p = (ppComponent_ProgrammableShaders)tg->Component_ProgrammableShaders.prv;
1488  node = (struct X3D_Effect*)sibAffector;
1489  //pop effect and bit mask off effect stack
1490  if(node->isValid){
1491  effect_stack_count--;
1492  //printf("sib_fin_effect not implemented %d\n",effect_stack_count);
1493  stack_pop(struct X3D_Node*,p->effect_stack);
1494  popShaderFlags();
1495  }
1496 }
1497 
1498 Stack *getEffectStack(){
1499  ttglobal tg = gglobal();
1500  ppComponent_ProgrammableShaders p = (ppComponent_ProgrammableShaders)tg->Component_ProgrammableShaders.prv;
1501  return p->effect_stack;
1502 }
1503 void update_effect_uniforms(){
1504  Stack * effect_stack;
1505  effect_stack = getEffectStack();
1506  if(effect_stack && effect_stack->n){
1507  int i;
1508  for(i=0;i<effect_stack->n;i++){
1509  struct X3D_Effect *effect = vector_get(struct X3D_Effect*,effect_stack,i);
1510  if (effect->isValid) {
1511  if (!effect->_initialized) {
1512  sendInitialFieldsToShader(X3D_NODE(effect));
1513  }
1514  }
1515  }
1516  }
1517 
1518 }
Definition: Vector.h:36