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