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