FreeWRL / FreeX3D 4.3.0
Component_ProgrammableShaders.c
1/*
2
3
4X3D 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
32Notes:
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
37X3D type GLSL type Initialize Route In Route Out
38-------------------------------------------------------------------------------------------------
39FIELDTYPE_SFFloat GL_FLOAT YES YES
40FIELDTYPE_MFFloat GL_FLOAT YES YES
41FIELDTYPE_SFRotation GL_FLOAT_VEC4 YES YES
42FIELDTYPE_MFRotation GL_FLOAT_VEC4 YES YES
43FIELDTYPE_SFVec3f GL_FLOAT_VEC3 YES YES
44FIELDTYPE_MFVec3f GL_FLOAT_VEC3 YES YES
45FIELDTYPE_SFBool GL_BOOL YES YES
46FIELDTYPE_MFBool GL_BOOL YES YES
47FIELDTYPE_SFInt32 GL_INT YES YES
48FIELDTYPE_MFInt32 GL_INT YES YES
49FIELDTYPE_SFNode
50FIELDTYPE_MFNode --
51FIELDTYPE_SFColor GL_FLOAT_VEC3 YES YES
52FIELDTYPE_MFColor GL_FLOAT_VEC3 YES YES
53FIELDTYPE_SFColorRGBA GL_FLOAT_VEC4 YES YES
54FIELDTYPE_MFColorRGBA GL_FLOAT_VEC4 YES YES
55FIELDTYPE_SFTime GL_FLOAT YES(float) YES(float)
56FIELDTYPE_MFTime
57FIELDTYPE_SFString --
58FIELDTYPE_MFString --
59FIELDTYPE_SFVec2f GL_FLOAT_VEC2 YES YES
60FIELDTYPE_MFVec2f GL_FLOAT_VEC2 YES YES
61FIELDTYPE_SFImage
62FIELDTYPE_FreeWRLPTR --
63FIELDTYPE_SFVec3d GL_FLOAT_VEC3 YES(float) YES(float)
64FIELDTYPE_MFVec3d
65FIELDTYPE_SFDouble GL_FLOAT YES(float) YES(float)
66FIELDTYPE_MFDouble
67FIELDTYPE_SFMatrix3f
68FIELDTYPE_MFMatrix3f
69FIELDTYPE_SFMatrix3d
70FIELDTYPE_MFMatrix3d
71FIELDTYPE_SFMatrix4f
72FIELDTYPE_MFMatrix4f
73FIELDTYPE_SFMatrix4d
74FIELDTYPE_MFMatrix4d
75FIELDTYPE_SFVec2d GL_FLOAT_2 YES(float) YES(float)
76FIELDTYPE_MFVec2d
77FIELDTYPE_SFVec4f GL_FLOAT_VEC4 YES YES
78FIELDTYPE_MFVec4f
79FIELDTYPE_SFVec4d GL_FLOAT_VEC4 YES(float) YES(float)
80FIELDTYPE_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
113void *Component_ProgrammableShaders_constructor(){
114 void *v = MALLOCV(sizeof(struct pComponent_ProgrammableShaders));
115 memset(v,0,sizeof(struct pComponent_ProgrammableShaders));
116 return v;
117}
118void 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}
128void 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.
148struct 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 */
199static 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;
320default :{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)); */
330static 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
439Note: Effect and EffectPart do not route-update their uniforms here.
440Reason: Effect/EffectPart can be composed into many compiled base shader permutations,
441 so they are updated from fieldvalues in child_shape
442more...
4432016 - added Effect and EffectPart to our bifurcated system of shaders:
4441. ubershader
4451a. 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
4501b. 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(); ...}
4611c. 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
4642. 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*/
479void 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 */
756static 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
857ComposedShader {
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
865ProgramShader {
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
875Note the differing location of the fields...
876
877*/
878
879
880void 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 */
931static 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/*********************************************************************/
948enum{
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
958static 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
1088static 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
1204static 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
1210bool 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
1254int 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}
1336int shaderprogram_compiled(struct X3D_ShaderProgram *node){
1337 return node->__loadstatus == LOADER_COMPILED;
1338}
1339
1340int 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}
1349void 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}
1356void 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
1380void 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
1402void 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/*****************************************************************/
1410void render_ComposedShader (struct X3D_ComposedShader *node) {
1411 COMPILE_IF_REQUIRED
1412 if (node->isValid) setUserShaderNode(X3D_NODE(node));
1413}
1414void render_PackagedShader (struct X3D_PackagedShader *node) {
1415 COMPILE_IF_REQUIRED
1416}
1417
1418void 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
1430int 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
1443void 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}
1456static int effect_stack_count = 0;
1457shaderflagsstruct getShaderFlags();
1458void pushShaderFlags(shaderflagsstruct flags);
1459void popShaderFlags();
1460
1461void 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}
1484void 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
1498Stack *getEffectStack(){
1499 ttglobal tg = gglobal();
1500 ppComponent_ProgrammableShaders p = (ppComponent_ProgrammableShaders)tg->Component_ProgrammableShaders.prv;
1501 return p->effect_stack;
1502}
1503void 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}