44#include <system_threads.h>
49#include <libFreeWRL.h>
66char *insertBefore(
char *current,
char *insert,
char* wholeBuffer,
int wholeBuffersize){
68 char *newcurrent, *here;
69 int insertlen, wholelen, need, movesize;
71 wholelen = strlen(current) +1;
72 insertlen = strlen(insert);
73 need = wholelen + insertlen + 1;
76 if(need < wholeBuffersize){
78 newcurrent = current + insertlen;
79 memmove(newcurrent,current,movesize);
80 memcpy(here,insert,insertlen);
82 ConsoleMessage(
"Not enough buffer for compositing shader buffsz=%d need=%d\n",wholeBuffersize,need);
91void removeAt(
char *here,
int len){
93 int wholelen, movesize;
95 wholelen = strlen(here) + 1;
97 movesize = wholelen - len;
98 memmove(here,source,movesize);
101void extractPlugCall(
char *start,
char *PlugName,
char *PlugParameters){
103 char *pns, *pne, *pps, *ppe;
105 pns = strstr(start,
"PLUG: ");
106 pns += strlen(
"PLUG: ");
107 pne = strchr(pns,
' ');
109 strncpy(PlugName,pns,len);
110 PlugName[len] =
'\0';
111 pps = strchr(pne,
'(');
112 ppe = strchr(pps,
')') + 1;
114 strncpy(PlugParameters,pps,len);
115 PlugParameters[len] =
'\0';
124int LookForPlugDeclarations(
char * CodeForPlugDeclarations,
int bsize,
char *PlugName,
char *ProcedureName,
char *ForwardDeclaration) {
133 char MainPlugName[100], MainPlugParams[1000];
135 int AnyOccurrencesHere = FALSE;
138 S = CodeForPlugDeclarations;
143 S = strstr(S,
"/* PLUG: ");
149 char ProcedureCallBuffer[500], *ProcedureCall;
150 extractPlugCall(S,MainPlugName,MainPlugParams);
151 if(!strcmp(MainPlugName,PlugName)){
156 ProcedureCall = ProcedureCallBuffer;
157 sprintf(ProcedureCall,
"%s%s;\n",ProcedureName,MainPlugParams);
158 S = insertBefore(S,ProcedureCall,CodeForPlugDeclarations,bsize);
159 AnyOccurrencesHere = TRUE;
164 S += strlen(
"/* PLUG:") + strlen(MainPlugName) + strlen(MainPlugParams);
171 if(AnyOccurrencesHere){
175 S = CodeForPlugDeclarations;
176 S = strstr(S,
"/* PLUG-DECLARATIONS */");
177 if(!S) S = CodeForPlugDeclarations;
178 S = insertBefore(S,ForwardDeclaration,CodeForPlugDeclarations,bsize);
183 printf(
"didn't find PLUG_%s\n",PlugName);
191void replaceAll(
char *buffer,
int bsize,
char *oldstr,
char *newstr){
193 while((found = strstr(buffer,oldstr))){
194 removeAt(found,strlen(oldstr));
195 insertBefore(found,newstr,buffer,bsize);
204void extractPlugName(
char *start,
char *PlugName,
char *PlugDeclaredParameters){
206 char *pns, *pne, *pps, *ppe;
208 pns = strstr(start,
"PLUG_");
209 pns += strlen(
"PLUG_");
211 pne = strpbrk(pns,
" (");
213 strncpy(PlugName,pns,len);
214 PlugName[len] =
'\0';
215 pps = strchr(pne,
'(');
216 ppe = strchr(pps,
')') + 1;
218 strncpy(PlugDeclaredParameters,pps,len);
219 PlugDeclaredParameters[len] =
'\0';
222#define SBUFSIZE 65534
223#define PBUFSIZE 16384
224int fw_strcpy_s(
char *dest,
int destsize,
const char *source){
227 if(source && strlen(source) < (
unsigned)destsize){
233int fw_strcat_s(
char *dest,
int destsize,
const char *source){
236 int destlen = strlen(dest);
238 if(strlen(source)+destlen < (
unsigned)destsize){
245void Plug(
int EffectPartType,
const char *PlugValue,
char **CompleteCode,
int *unique_int)
256 char PlugName[100], PlugDeclaredParameters[1000], PlugForwardDeclaration[1000], ProcedureName[100], PLUG_PlugName[100];
257 char Code[SBUFSIZE], Plug[PBUFSIZE];
258 int HasGeometryMain = FALSE, AnyOccurrences;
268 if(!CompleteCode[EffectPartType])
return;
269 err = fw_strcpy_s(Code,SBUFSIZE, CompleteCode[EffectPartType]);
270 err = fw_strcpy_s(Plug,PBUFSIZE, PlugValue);
275 HasGeometryMain = HasGeometryMain ||
276 ((EffectPartType == SHADERPART_GEOMETRY) && strstr(
"main(",Plug));
282 found = strstr(found,
"void PLUG_");
288 extractPlugName(found,PlugName,PlugDeclaredParameters);
289 found += strlen(
"void PLUG_") + strlen(PlugName) + strlen(PlugDeclaredParameters);
293 sprintf(ProcedureName,
"%s_%d",PlugName,(*unique_int));
298 sprintf(PLUG_PlugName,
"%s%s",
"PLUG_",PlugName);
299 replaceAll(Plug,PBUFSIZE,PLUG_PlugName,ProcedureName);
303 sprintf(PlugForwardDeclaration,
"void %s%s;\n",ProcedureName,PlugDeclaredParameters);
306 AnyOccurrences = LookForPlugDeclarations(Code,SBUFSIZE, PlugName,ProcedureName,PlugForwardDeclaration);
325 ConsoleMessage(
"Plug name %s not declared\n",PlugName);
336 err = fw_strcat_s(Code,SBUFSIZE,Plug);
337 FREE_IF_NZ(CompleteCode[EffectPartType]);
338 CompleteCode[EffectPartType] = strdup(Code);
341void AddVersion0(
int EffectPartType,
int versionNumber,
char *versionSuffix,
char **CompleteCode){
343 char Code[SBUFSIZE], line[1000];
349 if (!CompleteCode[EffectPartType])
return;
350 err = fw_strcpy_s(Code, SBUFSIZE, CompleteCode[EffectPartType]);
354 sprintf(line,
"#version %d %s\n", versionNumber, versionSuffix);
355 insertBefore(found, line, Code, SBUFSIZE);
356 FREE_IF_NZ(CompleteCode[EffectPartType]);
357 CompleteCode[EffectPartType] = strdup(Code);
360void AddExtension(
int EffectPartType,
char* extensionName,
char* behavior,
char** CompleteCode) {
362 char Code[SBUFSIZE], line[1000];
368 if (!CompleteCode[EffectPartType])
return;
369 err = fw_strcpy_s(Code, SBUFSIZE, CompleteCode[EffectPartType]);
371 found = strstr(Code,
"/*EXTENSIONS");
373 sprintf(line,
"#extension %s : %s\n", extensionName, behavior);
374 insertBefore(found, line, Code, SBUFSIZE);
375 FREE_IF_NZ(CompleteCode[EffectPartType]);
376 CompleteCode[EffectPartType] = strdup(Code);
379void AddVersion(
int EffectPartType,
int versionNumber,
char** CompleteCode) {
380 AddVersion0(EffectPartType, versionNumber,
"core", CompleteCode);
382void AddDefine0(
int EffectPartType,
const char *defineName,
int defineValue,
char **CompleteCode)
385 char Code[SBUFSIZE], line[1000];
391 if(!CompleteCode[EffectPartType])
return;
392 err = fw_strcpy_s(Code,SBUFSIZE, CompleteCode[EffectPartType]);
394 found = strstr(Code,
"/* DEFINE");
396 sprintf(line,
"#define %s %d \n",defineName,defineValue);
397 insertBefore(found,line,Code,SBUFSIZE);
398 FREE_IF_NZ(CompleteCode[EffectPartType]);
399 CompleteCode[EffectPartType] = strdup(Code);
402void AddDefine(
int EffectPartType,
const char *defineName,
char **CompleteCode){
405 AddDefine0(EffectPartType,defineName,1,CompleteCode);
418void EnableEffect(
struct X3D_Node * node,
char **CompletedCode,
int *unique_int){
422 ipart=SHADERPART_VERTEX;
424 for(i=0;i<effect->parts.n;i++){
426 if(part->_nodeType == NODE_EffectPart){
427 if(!strcmp(part->type->strptr,
"FRAGMENT"))
428 ipart = SHADERPART_FRAGMENT;
429 else if(!strcmp(part->type->strptr,
"VERTEX"))
430 ipart = SHADERPART_VERTEX;
431 str = part->url.p[0]->strptr;
432 if(!strncmp(str,
"data:text/plain,",strlen(
"data:text/plain,")))
433 str += strlen(
"data:text/plain,");
434 Plug(ipart,str, CompletedCode, unique_int);
438Stack *getEffectStack();
439void EnableEffects(
char **CompletedCode,
int *unique_int){
442 effect_stack = getEffectStack();
443 for(i=0;i<vectorSize(effect_stack);i++){
445 if(node->_nodeType == NODE_Effect){
446 EnableEffect(node,CompletedCode,unique_int);
499static const GLchar* genericVertexGLES2 =
"\
503#define attribute in \n\
504#define varying out \n\
506/* Generic GLSL vertex shader, used on OpenGL ES. */ \n\
508// we index into sampler arrays, OK for desktop, mobile needs GLES 3.1 and: \n\
509// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_gpu_shader5.txt \n\
510#extension GL_OES_gpu_shader5 : require //(or enable) \n\
513uniform mat4 fw_ModelViewMatrix; \n\
514uniform mat4 fw_ProjectionMatrix; \n\
515uniform mat4 fw_NormalMatrix; \n\
517uniform mat4 fw_ModelViewInverseMatrix; \n\
519attribute vec4 fw_Vertex; \n\
520attribute vec3 fw_Normal; \n\
522attribute int fw_Cindex; \n\
523layout (std430, binding = 10) buffer BufferBlock1 { \n\
526layout (std430, binding = 11) buffer BufferBlock2 { \n\
529layout (std430, binding = 12) buffer BufferObject1 { \n\
532layout (std430, binding = 13) buffer BufferObject2 { \n\
536layout (std430, binding = 14) buffer BufferBlock3 { \n\
539layout (std430, binding = 15) buffer BufferBlock4 { \n\
540 vec4 displace []; \n\
542#endif //DISPLACER \n\
544#if defined(LINETYPE) && defined(FULL) \n\
545//desktop glsl 130 \n\
546//glsl desktop version 130 can do flat instead of varying \n\
547//which allows the provoking vertex (for GL_LINE_STRIP its the second vertex in a pair) \n\
548//to output something to the frag that isnt interpolated - like .vert computed distance to prev \n\
549flat out vec2 f_prev; \n\
550flat out vec2 f_next; \n\
551flat out float f_linestrip_end; //0 middle, 1 start, 2 end segment\n\
553in vec3 a_prevVertex; \n\
554in vec3 a_nextVertex; \n\
555uniform int u_linetype; \n\
557#if defined(LINETYPE) || defined(POINTP) \n\
558uniform vec4 u_screenresolution; \n\
559#endif // LINETYPE POINTP \n\
562uniform mat4 fw_TextureMatrix[4]; \n\
563uniform int nTexMatrix; \n\
564attribute vec4 fw_MultiTexCoord0; \n\
565attribute vec4 fw_MultiTexCoord1; \n\
566attribute vec4 fw_MultiTexCoord2; \n\
567attribute vec4 fw_MultiTexCoord3; \n\
568uniform int nTexCoordChannels; \n\
569uniform int fw_tmap[6]; \n\
570uniform int fw_cmap[6]; \n\
571uniform int fw_ntexcombo; \n\
572uniform int fw_tgen[6]; \n\
573uniform float fw_parameter[7]; \n\
574uniform int fw_parameter_n; \n\
575uniform int flipuv; \n\
576vec4 yupuv(in vec4 uv){ \n\
577 //gltf uv are y-down, so we flag and send the flag here \n\
579 if(flipuv==1) yup.y = 1.0 - yup.y; \n\
582//varying vec3 v_texC; \n\
583varying vec3 fw_TexCoord[6]; \n\
585uniform int tex3dUseVertex; \n\
588#define TCGT_CAMERASPACENORMAL 0\n \
589#define TCGT_CAMERASPACEPOSITION 1\n \
590#define TCGT_CAMERASPACEREFLECTION 2\n \
591#define TCGT_CAMERASPACEREFLECTIONVECTOR 3\n \
592#define TCGT_COORD 4\n \
593#define TCGT_COORD_EYE 5\n \
594#define TCGT_NOISE 6\n \
595#define TCGT_NOISE_EYE 7\n \
596#define TCGT_REGULAR 8\n \
597#define TCGT_SPHERE 9\n \
598#define TCGT_SPHERE_LOCAL 10\n \
599#define TCGT_SPHERE_REFLECT 11\n \
600#define TCGT_SPHERE_REFLECT_LOCAL 12\n \
601uniform int fw_textureCoordGenType; \n\
603// there were other 3D noise function, this one was short in lines \n\
607// Description : Array and textureless GLSL 2D/3D/4D simplex \n\
608// noise functions. \n\
609// Author : Ian McEwan, Ashima Arts. \n\
610// Maintainer : stegu \n\
611// Lastmod : 20201014 (stegu) \n\
612// License : Copyright (C) 2011 Ashima Arts. All rights reserved. \n\
613// Distributed under the MIT License. See LICENSE file. \n\
614// https://github.com/ashima/webgl-noise \n\
615// https://github.com/stegu/webgl-noise \n\
618vec3 mod289(vec3 x) { \n\
619 return x - floor(x * (1.0 / 289.0)) * 289.0; \n\
622vec4 mod289(vec4 x) { \n\
623 return x - floor(x * (1.0 / 289.0)) * 289.0; \n\
626vec4 permute(vec4 x) { \n\
627 return mod289(((x * 34.0) + 10.0) * x); \n\
630vec4 taylorInvSqrt(vec4 r) \n\
632 return 1.79284291400159 - 0.85373472095314 * r; \n\
635float snoise(vec3 v) \n\
637 const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0); \n\
638 const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); \n\
641 vec3 i = floor(v + dot(v, C.yyy)); \n\
642 vec3 x0 = v - i + dot(i, C.xxx); \n\
645 vec3 g = step(x0.yzx, x0.xyz); \n\
646 vec3 l = 1.0 - g; \n\
647 vec3 i1 = min(g.xyz, l.zxy); \n\
648 vec3 i2 = max(g.xyz, l.zxy); \n\
650 // x0 = x0 - 0.0 + 0.0 * C.xxx; \n\
651 // x1 = x0 - i1 + 1.0 * C.xxx; \n\
652 // x2 = x0 - i2 + 2.0 * C.xxx; \n\
653 // x3 = x0 - 1.0 + 3.0 * C.xxx; \n\
654 vec3 x1 = x0 - i1 + C.xxx; \n\
655 vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y \n\
656 vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y \n\
660 vec4 p = permute(permute(permute(\n\
661 i.z + vec4(0.0, i1.z, i2.z, 1.0)) \n\
662 + i.y + vec4(0.0, i1.y, i2.y, 1.0)) \n\
663 + i.x + vec4(0.0, i1.x, i2.x, 1.0)); \n\
665 // Gradients: 7x7 points over a square, mapped onto an octahedron. \n\
666 // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) \n\
667 float n_ = 0.142857142857; // 1.0/7.0 \n\
668 vec3 ns = n_ * D.wyz - D.xzx; \n\
670 vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) \n\
672 vec4 x_ = floor(j * ns.z); \n\
673 vec4 y_ = floor(j - 7.0 * x_); // mod(j,N) \n\
675 vec4 x = x_ * ns.x + ns.yyyy; \n\
676 vec4 y = y_ * ns.x + ns.yyyy; \n\
677 vec4 h = 1.0 - abs(x) - abs(y); \n\
679 vec4 b0 = vec4(x.xy, y.xy); \n\
680 vec4 b1 = vec4(x.zw, y.zw); \n\
682 //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; \n\
683 //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; \n\
684 vec4 s0 = floor(b0) * 2.0 + 1.0; \n\
685 vec4 s1 = floor(b1) * 2.0 + 1.0; \n\
686 vec4 sh = -step(h, vec4(0.0)); \n\
688 vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; \n\
689 vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww; \n\
691 vec3 p0 = vec3(a0.xy, h.x); \n\
692 vec3 p1 = vec3(a0.zw, h.y); \n\
693 vec3 p2 = vec3(a1.xy, h.z); \n\
694 vec3 p3 = vec3(a1.zw, h.w); \n\
696 //Normalise gradients \n\
697 vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); \n\
703 // Mix final noise value \n\
704 vec4 m = max(0.5 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0); \n\
706 return 105.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), \n\
707 dot(p2, x2), dot(p3, x3))); \n\
713varying vec2 hatchPosition; \n\
717varying vec4 castle_vertex_eye; \n\
718varying vec3 castle_normal_eye; \n\
719varying vec4 castle_Color; //DA diffuse ambient term \n\
721//uniform float castle_MaterialDiffuseAlpha; \n\
722//uniform float castle_MaterialShininess; \n\
723/* Color summed with all the lights. \n\
724 Like gl_Front/BackLightModelProduct.sceneColor: \n\
725 material emissive color + material ambient color * global (light model) ambient. \n\
729#define MAX_LIGHTS 8 \n\
730uniform int lightcount; \n\
732//uniform float lightRadius[MAX_LIGHTS]; \n\
733uniform int lightType[MAX_LIGHTS];//ANGLE like this \n\
734struct fw_LightSourceParameters { \n\
741 float spotBeamWidth; \n\
742 float spotCutoff; \n\
743 vec3 Attenuations; \n\
744 float lightRadius; \n\
746 float shadowIntensity; \n\
750uniform fw_LightSourceParameters fw_LightSource[MAX_LIGHTS] /* gl_MaxLights */ ;\n\
754//uniform vec3 castle_SceneColor; \n\
755//uniform vec4 castle_UnlitColor; \n\
757uniform vec4 fw_UnlitColor; \n\
760struct fw_MaterialParameters { \n\
767 float normalScale; \n\
768 float transparency; \n\
773 // multitextures are disaggregated \n\
778 int samplr[10]; //0 texture2D 1 cubeMap \n\
780 int nt; //total single textures \n\
781 //iunit [0] normal [1] emissive [2] occlusion [3] diffuse OR base [4] shininess OR metallicRoughness [5] specular [6] ambient \n\
782 int tcount[7]; //num single textures 1= one texture 0=no texture 2+ = multitexture \n\
783 int tstart[7]; // where in packed tindex list to start looping \n\
784 //int cindex[7]; // which geometry multitexcoord channel 0=default \n\
786uniform fw_MaterialParameters fw_FrontMaterial; \n\
788uniform fw_MaterialParameters fw_BackMaterial; \n\
789uniform int material_side; //see renderfuncs reallydrawonce //0= front and back - no material difference, 1 = front 2=back\n\
792varying vec3 castle_ColorES; //emissive shininess term \n\
793vec3 castle_Emissive; \n\
799 float visibilityRange; \n\
800 float fogScale; //applied on cpu side to visrange \n\
801 int fogType; // 0 None, 1= FOGTYPE_LINEAR, 2 = FOGTYPE_EXPONENTIAL \n\
802 // ifdefed int haveFogCoords; \n\
804uniform fogParams fw_fogparams; \n\
806attribute float fw_FogCoords; \n\
809float castle_MaterialDiffuseAlpha; \n\
810float castle_MaterialShininess; \n\
811vec3 castle_SceneColor; \n\
812vec4 castle_UnlitColor; \n\
813vec4 castle_Specular; \n\
816attribute vec4 fw_Color; //castle_ColorPerVertex; \n\
817varying vec4 cpv_Color; \n\
820uniform vec3 particlePosition; \n\
821uniform vec3 particleDirection; \n\
822uniform mat4 particleTransform; \n\
823uniform int fw_ParticleGeomType; \n\
826uniform float u_pointSize; \n\
827uniform vec3 u_pointAttenuation; \n\
828uniform vec2 u_pointSizeRange; \n\
829uniform int u_pointtColorMode; \n\
830uniform vec3 u_pointPosition; \n\
831uniform int u_pointMethod; \n\
832uniform float u_pointFogCoord; \n\
833uniform vec4 u_pointCPV; \n\
836 //literal string size break \n" "\
837 vec3 dehomogenize(in mat4 matrix, in vec4 vector){ \n\
838 vec4 tempv = vector; \n\
839 if(tempv.w == 0.0) tempv.w = 1.0; \n\
840 vec4 temp = matrix * tempv; \n\
841 float winv = 1.0/temp.w; \n\
842 return temp.xyz * winv; \n\
844 bool approx(float a, float b){ \n\
845 if( abs(a - b) < .0001 )return true; \n\
848struct MaterialInfo \n\
850 float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) \n\
851 vec3 reflectance0; // full reflectance color (normal incidence angle) \n\
853 float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) \n\
854 vec3 diffuseColor; // color contribution from diffuse lighting \n\
856 vec3 reflectance90; // reflectance color at grazing angle \n\
857 vec3 specularColor; // color contribution from specular lighting \n\
859/* PLUG-DECLARATIONS */ \n\
860vec3 cpv_rgb_replace(in vec3 c3){ \n\
862 #ifdef CPV //color per vertex \n\
863 ret = fw_Color.rgb; \n\
867float cpv_alpha_modulate(in float alpha){\n\
868 float ret = alpha; \n\
869 #ifdef CPV //color per vertex \n\
870 ret = fw_Color.a; \n\
874//constant string break " "\n\
877//STEP 0: GEOMETRY SECTION \n\
879 float fog_coord = fw_FogCoords; \n\
880 #endif //FOGCOORD \n\
882 hatchPosition = fw_Vertex.xy; \n\
885 vec4 vertex_object = fw_Vertex; \n\
888 vertex_object.xyz += displace[dindex[fw_Cindex]].xyz; \n\
889 //vertex_object.x += displace[6].x; \n\
890 #endif //DISPLACER \n\
891 ivec4 pvi = PVI[fw_Cindex]; \n\
892 vec4 pvw = PVW[fw_Cindex]; \n\
893 vec4 vo = vec4(0.0); \n\
894 vo += JT[pvi.r-1]*pvw.r*vertex_object; \n\
895 vo += JT[pvi.g-1]*pvw.g*vertex_object; \n\
896 vo += JT[pvi.b-1]*pvw.b*vertex_object; \n\
897 vo += JT[pvi.a-1]*pvw.a*vertex_object; \n\
898 vertex_object = vo; \n\
899 #endif //SKINNING \n\
901 if(fw_ParticleGeomType != 4){ \n\
904 rot2 = mat4(1.0); \n\
906 float yaw = atan(particleDirection.y,particleDirection.x); \n\
907 float pitch = asin(particleDirection.z); \n\
908 rot[0][0] = cos(yaw); \n\
909 rot[1][1] = rot[0][0]; \n\
910 rot[0][1] = sin(yaw); \n\
911 rot[1][0] = -rot[0][1]; \n\
912 rot2[0][0] = cos(pitch); \n\
913 rot2[2][2] = rot2[0][0]; \n\
914 rot2[0][2] = sin(pitch); \n\
915 rot2[2][0] = -rot2[0][2]; \n\
916 rot = rot * rot2; \n\
917 vertex_object = rot * particleTransform * vertex_object; \n\
918 //vertex_object.xyz /= vertex_object.w; \n\
919 //vertex_object.w = 1.0; \n\
921 //vertex_object = particleTransform * vertex_object; \n\
922 vertex_object.xyz += particlePosition; \n\
924 #endif //PARTICLE \n\
925 vec3 normal_object = fw_Normal; \n\
927 //ivec4 pvi = PVI[fw_Cindex]; \n\
928 //vec4 pvw = PVW[fw_Cindex]; \n\
929 normal_object = vec3(0.0); \n\
930 normal_object += JN[pvi.r-1]*pvw.r*fw_Normal; \n\
931 normal_object += JN[pvi.g-1]*pvw.g*fw_Normal; \n\
932 normal_object += JN[pvi.b-1]*pvw.b*fw_Normal; \n\
933 normal_object += JN[pvi.a-1]*pvw.a*fw_Normal; \n\
934 #endif //SKINNING \n\
935 /* PLUG: vertex_object_space_change (vertex_object, normal_object) */ \n\
936 /* PLUG: vertex_object_space (vertex_object, normal_object) */ \n\
938 castle_vertex_eye = fw_ModelViewMatrix * vertex_object; \n\
939 #if defined(LINETYPE) && defined(FULL) \n\
940 if(u_linetype > 1){ \n\
941 //get curr, prev, next into screenspace \n\
942 //missing: screen aspect correction\n\
943 vec4 curr = fw_ProjectionMatrix * castle_vertex_eye; \n\
944 vec4 prev = fw_ProjectionMatrix * fw_ModelViewMatrix * vec4(a_prevVertex,1.0); \n\
945 //vec4 next = fw_ProjectionMatrix * fw_ModelViewMatrix * vec4(a_nextVertex,1.0); \n\
946 //projected coords are in -1 to 1 range \n\
947 f_prev = ((prev.xyz/prev.w).xy*.5 + vec2(.5))*u_screenresolution.xy; \n\
948 //f_next = (next.xyz/next.w).xy*u_screenresolution.xy*.5; \n\
949 //using GL_LINE_STRIP the 2nd vertex is the provoking vertex so is next \n\
950 f_next = ((curr.xyz/curr.w).xy*.5 + vec2(.5))*u_screenresolution.xy; \n\
951 v_curr = ((curr.xyz/curr.w).xy*.5 + vec2(.5))*u_screenresolution.xy; \n\
952 //float index aka findex method of determining start/end of polyline \n\
953 float findex = a_nextVertex.x; \n\
954 float fcount = a_nextVertex.y; \n\
955 f_linestrip_end = 0; \n\
956 if(approx(findex -1,0.0)) f_linestrip_end = 1; \n\
957 if(approx(findex,fcount-1.0)) f_linestrip_end += 2; \n\
959 #endif //LINETYPE \n\
961 //sprite: align to viewer \n\
962 if(fw_ParticleGeomType == 4){ \n\
963 vec4 ppos = vec4(particlePosition,1.0); \n\
964 vec4 particle_eye = fw_ModelViewMatrix * ppos; \n\
966 vec4 particle_eye1 = fw_ModelViewMatrix * ppos; \n\
967 float pscal = length(particle_eye1.xyz - particle_eye.xyz); \n\
968 castle_vertex_eye = particle_eye + pscal*vertex_object; \n\
970 #endif //PARTICLE \n\
971 castle_normal_eye = normalize( (fw_NormalMatrix * vec4(normal_object,1.0)).xyz); \n\
973 /* PLUG: vertex_eye_space (castle_vertex_eye, castle_normal_eye) */ \n\
975// STEP 2 MATERIAL SECTION \n\
976 fw_MaterialParameters ourMat = material_side < 2 ? fw_FrontMaterial : fw_BackMaterial; \n\
977 //default unlits in case we dont set them \n\
978 castle_UnlitColor = vec4(1.0,1.0,1.0,1.0); \n\
979 castle_MaterialDiffuseAlpha = 1.0; \n\
980 castle_Color = castle_UnlitColor; \n\
983 castle_ColorES = vec3(0.0); \n\
984 if(ourMat.type == 0){ \n\
985 castle_MaterialDiffuseAlpha = cpv_alpha_modulate(1.0 - ourMat.transparency); \n\
986 castle_SceneColor = cpv_rgb_replace(vec3(1.0)); //ourMat.emissive; \n\
987 castle_Emissive = ourMat.emissive; \n\
988 castle_Color = vec4(castle_SceneColor, castle_MaterialDiffuseAlpha); \n\
989 }else if(ourMat.type == 1){ \n\
990 castle_MaterialDiffuseAlpha = cpv_alpha_modulate(1.0 - ourMat.transparency); \n\
991 castle_SceneColor = cpv_rgb_replace(vec3(1.0)); \n\
992 castle_Emissive = ourMat.emissive; \n\
993 castle_Color = vec4(castle_SceneColor, castle_MaterialDiffuseAlpha); \n\
994 }else if(ourMat.type == 2){ \n\
995 castle_MaterialDiffuseAlpha = cpv_alpha_modulate(1.0 - ourMat.transparency); \n\
996 castle_MaterialShininess = ourMat.shininess; \n\
997 castle_SceneColor = cpv_rgb_replace(ourMat.diffuse)*ourMat.ambient; \n\
998 castle_Specular = vec4(ourMat.specular,1.0); \n\
999 castle_Emissive = ourMat.emissive; \n\
1000 castle_Color = vec4(castle_SceneColor, castle_MaterialDiffuseAlpha); \n\
1001 }else if(ourMat.type == 3){ \n\
1002 castle_MaterialDiffuseAlpha = cpv_alpha_modulate(1.0 - ourMat.transparency); \n\
1003 castle_SceneColor = cpv_rgb_replace(ourMat.baseColor); \n\
1004 castle_Emissive = ourMat.emissive; \n\
1005 castle_Color = vec4(castle_SceneColor, castle_MaterialDiffuseAlpha); \n\
1009 vec3 E = -normalize(castle_vertex_eye.xyz); \n\
1010 vec3 N = normalize (castle_normal_eye); \n\
1011 bool backFacing = (dot(N,E) < 0.0); \n\
1012 if (backFacing) { \n\
1015 castle_ColorES = vec3(0.0); \n\
1016 if(ourMat.type == 0){ \n\
1017 // no material aka MAT_NONE, not in specs \n\
1018 castle_MaterialDiffuseAlpha = cpv_alpha_modulate(1.0 - ourMat.transparency); \n\
1019 castle_SceneColor = cpv_rgb_replace(vec3(1.0)); //ourMat.emissive; \n\
1020 castle_Emissive = ourMat.emissive; \n\
1021 castle_Color = vec4(castle_SceneColor, castle_MaterialDiffuseAlpha); \n\
1022 }else if(ourMat.type == 1){ \n\
1023 // unlit emissive \n\
1024 castle_MaterialDiffuseAlpha = cpv_alpha_modulate(1.0 - ourMat.transparency); \n\
1025 castle_SceneColor = cpv_rgb_replace(ourMat.emissive); \n\
1026 castle_Emissive = ourMat.emissive; \n\
1027 castle_Color = vec4(castle_SceneColor, castle_MaterialDiffuseAlpha); \n\
1028 }else if(ourMat.type == 2){ \n\
1029 // Material Phong lighting \n\
1030 castle_MaterialDiffuseAlpha = cpv_alpha_modulate(1.0 - ourMat.transparency); \n\
1031 castle_MaterialShininess = ourMat.shininess; \n\
1032 castle_SceneColor = cpv_rgb_replace(ourMat.diffuse)*ourMat.ambient; \n\
1033 castle_Specular = vec4(ourMat.specular,1.0); \n\
1034 castle_Emissive = ourMat.emissive; \n\
1035 vec3 vcolor = vec3(0.0,0.0,0.0); \n\
1037 /* back Facing materials - flip the normal and grab back materials */ \n\
1038 /* PLUG: add_light_contribution2 (vcolor, castle_ColorES, castle_vertex_eye, N, ourMat.shininess, ourMat.ambient, ourMat.diffuse, ourMat.specular) */ \n\
1039 /* Clamp sum of lights colors to be <= 1. See template.fs for comments. */ \n\
1041 castle_Color = vec4(min(vcolor,1.0),castle_MaterialDiffuseAlpha); \n\
1042 }else if(ourMat.type == 3){ \n\
1043 //MAT_PHYSICAL aka physical lighting\n\
1044 castle_MaterialDiffuseAlpha = cpv_alpha_modulate(1.0 - ourMat.transparency); \n\
1045 castle_SceneColor = cpv_rgb_replace(ourMat.baseColor); \n\
1046 castle_Emissive = ourMat.emissive; \n\
1047 vec3 vcolor = vec3(0.0, 0.0, 0.0); \n\
1049 float metallic = ourMat.metallic; \n\
1050 float perceptualRoughness = ourMat.roughness; \n\
1051 vec3 baseColor = castle_SceneColor; //getBaseColor(); \n\
1053 vec3 specularColor= vec3(0.0); \n\
1054 vec3 f0 = vec3(0.04); \n\
1055 // ?? baseColor *= getVertexColor().xyz; //hunh? \n\
1056 vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0) * (1.0 - metallic); \n\
1057 specularColor = mix(f0, baseColor.rgb, metallic); \n\
1059 float alphaRoughness = perceptualRoughness * perceptualRoughness; \n\
1060 // Compute reflectance. \n\
1061 float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); \n\
1062 vec3 specularEnvironmentR0 = specularColor.rgb; \n\
1063 // Anything less than 2% is physically impossible and is instead considered to be shadowing. \n\
1064 vec3 specularEnvironmentR90 = vec3(clamp(reflectance * 50.0, 0.0, 1.0)); \n\
1065 MaterialInfo materialInfo = MaterialInfo( \n\
1066 perceptualRoughness, \n\
1067 specularEnvironmentR0, \n\
1070 specularEnvironmentR90, \n\
1074 //vec3 normal = N; //getNormal(); \n\
1075 /* PLUG: add_light_physical (vcolor, castle_vertex_eye.xyz, N, materialInfo ) */ \n\
1077 vcolor += castle_Emissive; //getEmissive(); \n\
1078 castle_Color = vec4(vcolor, castle_MaterialDiffuseAlpha); \n\
1082 castle_SceneColor = vec3(0.0,0.0,0.0); //line gets color from castle_Emissive \n\
1085 castle_Color.rgb = castle_UnlitColor.rgb; \n\
1089 //background sky comes through here, COLOR_MATERIAL_SHADER only \n\
1090 //castle_Color = fw_Color; \n\
1091 cpv_Color = fw_Color; \n\
1094//STEP 3 TEXTURE COORDINATES AND TRANSFORMS \n\
1096 vec4 texcoord = yupuv(fw_MultiTexCoord0); \n\
1098 //to re-use vertex coords as texturecoords3D, we need them in 0-1 range: CPU calc of fw_TextureMatrix0 \n\
1099 if(tex3dUseVertex == 1) \n\
1100 texcoord = vec4(fw_Vertex.xyz,1.0); \n\
1104 vec3 vertexNorm; \n\
1106 vec3 texcoord3 = texcoord.xyz; \n\
1107 vertexNorm = normalize((fw_NormalMatrix * vec4(fw_Normal,1.0)).xyz); \n\
1108 vertexPos = fw_ModelViewMatrix * fw_Vertex; \n\
1109 /* sphereEnvironMapping Calculation */ \n\
1110 vec3 u=normalize(vec3(vertexPos)); /* u is normalized position, used below more than once */ \n\
1111 vec3 r= reflect(u,vertexNorm); \n\
1112 if (fw_textureCoordGenType==TCGT_SPHERE) { /* TCGT_SPHERE GL_SPHERE_MAP OpenGL Equiv */ \n\
1113 float m=2.0 * sqrt(r.x*r.x + r.y*r.y + (r.z*1.0)*(r.z*1.0)); \n\
1114 texcoord3 = vec3(r.x/m+0.5,r.y/m+0.5,0.0); \n\
1115 }else if (fw_textureCoordGenType==TCGT_CAMERASPACENORMAL) { \n\
1116 /* GL_REFLECTION_MAP used for sampling cubemaps */ \n\
1117 float dotResult = 2.0 * dot(u,r); \n\
1118 texcoord3 = vec3(u-r)*dotResult; \n\
1119 }else if (fw_textureCoordGenType==TCGT_COORD) { \n\
1120 /* 3D textures can use coords in 0-1 range */ \n\
1121 texcoord3 = fw_Vertex.xyz; //xyz; \n\
1122 } else { /* default usage - like default CubeMaps */ \n\
1123 vec3 u=normalize(vec3(fw_ProjectionMatrix * fw_Vertex)); /* myEyeVertex */ \n\
1124 texcoord3 = reflect(u,vertexNorm); \n\
1126 texcoord.xyz = texcoord3; \n\
1129//constant string break " "\n\
1131 tcoord[0] = texcoord; //fw_MultiTexCoord0; \n\
1132 tcoord[1] = yupuv(fw_MultiTexCoord1); \n\
1133 tcoord[2] = yupuv(fw_MultiTexCoord2); \n\
1134 tcoord[3] = yupuv(fw_MultiTexCoord3); \n\
1135 mat4 ttrans = mat4(1.0); \n\
1136 vec4 tc = vec4(0.0,0.0,0.0,1.0); \n\
1137 // loop over output (transformed) texcoord \n\
1138 //for(int i=0;i<fw_ntexcombo;i++){ \n\
1139 for(int i=0;i<6;i++){ \n\
1140 int itmap = i >= fw_ntexcombo ? -1 : fw_tmap[i]; //programmer: should it be >= ? \n\
1141 int icmap = i >= fw_ntexcombo ? -1 : fw_cmap[i]; //ditto \n\
1142 //spec rules: not enough transforms? use identity, not enough coords? use last ones\n\
1143 ttrans = mat4(1.0); \n\
1144 if(icmap < 0) icmap = min(i,nTexCoordChannels-1); \n\
1145 tc = tcoord[max(icmap,0)]; \n\
1146 //if(i < nTexMatrix) ttrans = fw_TextureMatrix[i]; \n\
1147 if(itmap > -1 && fw_tgen[itmap] != TCGT_REGULAR) { \n\
1148 vec3 vertexNorm; \n\
1150 int tgen_type = fw_tgen[itmap]; \n\
1151 vec3 texcoord3 = tc.xyz; \n\
1152 vertexNorm = normalize((fw_NormalMatrix * vec4(fw_Normal,1.0)).xyz); \n\
1153 vertexPos = fw_ModelViewMatrix * fw_Vertex; \n\
1154 /* sphereEnvironMapping Calculation */ \n\
1155 vec3 u=normalize(vec3(vertexPos)); /* u is normalized position, used below more than once */ \n\
1156 vec3 r= reflect(u,vertexNorm); \n\
1157 if (tgen_type==TCGT_SPHERE) { /* TCGT_SPHERE GL_SPHERE_MAP OpenGL Equiv */ \n\
1158 float m=2.0 * sqrt(dot(r,r)); \n\
1159 texcoord3 = vec3(r.x/m+0.5,r.y/m+0.5,0.0); \n\
1160 }else if (tgen_type==TCGT_SPHERE_LOCAL) { \n\
1161 vec3 ul=normalize(fw_Vertex.xyz); /* u is normalized position, used below more than once */ \n\
1162 vec3 rl= reflect(ul,fw_Normal); \n\
1163 float m=2.0 * sqrt(dot(rl,rl)); \n\
1164 texcoord3 = vec3(rl.x/m+0.5,rl.y/m+0.5,0.0); \n\
1165 }else if (tgen_type==TCGT_CAMERASPACENORMAL) { \n\
1166 texcoord3 = vertexNorm*2.0 -1.0; \n\
1167 }else if (tgen_type==TCGT_CAMERASPACEPOSITION) { \n\
1168 texcoord3 = normalize(vertexPos.xyz)*2.0 -1.0; \n\
1169 }else if (tgen_type==TCGT_COORD) { \n\
1170 /* 3D textures can use coords in 0-1 range */ \n\
1171 texcoord3 = normalize(fw_Vertex.xyz)*2.0 - 1.0; //xyz; \n\
1172 }else if (tgen_type==TCGT_COORD_EYE) { \n\
1173 /* 3D textures can use coords in 0-1 range */ \n\
1174 texcoord3 = normalize(vertexPos.xyz)*2.0 - 1.0; //xyz; \n\
1175 }else if (tgen_type==TCGT_NOISE) { \n\
1176 vec3 uu = fw_Vertex.xyz; \n\
1177 uu.z *= snoise(uu); \n\
1178 texcoord3 = normalize(uu)*2.0 - 1.0; //xyz; \n\
1179 }else if (tgen_type==TCGT_NOISE_EYE) { \n\
1180 texcoord3 = normalize(vertexPos.xyz * snoise(vertexPos.xyz))*2.0 - 1.0; //xyz; \n\
1181 } else if(tgen_type == TCGT_CAMERASPACEREFLECTIONVECTOR || tgen_type == TCGT_CAMERASPACEREFLECTION){ \n\
1182 vec4 camera = fw_ModelViewInverseMatrix * vec4(0.0,0.0,0.0,1.0); \n\
1183 vec3 uu = normalize( vec4(vertex_object + camera).xyz ); \n\
1184 vec3 vv = normalize(fw_Normal); \n\
1185 texcoord3 = normalize(reflect(uu,vv)); //computed in object space \n\
1186 texcoord3.st = -texcoord3.st; //helps with renderman cubemap convention \n\
1187 } else if(tgen_type == TCGT_SPHERE_REFLECT) { \n\
1188 vec3 uu=normalize(vec3(fw_ProjectionMatrix * fw_Vertex)); /* myEyeVertex */ \n\
1189 if(fw_parameter_n == 1){ \n\
1190 float eta = 1.0/fw_parameter[0]; \n\
1191 texcoord3 = normalize(refract(uu,vertexNorm, eta)); \n\
1193 texcoord3 = normalize(reflect(uu,vertexNorm)); \n\
1194 } else if(tgen_type == TCGT_SPHERE_REFLECT_LOCAL) { \n\
1195 vec3 vlocal = vec3(fw_parameter[1],fw_parameter[2],fw_parameter[3]);\n\
1196 vec3 uu=normalize(vec3(vlocal - fw_Vertex.xyz)); \n\
1197 float eta = 1.0/(fw_parameter[0]+.001); \n\
1198 texcoord3 = normalize(refract(uu,fw_Normal, eta)); \n\
1199 } else { /* default usage - like default CubeMaps */ \n\
1200 vec3 uu=normalize(vec3(fw_ProjectionMatrix * fw_Vertex)); /* myEyeVertex */ \n\
1201 texcoord3 = normalize(reflect(uu,vertexNorm)); \n\
1203 fw_TexCoord[i] = texcoord3; \n\
1205 if(itmap > -1) ttrans = fw_TextureMatrix[itmap]; \n\
1206 //if(i < nTexCoordChannels) tc = tcoord[i]; \n\
1207 fw_TexCoord[i] = dehomogenize(ttrans, tc); \n\
1212 vec4 camera = fw_ModelViewInverseMatrix * vec4(0.0,0.0,0.0,1.0); \n\
1213 //vec3 u = normalize( vec4(castle_vertex_eye - camera).xyz ); \n\
1214 vec3 u = normalize( vec4(vertex_object + camera).xyz ); \n\
1215 vec3 v = normalize(fw_Normal); \n\
1216 fw_TexCoord[0] = normalize(reflect(u,v)); //computed in object space \n\
1217 fw_TexCoord[0].st = -fw_TexCoord[0].st; //helps with renderman cubemap convention \n\
1218 //for(int i=1;i<6;i++) fw_TexCoord[i] = fw_TexCoord[0]; //programmer: please integrate with multitexture (trans+coord) above\n\
1219 #endif //CUB_OLD \n\
1221 hatchPosition = fw_TexCoord[0].xy; \n\
1226 gl_Position = fw_ProjectionMatrix * castle_vertex_eye; \n\
1229 //particle-system-like PointSet points get special CPV, fogcoord handling, like pointPosition \n\
1231 fog_coord = u_pointFogCoord; \n\
1232 #endif //FOGCOORD \n\
1234 cpv_Color = u_pointCPV; \n\
1236 if(u_pointMethod == 2) { \n\
1237 //OBJECTSCALE - keep sprite-aligned but size fade with distance \n\
1238 vec4 ppos = vec4(u_pointPosition,1.0); \n\
1239 vec4 point_eye = fw_ModelViewMatrix * ppos; \n\
1241 vec4 point_eye1 = fw_ModelViewMatrix * ppos; \n\
1242 float pscal = length(point_eye1.xyz - point_eye.xyz); \n\
1243 castle_vertex_eye = point_eye + pscal*vertex_object*u_pointSize; \n\
1244 gl_Position = fw_ProjectionMatrix * castle_vertex_eye; \n\
1246 vec4 ppos = vec4(u_pointPosition,1.0); \n\
1247 vec4 castle_vertex_eye = fw_ModelViewMatrix * ppos; \n\
1248 vec4 view_position = fw_ProjectionMatrix * castle_vertex_eye; \n\
1249 float pscal = 1.0; \n\
1250 if(u_pointMethod == 1) { \n\
1251 //simple screen scale \n\
1252 pscal = u_pointSize; \n\
1253 } else if(u_pointMethod == 3) { \n\
1254 // fancy attenuation, screen scale \n\
1255 float zdist = castle_vertex_eye.z; \n\
1256 pscal = u_pointAttenuation.x + zdist*u_pointAttenuation.y + zdist*zdist*u_pointAttenuation.z; \n\
1257 if(pscal > 0.0) pscal = u_pointSize/pscal; \n\
1258 else pscal = u_pointSize; \n\
1259 pscal = max(pscal,u_pointSizeRange.x); \n\
1260 pscal = min(pscal,u_pointSizeRange.y); \n\
1262 //convert from screen pixel size to view coords \n\
1263 vec2 view_point = (vec2(pscal)*vertex_object.xy / u_screenresolution.xy) *vec2(2.0)* view_position.w; \n\
1264 view_position.xy += view_point; \n\
1265 gl_Position = view_position; \n\
1270 castle_vertex_eye.z = fog_coord; \n\
1271 #endif //FOGCOORD \n\
1274 castle_Color = fw_UnlitColor; \n\
1318static const GLchar* genericFragmentCube =
"\
1319#version 450 core \n\
1320out vec4 FragColor; \n\
1321in vec3 fw_TexCoord[6]; \n\
1323uniform samplerCube textureUnitCube[1]; \n\
1327 FragColor = vec4(texture(textureUnitCube[0], fw_TexCoord[0]).rgb, 1.0); \n\
1334static const GLchar *genericFragmentGLES2 =
"\
1338precision mediump float; \n\
1339// we index into sampler arrays, OK for desktop, mobile needs GLES 3.1 and: \n\
1340// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_gpu_shader5.txt \n\
1341#extension GL_OES_gpu_shader5 : require //(or enable) \n\
1343//precision highp float; \n\
1345#define varying in \n\
1346#define texture2D texture \n\
1347#define texture3D texture \n\
1348#define textureCube texture \n\
1349#define texture2DProj textureProj \n\
1350#define texture3DProj textureProj \n\
1351out vec4 FragColor; \n\
1352/* Generic GLSL fragment shader, used on OpenGL ES. */ \n\
1354varying vec4 castle_Color; \n\
1357#define MAX_LIGHTS 8 \n\
1359//for shadows, shape frag coord transformed into light system by vertex shader \n\
1360uniform mat4 lightMat[8]; \n\
1362uniform int lightcount; \n\
1363//uniform float lightRadius[MAX_LIGHTS]; \n\
1364uniform int lightType[MAX_LIGHTS];//ANGLE like this \n\
1365struct fw_LightSourceParameters { \n\
1368 float intensity; \n\
1370 vec3 halfVector; \n\
1372 float spotBeamWidth; \n\
1373 float spotCutoff; \n\
1374 vec3 Attenuations; \n\
1375 float lightRadius; \n\
1377 float shadowIntensity; \n\
1381uniform fw_LightSourceParameters fw_LightSource[MAX_LIGHTS] /* gl_MaxLights */ ;\n\
1385varying vec4 cpv_Color; \n\
1387struct MaterialInfo \n\
1389 float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) \n\
1390 vec3 reflectance0; // full reflectance color (normal incidence angle) \n\
1392 float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) \n\
1393 vec3 diffuseColor; // color contribution from diffuse lighting \n\
1395 vec3 reflectance90; // reflectance color at grazing angle \n\
1396 vec3 specularColor; // color contribution from specular lighting \n\
1399/* PLUG-DECLARATIONS */ \n\
1401uniform int textureCount; \n\
1402varying vec3 fw_TexCoord[6]; \n\
1404uniform int tex3dTiles[3]; \n\
1405uniform int repeatSTR[3]; \n\
1406uniform int magFilter; \n\
1408#if defined(TEX3D) || defined(TEX3DLAY) \n\
1409uniform sampler2D fw_Texture_unit0; \n\
1410#endif //TEX3D || TEX3DLAY \n\
1412//uniform sampler2D fw_Texture_unit0; \n\
1413uniform sampler2D fw_Texture_unit1; \n\
1414uniform sampler2D fw_Texture_unit2; \n\
1415uniform sampler2D fw_Texture_unit3; \n\
1416//uniform int textureCount; \n\
1417#endif //TEX3DLAY \n\
1418#if defined(MTEXA) || defined(PROJTEX) \n\
1419uniform sampler2D fw_Texture_unit1; \n\
1420uniform sampler2D fw_Texture_unit2; \n\
1421uniform sampler2D fw_Texture_unit3; \n\
1422uniform ivec2 fw_Texture_mode0; \n\
1423uniform ivec2 fw_Texture_mode1; \n\
1424uniform ivec2 fw_Texture_mode2; \n\
1425uniform ivec2 fw_Texture_mode3; \n\
1426uniform ivec2 fw_Texture_source0; \n\
1427uniform ivec2 fw_Texture_source1; \n\
1428uniform ivec2 fw_Texture_source2; \n\
1429uniform ivec2 fw_Texture_source3; \n\
1430uniform int fw_Texture_function0; \n\
1431uniform int fw_Texture_function1; \n\
1432uniform int fw_Texture_function2; \n\
1433uniform int fw_Texture_function3; \n\
1434//uniform int textureCount; \n\
1435void finalColCalcA(inout vec4 prevColour, in int mode, in int modea, in int func, in sampler2D tex, in vec2 texcoord){ \n\
1436 /* PLUG: finalColCalc ( prevColour, mode, modea, func, tex, texcoord ) */ \n\
1438#endif //defined(MTEXA) || defined(PROJTEX) \n\
1439#if defined(MTEX) || defined(PROJTEX) \n\
1440uniform vec4 mt_Color; \n\
1441void finalColCalcB(inout vec4 prevColour, in int mode, in int modea, in int func, in vec4 currentColor){ \n\
1442 /* PLUG: finalColCalc0 ( prevColour, mode, modea, func, currentColor ) */ \n\
1444#endif //defined(MTEX) || defined(PROJTEX) \n\
1446//literal string size break \n" "\
1448uniform int u_pointColorMode; \n\
1450#if defined(LINETYPE) && defined(FULL) \n\
1451uniform int u_linetype; \n\
1452uniform float u_lineperiod; \n\
1453uniform float u_linewidth; \n\
1454uniform int u_linestrip_start_style; \n\
1455uniform int u_linestrip_end_style; \n\
1456uniform vec2 u_linetype_uv[128]; \n\
1457uniform vec3 u_linetype_tse[128]; \n\
1458uniform vec4 u_screenresolution; \n\
1460flat in vec2 f_prev; \n\
1461flat in vec2 f_next; \n\
1462flat in float f_linestrip_end; \n\
1464bool approx(float a, float b){ \n\
1465 if( abs(a-b) < .0001) return true; \n\
1468bool on_linetype(inout vec4 frag_color){ \n\
1471 //procedural dashed line method (not used but works for simple dash)\n\
1472 float distance = length(v_curr - f_prev); \n\
1473 //info about cycle length \n\
1474 float period = 20.0; \n\
1475 float phase = mod(distance,20.0); \n\
1476 if(phase > 10.0) on = false; \n\
1478 //parametric dashed line method \n\
1479 vec2 baseline = f_next - f_prev; \n\
1480 vec2 u_dir = normalize(baseline); \n\
1481 vec2 v_dir = normalize(cross(vec3(0,0,1),vec3(u_dir,0.0)).xy); \n\
1483 //gl_FragCoord is relative to whole opengl window, we need viewport \n\
1484 vec2 vpcoord = gl_FragCoord.xy - u_screenresolution.pq; \n\
1485 ubar.s = dot(vpcoord.xy - f_prev, u_dir); \n\
1486 ubar.t = dot(vpcoord.xy - v_curr, v_dir); \n\
1487 float phase = mod(ubar.s, u_lineperiod); \n\
1488 vec2 uu = vec2(0.0,0.0); \n\
1489 bool gap = false; \n\
1491 vec3 tse = u_linetype_tse[int(phase)]; \n\
1492 uu = u_linetype_uv[int(phase)]; \n\
1493 gap = int(tse.x + .5) == 0; \n\
1494 dash = vec2(tse.y,tse.z); \n\
1495 vec2 ubarperiod = vec2(phase,ubar.t); \n\
1499 if( abs(ubarperiod.t - uu.t) > u_linewidth ) on = false; \n\
1500 //if( length(ubarperiod-uu) > u_linewidth *.5 ) on = false; \n\
1502 //do fancy linestrip end if required and on linestrip end segment \n\
1503 if( u_linestrip_start_style > 0 || u_linestrip_end_style > 0) \n\
1504 if(!approx(f_linestrip_end,0.0)){ \n\
1505 //a line can be both start and and of polyline \n\
1506 bool s_start = approx(mod(f_linestrip_end,2.0),1.0); \n\
1507 bool s_end = approx(floor(f_linestrip_end/2.0),1.0); \n\
1509 vec2 uend = vec2(0.0); \n\
1510 if(u_linestrip_start_style == 1){ \n\
1512 float arrowlength = 14.0; \n\
1513 vec2 head = vec2(uend.s + arrowlength,0.0); \n\
1514 if(ubar.s < head.s){ \n\
1516 vec2 range = head - ubar; \n\
1517 float d = 2.0*range.t + range.s; \n\
1518 if(d < arrowlength) on = true; \n\
1520 } else if(u_linestrip_start_style == 2){ \n\
1522 float radius = 6.0; \n\
1523 vec2 center = vec2(0.0); \n\
1524 center.s = (uend.s + radius); \n\
1525 vec2 diameter = uend + vec2(2.0*radius,0.0); \n\
1526 if(ubar.s < diameter.s){ \n\
1528 if( length(ubar - center) <= radius ) on = true; \n\
1533 vec2 uend = vec2(0.0); \n\
1534 uend.s = dot(f_next - f_prev, u_dir); \n\
1535 //must be end 2.0 \n\
1536 if(u_linestrip_end_style == 1){ \n\
1538 float arrowlength = 14.0; \n\
1539 vec2 head = vec2(uend.s - arrowlength,0.0); \n\
1540 if(ubar.s > head.s){ \n\
1542 vec2 range = ubar - head; \n\
1543 float d = 2.0*range.t + range.s; \n\
1544 if(d < arrowlength) on = true; \n\
1546 } else if(u_linestrip_end_style == 2){ \n\
1548 float radius = 6.0; \n\
1549 vec2 center = vec2(0.0); \n\
1550 center.s = (uend.s- radius); \n\
1551 vec2 diameter = uend - vec2(2.0*radius,0.0); \n\
1552 if(ubar.s > diameter.s){ \n\
1554 if( length(ubar - center) <= radius ) on = true; \n\
1564struct fillproperties { \n\
1565 vec4 HatchColour; \n\
1570uniform fillproperties fillprops; \n\
1571varying vec2 hatchPosition; \n\
1573//literal string size break \n" "\
1578 float visibilityRange; \n\
1580 int fogType; // 0 None, 1= FOGTYPE_LINEAR, 2 = FOGTYPE_EXPONENTIAL \n\
1581 // ifdefed int haveFogCoords; \n\
1583uniform fogParams fw_fogparams; \n\
1586#ifdef HAS_GEOMETRY_SHADER \n\
1587#define castle_vertex_eye castle_vertex_eye_geoshader \n\
1588#define castle_normal_eye castle_normal_eye_geoshader \n\
1589#endif // HAS_GEOMETRY_SHADER \n\
1591varying vec4 castle_vertex_eye; \n\
1592varying vec3 castle_normal_eye; \n\
1595//per-fragment lighting ie phong \n\
1596struct fw_MaterialParameters { \n\
1601 float shininess; \n\
1602 float occlusion; \n\
1603 float normalScale; \n\
1604 float transparency; \n\
1607 float roughness; \n\
1609 // multitextures are disaggregated \n\
1614 int samplr[10]; //0 texture2D 1 cubeMap \n\
1616 int nt; //total single textures \n\
1617 //iunit [0] normal [1] emissive [2] occlusion [3] diffuse OR base [4] shininess OR metallicRoughness [5] specular [6] ambient \n\
1618 int tcount[7]; //num single textures 1= one texture 0=no texture 2+ = multitexture \n\
1619 int tstart[7]; // where in packed tindex list to start looping \n\
1620 //int cindex[7]; // which geometry multitexcoord channel 0=default \n\
1622uniform fw_MaterialParameters fw_FrontMaterial; \n\
1624uniform fw_MaterialParameters fw_BackMaterial; \n\
1628//vec3 castle_ColorES; \n\
1630//per-vertex lighting - interpolated Emissive-specular \n\
1631varying vec3 castle_ColorES; //emissive shininess term \n\
1634//#if defined(TEX) || defined(PROJTEX) \n\
1635#if defined(SHADOW) || defined(CUB) || defined(PROJTEX) \n\
1636//shared samplerCube array -pointlight shadows, cubemapTextures \n\
1637uniform samplerCube textureUnitCube[8]; \n\
1638//shared sampler2D array -PTM or PBR use \n\
1639uniform sampler2D textureUnit[8]; \n\
1640#else //SHADOW || CUB \n\
1641//shared sampler2D array -PTM or PBR use \n\
1642uniform sampler2D textureUnit[16]; \n\
1643#endif //SHADOW || CUB || PROJTEX\n\
1644#if defined(SHADOW) || defined(PROJTEX) //this stuff only works in the fragment shader \n\
1645float local3D2cubedepth(in vec3 local, in float near, in float far) \n\
1647 //for cubemap depth, find which of 6 (perspective-rendered depthmap) faces will be sampled, \n\
1648 // and scale local 3d vector to depth map scale for comparison elsewhere \n\
1649 // https://en.wikipedia.org/wiki/Z-buffering#Mathematics \n\
1650 // https://stackoverflow.com/questions/10786951/omnidirectional-shadow-mapping-with-depth-cubemap \n\
1651 vec3 abslocal = abs(local); \n\
1652 float maxAxis = max(abslocal.x, max(abslocal.y, abslocal.z)); \n\
1653 float zfactor = (far + near) / (far - near) - (2.0 * far * near) / (far - near) / maxAxis; \n\
1654 return (zfactor + 1.0) * 0.5; \n\
1656#endif //SHADOW || PROJTEX \n\
1658float ShadowCalculation(in int ilight, in vec3 lightdir) \n\
1660 float shadow = 0.0; \n\
1661 vec4 lightCoord = lightMat[ilight] * castle_vertex_eye; \n\
1662 vec4 lightNorm = lightMat[ilight] * vec4((castle_vertex_eye.xyz + castle_normal_eye.xyz),1.0); \n\
1663 vec4 fragPosLightSpace = lightCoord; \n\
1664 int type = lightType[ilight]; \n\
1665 vec3 projCoords, projNorm; \n\
1666 // perform perspective divide \n\
1667 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; \n\
1668 //instead of inverseTranspose we transform another point, and subtract \n\
1669 projNorm = lightNorm.xyz/lightNorm.w; \n\
1670 float closestDepth = 10.0; \n\
1671 float currentDepth = 10.0; \n\
1673 //PointLight uses cubemap shadow and 3D lookup coord \n\
1674 vec3 pc = lightCoord.xyz; \n\
1676 vec3 nc = normalize(pc); \n\
1677 closestDepth = texture(textureUnitCube[fw_LightSource[ilight].depthmap], nc).r; \n\
1678 currentDepth = local3D2cubedepth(pc,.1,fw_LightSource[ilight].lightRadius); \n\
1680 // transform to [0,1] range \n\
1681 projCoords = projCoords * 0.5 + 0.5; \n\
1682 // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords) \n\
1683 closestDepth = texture(textureUnit[fw_LightSource[ilight].depthmap], projCoords.xy).r; \n\
1684 // get depth of current fragment from light's perspective \n\
1685 currentDepth = projCoords.z; \n\
1686 if (projCoords.z > 1.0) \n\
1687 currentDepth = 1.0; \n\
1689 // calculate bias (based on depth map resolution and slope) \n\
1690 vec3 normal = normalize(projNorm-projCoords); \n\
1691 //vec3 lightDir = normalize(lightPos - fs_in.FragPos); \n\
1692 vec3 lightDir = normalize(lightdir); \n\
1693 // https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping \n\
1694 // solve shadow acne with a small bias \n\
1695 //float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005); \n\
1696 float bias = 0.005; \n\
1697 // check whether current frag pos is in shadow \n\
1698 shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; \n\
1699 //shadow = (currentDepth - bias - closestDepth)*100.0; \n\
1700 //shadow = currentDepth; \n\
1702 //shadow = closestDepth; \n\
1705 vec2 texelSize = 1.0 / textureSize(textureUnit[fw_LightSource[ilight].depthmap], 0); \n\
1706 for (int x = -1; x <= 1; ++x) \n\
1708 for (int y = -1; y <= 1; ++y) \n\
1710 float pcfDepth = texture(textureUnit[fw_LightSource[ilight].depthmap], projCoords.xy + vec2(x, y) * texelSize).r; \n\
1711 shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; \n\
1716 // keep the shadow at 0.0 when outside the far_plane region of the light's frustum. \n\
1717 //if (projCoords.z > 1.0) \n\
1718 // shadow = 0.0; \n\
1722//#endif //defined(TEX) || defined(PROJTEX) \n\
1725struct TextureProjectorProperties { \n\
1731 float farDistance; \n\
1732 int type; //0,1 2D 2 cubemap \n\
1733 float intensity; \n\
1735 float shadowIntensity; \n\
1738uniform struct TextureProjectorProperties ptms[8]; \n\
1739struct TextureDescriptor { \n\
1740//per texture descriptor (projector 1:m texdescriptor m:1 sampler): \n\
1747uniform struct TextureDescriptor tdescs[16]; \n\
1748uniform int ptmCount; \n\
1749vec4 fragProjCalTexCoord(in vec4 frag_color) { \n\
1751 for(int i=0;i<ptmCount;i++) { \n\
1752 struct TextureProjectorProperties ptm = ptms[i]; \n\
1753 //is point on + side of projector ? \n\
1754 vec4 projTexCoord = ptm.GenMatCam * vec4(castle_vertex_eye.xyz,1.0); \n\
1755 vec4 projTexNorm = ptm.GenMatCam * vec4((castle_vertex_eye.xyz + castle_normal_eye.xyz),1.0); \n\
1756 if(ptm.type == 2) { \n\
1757 //ProjectorPoint uses cubemap for diffuse and shadow, and a 3D lookup coord \n\
1758 vec3 pc = projTexCoord.xyz; \n\
1759 bool facingProjector = true; \n\
1760 if(ptm.backCull == 1) \n\
1762 vec3 pn = projTexNorm.xyz/projTexNorm.w; \n\
1763 vec3 nvec = normalize(pn - pc); \n\
1764 vec3 pvec = normalize(pc); \n\
1765 float dotval = dot(nvec,pvec); \n\
1766 facingProjector = (dotval <= 0.0); \n\
1768 if(facingProjector){ \n\
1769 if(ptm.shadows > 0){ \n\
1770 vec3 nc = normalize(pc); \n\
1772 float closestDepth = texture(textureUnitCube[ptm.depthmap], nc).r; \n\
1773 float currentDepth = local3D2cubedepth(pc,.1,ptm.farDistance); \n\
1774 //float currentDepth = length(nc); \n\
1775 //float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005); \n\
1776 float bias = 0.005; \n\
1777 // check whether current frag pos is in shadow \n\
1778 float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; \n\
1779 facingProjector = shadow == 0.0; \n\
1782 if(facingProjector){ \n\
1783 //pc.yz = -pc.yz; //renderman cubemap convention \n\
1784 vec3 nc = normalize(pc); \n\
1785 struct TextureDescriptor tdesc = tdescs[ptm.tstart]; \n\
1786 frag_color.rgb = texture(textureUnitCube[tdesc.tindex], nc).rgb; \n\
1787 frag_color.rgb = frag_color.rgb * ptm.color * ptm.intensity; \n\
1788 frag_color.a = 1.0; \n\
1790 } else { //ptm.type \n\
1791 if( projTexCoord.z > 0.0 ){ \n\
1792 vec4 pp = projTexCoord; \n\
1793 bool inside = (-pp.w < pp.x) && (pp.x < pp.w); \n\
1794 inside = inside && (-pp.w < pp.y) && (pp.y < pp.w); \n\
1795 inside = inside && (-pp.w < pp.z) && (pp.z < pp.w); \n\
1797 bool facingProjector = true; \n\
1798 vec3 pptex = pp.xyz/pp.w; \n\
1799 if(ptm.backCull == 1) \n\
1801 vec3 pn = projTexNorm.xyz/projTexNorm.w; \n\
1802 //if(!gl_FrontFacing) pn = -pn; \n\
1803 vec3 nvec = normalize(pn - pptex.xyz); \n\
1804 vec3 peye = vec3(0.0,0.0,1.0); //normalize(pc); \n\
1805 float dotval = dot(nvec,peye); \n\
1806 facingProjector = (dotval < 0.0); \n\
1808 pptex.xyz = pptex.xyz *.5 + .5; \n\
1809 if(facingProjector){ \n\
1810 if(ptm.shadows > 0){ \n\
1811 float currentDepth = pptex.z; \n\
1812 //if (pptex.z > 1.0) \n\
1813 // currentDepth = 1.0; \n\
1814 float closestDepth = texture2D(textureUnit[ptm.depthmap],pptex.xy).r; \n\
1815 //float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005); \n\
1816 float bias = 0.005; \n\
1817 // check whether current frag pos is in shadow \n\
1818 float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; \n\
1819 //frag_color = vec4(vec3(ptmdepthmap[i]),1.0); \n\
1820 //frag_color = vec4(vec3(.2,.2,depthValue),1.0); \n\
1821 facingProjector = shadow == 0.0; //pptex.z < depthValue; \n\
1824 if(facingProjector){ \n\
1825 //parallel/ortho \n\
1826 vec2 ptex = pptex.xy; \n\
1827 //ptex.x = (ptex.x * .5) + .5; \n\
1828 //ptex.y = (ptex.y * .5) + .5; \n\
1829 int ndesc = ptm.tcount; \n\
1830 struct TextureDescriptor tdesc; \n\
1831 vec4 prev = frag_color; \n\
1832 for(int j=0;j<ndesc;j++){ \n\
1833 tdesc = tdescs[ptm.tstart+j]; \n\
1834 int kk = tdesc.tindex; \n\
1835 int modea = int(tdesc.mode / 100); \n\
1836 int mode = tdesc.mode - 100*modea; \n\
1837 finalColCalcA(prev, mode, modea, tdesc.func, textureUnit[tdesc.tindex], ptex); \n\
1839 //frag_color = prev;\n\
1840 frag_color.rgb = prev.rgb * ptm.color * ptm.intensity; \n\
1841 frag_color.a = prev.a; \n\
1847 return frag_color; \n\
1850/* Wrapper for calling PLUG texture_coord_shift */ \n\
1851vec2 texture_coord_shifted(in vec2 tex_coord) \n\
1853 /* PLUG: texture_coord_shift (tex_coord) */ \n\
1854 return tex_coord; \n\
1856//literal string size break \n" "\
1857//statics for multitexturing function\n\
1858vec3 mtex_specular; \n\
1859vec4 mtex_diffuse; \n\
1860//PHYSICAL LIGHTING >> \n\
1861// https://github.com/KhronosGroup/glTF-Sample-Viewer \n\
1862const float M_PI = 3.141592653589793; \n\
1863// sRGB to linear approximation \n\
1864const float GAMMA = 2.2; \n\
1865vec4 SRGBtoLINEAR(vec4 srgbIn) \n\
1867 return vec4(pow(srgbIn.xyz, vec3(GAMMA)), srgbIn.w); \n\
1869const float INV_GAMMA = 1.0 / GAMMA; \n\
1870// linear to sRGB approximation \n\
1871vec3 LINEARtoSRGB(vec3 color) \n\
1873 return pow(color, vec3(INV_GAMMA)); \n\
1875// << PhYSICAL LIGHTING \n\
1877fw_MaterialParameters mat = fw_FrontMaterial; \n\
1878// material.maps: iuse [0] normal [1] emissive [2] occlusion [3] diffuse OR base [4] shininess OR metallicRoughness [5] specular [6] ambient \n\
1879vec4 sample_map(in int iuse, in int istage, in bool apply_gamma){ \n\
1880 //simpler than texture_apply, just for 1 texture \n\
1881 vec4 nc = vec4(1.0,1.0,1.0,1.0); \n\
1882 int tex_index = mat.tindex[mat.tstart[iuse]+istage]; \n\
1883 int coord_index = mat.cmap[mat.tstart[iuse]+istage]; \n\
1884 int samplr = mat.samplr[mat.tstart[iuse]+istage]; \n\
1887 nc = texture(textureUnitCube[tex_index], fw_TexCoord[coord_index].xyz); \n\
1890 nc = texture2D(textureUnit[tex_index],fw_TexCoord[coord_index].st); \n\
1891 if(apply_gamma) nc = SRGBtoLINEAR(nc); \n\
1894vec3 getNormal(){ \n\
1895 int normal_image = 0; \n\
1896 vec3 N = normalize (castle_normal_eye); \n\
1897 if (!gl_FrontFacing) //backFacing \n\
1899 if(mat.tcount[normal_image] > 0){ \n\
1900 // https://learnopengl.com/Advanced-Lighting/Normal-Mapping \n\
1901 //texture transform applied in vertex shader \n\
1902 vec2 UV = fw_TexCoord[mat.cmap[mat.tstart[normal_image]]].xy; \n\
1904 // Retrieve the tangent space matrix \n\
1905 vec3 pos_dx = dFdx(castle_vertex_eye.xyz); \n\
1906 vec3 pos_dy = dFdy(castle_vertex_eye.xyz); \n\
1907 vec3 tex_dx = dFdx(vec3(UV, 0.0)); \n\
1908 vec3 tex_dy = dFdy(vec3(UV, 0.0)); \n\
1909 vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t); \n\
1911 t = normalize(t - N * dot(N, t)); \n\
1912 vec3 b = normalize(cross(N, t)); \n\
1913 mat3 tbn = mat3(t, b, N); \n\
1914 //vec4 nc = texture2D(textureUnit[mat.tindex[mat.tstart[0]]],fw_TexCoord[mat.cindex[normal_image]].xy); \n\
1915 vec4 nc = sample_map(normal_image,0,false); \n\
1916 vec3 ncn = normalize(vec3(nc.x * 2.0 - 1.0, nc.y*2.0 -1.0, nc.z)); //-1 to 1, -1 to 1, 0 to 1 \n\
1917 vec3 ncns = normalize(ncn*vec3(mat.normalScale,mat.normalScale,1.0)); \n\
1918 //normal.xyz = normalize((textureSample(normalTexture).rgb * vec3(2,2,2) - vec3(1,1,1)) * vec3(normalScale, normalScale, 1)) \n\
1919 //vec3 nscaled = normalize(nc.xyz*vec3(2.0,2.0,2.0) - vec3(1.0,1.0,1.0)*vec3(mat.normalScale,mat.normalScale,1.0)); \n\
1920 //N = normalize(tbn * (2.0 * nc.xyz - 1.0)); \n\
1921 //N = normalize(tbn * (2.0 * nc.xyz - vec3(mat.normalScale,mat.normalScale,1.0))); \n\
1922 N = normalize(tbn * ncns); \n\
1926vec3 getEmissive(){ \n\
1927 vec3 E = mat.emissive; \n\
1928 int emissive_image = 1; \n\
1929 if(mat.type > 0 && mat.tcount[emissive_image] > 0){ \n\
1930 vec4 ec = sample_map(emissive_image,0,false); \n\
1931 E.rgb *= ec.rgb; \n\
1935float getAlpha(){ \n\
1937 if(mat.type > 0) { \n\
1938 A -= mat.transparency; \n\
1939 int transparency_image = 3; //diffuse or base image \n\
1940 if(mat.type == 1) transparency_image = 1; //emissive image \n\
1941 if(mat.tcount[transparency_image] > 0) { \n\
1942 vec4 dc = sample_map(transparency_image,0,false); \n\
1948float getOcclusion(){ \n\
1949 float occ = 1.0; //1=not occluded, 0=occluded\n\
1950 if(mat.type == 2 || mat.type == 3) { \n\
1951 int occlusion_image = 2; \n\
1952 if(mat.tcount[occlusion_image] > 0) { \n\
1953 occ = mat.occlusion; //occlusionStrength \n\
1954 vec4 oc = sample_map(occlusion_image,0,false); \n\
1955 occ *= oc.r; //only the red \n\
1960float getShininess() { \n\
1961 float S = mat.shininess; \n\
1962 int shininess_image = 4; \n\
1963 if(mat.type == 2 && mat.tcount[shininess_image] > 0){ \n\
1964 vec4 sc = sample_map(shininess_image,0,false); \n\
1969vec3 getSpecular() { \n\
1970 vec3 S = mat.specular; \n\
1971 int specular_image = 5; \n\
1972 if(mat.type == 2 && mat.tcount[specular_image] > 0){ \n\
1973 vec4 sc = sample_map(specular_image,0,false); \n\
1974 S.rgb *= sc.rgb; \n\
1978float getAmbient(){ \n\
1979 float amb = mat.ambient; \n\
1980 int ambient_image = 6; \n\
1981 if(mat.type == 2 && mat.tcount[ambient_image] > 0){ \n\
1982 vec4 ac = sample_map(ambient_image,0,false); \n\
1987float getMetallic(){ \n\
1988 float met = mat.metallic; \n\
1989 int metallic_image = 4; \n\
1990 if(mat.type == 3 && mat.tcount[metallic_image] > 0){ \n\
1991 vec4 mr = sample_map(metallic_image,0,false); \n\
1996float getRoughness(){ \n\
1997 float rou = mat.roughness; \n\
1998 int roughness_image = 4; //same as metallic \n\
1999 if(mat.type == 3 && mat.tcount[roughness_image] > 0){ \n\
2000 vec4 mr = sample_map(roughness_image,0,false); \n\
2005vec4 getVertexColor() { \n\
2006 //H: this is supposed to be from vertex shader \n\
2007 vec4 color = vec4(1.0); \n\
2009 color = cpv_Color; \n\
2013vec4 getMainColor(in vec4 fragColor, in int iuse) { \n\
2014 // https://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/lighting.html#Lightingoff \n\
2015 // table 17-2, 17-3 logic here \n\
2016 // function returns ODrgb (lit) or Irgb (unlit) \n\
2017 // MODT - freewrl out-of-spec option: alwasy modulate texture with diffuse \n\
2018 // MODC - illuminance texture, modulate texture with any CPV/CPF or mat.diffuse if no CPV \n\
2019 // MODA - texture has no interesting alpha, use material.diffuse.a \n\
2020 vec4 dcolor = fragColor; \n\
2021 float mixcpv = 0.0; \n\
2030 vec4 IC = getVertexColor(); \n\
2031 dcolor = mix(dcolor,IC,mixcpv); \n\
2033 if(mat.tcount[iuse] > 0){ \n\
2034 //appearance level textures (vs material level) \n\
2035 vec4 tcolor = vec4(1.0); \n\
2036 #if defined(MODT) || defined(MODC) \n\
2037 tcolor.rgb = dcolor.rgb; \n\
2038 #endif //MODT || MODC \n\
2039 /* PLUG: texture_apply (tcolor, iuse) */ \n\
2040 dcolor.rgb *= tcolor.rgb; \n\
2042 dcolor.a *= tcolor.a; \n\
2044 dcolor.a = tcolor.a; \n\
2050vec4 getGouraudColor() { \n\
2051 vec4 dcolor = castle_Color; \n\
2053 dcolor = vec4(clamp(castle_ColorES + castle_Color.rgb,0.0,1.0),castle_Color.a); \n\
2056 dcolor = cpv_Color; \n\
2059 int iuse = mat.type < 2 ? 1 : 3; \n\
2060 if(mat.tcount[iuse] > 0){ \n\
2061 vec4 tcolor = vec4(1.0); \n\
2062 #if defined(MODT) || defined(MODC) \n\
2063 tcolor.rgb = dcolor.rgb; \n\
2064 #endif //MODT || MODC \n\
2065 /* PLUG: texture_apply (tcolor, iuse) */ \n\
2066 dcolor.rgb = tcolor.rgb; \n\
2068 dcolor.a *= tcolor.a; \n\
2070 dcolor.a = tcolor.a; \n\
2076uniform int material_side; //see renderfuncs reallydrawonce //0= front and back - no material difference, 1 = front 2=back\n\
2077//literal string size break \n" "\
2080//STEP0 MATERIALS \n\
2082 mtex_specular = castle_ColorES; \n\
2083 mtex_diffuse = castle_Color; \n\
2085 /* back Facing materials - flip the normal and grab back materials */ \n\
2086 if (gl_FrontFacing && material_side == 2) discard; \n\
2087 if(!gl_FrontFacing && material_side == 1) discard; \n\
2088 //if (!gl_FrontFacing){ //backFacing) { \n\
2089 mat = fw_FrontMaterial; \n\
2090 if(material_side == 2){ \n\
2092 mat = fw_BackMaterial; \n\
2095 vec3 N = getNormal(); \n\
2097//STEP1 INITIALIZE \n\
2098 vec4 fragment_color; \n\
2100 //lines are unlit (no lights) \n\
2101 vec4 dcolor = vec4(1.0); \n\
2102 dcolor.rgb = getEmissive(); \n\
2104 dcolor= getVertexColor(); \n\
2108 //if(textureCount > 0){ \n\
2109 int iuse = mat.type < 2 ? 1 : 3; \n\
2110 if(mat.tcount[iuse] > 0){ \n\
2111 vec3 N = getNormal(); \n\
2112 vec4 tcolor = vec4(1); \n\
2113 /* PLUG: texture_apply (tcolor, iuse) */ \n\
2114 if(u_pointColorMode == 1) dcolor.a = tcolor.a; \n\
2115 if(u_pointColorMode == 2) dcolor = tcolor; \n\
2116 if(u_pointColorMode == 3) { \n\
2117 dcolor.rgb += tcolor.rgb; \n\
2118 dcolor.a = tcolor.a;; \n\
2123 fragment_color = dcolor; \n\
2124 #if defined(LINETYPE) && defined(FULL) \n\
2125 if(u_linetype > 1) \n\
2126 if(!on_linetype(fragment_color)){ \n\
2128 //fragment_color.a = 0.0; \n\
2130 #endif //LINETYPE \n\
2133 //mostly 3D geometry \n\
2134 //vec4 diffuseFactor = getDiffuseFactor(); \n\
2135 //fragment_color = diffuseFactor; \n\
2138 // commandline freewrl --shadingStyle 1 (Gouraud) invokes this \n\
2139 //if(mat.type == 0){ \n\
2140 // as of June 2022 Background still going through here and mat.type = MAT_NONE is default in freewrl \n\
2141 fragment_color = getGouraudColor(); \n\
2143 #endif //not PHONG \n\
2146 // commandline freewrl --shadingStyle 2 (Phong, default if not specified) invokes this \n\
2147 if(mat.type == 0){ \n\
2148 // as of June 2022 Background still going through here and mat.type = MAT_NONE is default in freewrl \n\
2149 fragment_color = getGouraudColor(); \n\
2151 if(mat.type == 1) { \n\
2152 //MAT_UNLIT - no lighting \n\
2153 //fragment_color.rgb = getEmissive(); \n\
2154 //fragment_color.a = getAlpha(); \n\
2156 vec4 apriori = vec4(mat.emissive, 1.0-mat.transparency); \n\
2157 fragment_color = getMainColor(apriori,iuse); // getEmissive(); \n\
2158 //if the shape is using TextureCoordinateGenerator with some modes (CAMERASPACENORMAL, CAMERASPACEREFLECTIONVECTOR) \n\
2159 // .. then the shader code may need access to normals (where?) \n\
2160 // .. but not use here for lighting \n\
2163 //per-fragment lighting aka PHONG shading \n\
2164 if(mat.type == 2){ \n\
2165 //MAT_REGULAR aka phong lighting \n\
2167 //start over with the color, since we have material and lighting in here \n\
2168 vec3 cumulative_specular = vec3(0.0,0.0,0.0); \n\
2169 vec3 cumulative_diffuse = vec3(0.0,0.0,0.0); \n\
2170 fragment_color.a = getAlpha(); \n\
2171 float shiny = getShininess(); \n\
2172 float amby = getAmbient(); \n\
2173 vec4 apriori = vec4(mat.diffuse,1.0-mat.transparency); \n\
2175 fragment_color = getMainColor(apriori,iuse); \n\
2176 vec3 diffy = fragment_color.rgb; //getDiffuseFactor().rgb; //diffuseFactor.rgb; //\n\
2177 vec3 specy = getSpecular(); \n\
2178 vec3 normy = getNormal(); \n\
2179 float occy = getOcclusion(); \n\
2180 /* PLUG: add_light_contribution2 (cumulative_diffuse, cumulative_specular, castle_vertex_eye, normy, shiny, amby, diffy, specy) */ \n\
2181 fragment_color.rgb = cumulative_diffuse + cumulative_specular; \n\
2182 fragment_color.rgb *= occy; \n\
2183 //fragment_color.rgb = clamp(fragment_color.rgb,0.0,1.0); \n\
2185 fragment_color.rgb += getEmissive(); \n\
2186 } else if(mat.type == 3){ \n\
2187 //MAT_PHYSICAL aka physical lighting\n\
2188 fragment_color.a = getAlpha(); \n\
2190 float metallic = getMetallic(); \n\
2191 float perceptualRoughness = getRoughness(); \n\
2192 vec4 apriori = vec4(mat.baseColor,1.0-mat.transparency); \n\
2194 fragment_color = getMainColor(apriori,iuse); \n\
2195 vec3 baseColor = fragment_color.rgb; // getBaseColor(); \n\
2197 vec3 specularColor= vec3(0.0); \n\
2198 vec3 f0 = vec3(0.04); \n\
2199 // ?? baseColor *= getVertexColor().xyz; //hunh? \n\
2200 vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0) * (1.0 - metallic); \n\
2201 specularColor = mix(f0, baseColor.rgb, metallic); \n\
2203 float alphaRoughness = perceptualRoughness * perceptualRoughness; \n\
2204 // Compute reflectance. \n\
2205 float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); \n\
2206 vec3 specularEnvironmentR0 = specularColor.rgb; \n\
2207 // Anything less than 2% is physically impossible and is instead considered to be shadowing. \n\
2208 vec3 specularEnvironmentR90 = vec3(clamp(reflectance * 50.0, 0.0, 1.0)); \n\
2209 MaterialInfo materialInfo = MaterialInfo( \n\
2210 perceptualRoughness, \n\
2211 specularEnvironmentR0, \n\
2214 specularEnvironmentR90, \n\
2218 vec3 color = vec3(0.0, 0.0, 0.0); \n\
2219 vec3 normal = getNormal(); \n\
2220 vec3 view = normalize(- castle_vertex_eye.xyz); //hunh?? thought our v_Position was already in Eye space \n\
2221 float occy = getOcclusion(); \n\
2222 //color += apply_lights_physical( materialInfo, normal, view ); \n\
2223 /* PLUG: add_light_physical (color, castle_vertex_eye.xyz, normal, materialInfo ) */ \n\
2225 fragment_color.rgb = color; \n\
2227 fragment_color.rgb += getEmissive(); \n\
2232 //fillPropCalc(fragment_color, hatchPosition); \n\
2233 /* PLUG: fragment_fillPropertiesApply (fragment_color, hatchPosition) */ \n\
2236//STEP3 PROJECTORS AND IBL image based lighting \n\
2238 fragment_color = fragProjCalTexCoord(fragment_color); \n\
2239 #endif //PROJTEX \n\
2241 #endif //ndef LINE \n\
2243 /* PLUG: fog_apply (fragment_color, N) */ \n\
2245 fragment_color.rgb = LINEARtoSRGB(fragment_color.rgb); \n\
2246 FragColor = fragment_color; \n\
2248 /* PLUG: fragment_end (FragColor) */ \n\
2253static const GLchar *plug_fragment_fillProperties_apply =
"\
2255float either(float x, float y){ \n\
2256 //returns 1 if either are > 0, else 0 \n\
2257 return step(.5,x+y); \n\
2259float inrange(float curpos, float fx, float linewidth){ \n\
2260 //returns 1.0 if on line, else 0.0 \n\
2261 //return step(fx-linewidth*.5,curpos) - step(fx+linewidth*.5,curpos);; \n\
2262 //either in this cycle or (with +linewidth) the prior cycle \n\
2263 float fxfloor = floor(fx+linewidth); \n\
2264 //return step(ffx,curpos) - step(fract(ffx+linewidth),curpos); \n\
2265 return either(step(fx,curpos) - step(fx+linewidth,curpos),step(fx-fxfloor,curpos) - step(fx-fxfloor+linewidth,curpos)); \n\
2266 //return either(step(fx,curpos) - step(fx+linewidth,curpos),step(fx-1.0,curpos) - step(fx+linewidth-1.0,curpos)); \n\
2268float inrange3(float curpos, float fx, float linewidth, float cycle_height){ \n\
2269 //returns 1.0 if on line, else 0.0 \n\
2270 float inside = 0.0; \n\
2271 if(cycle_height < 1.0){ \n\
2272 float ncycle = 1.0/cycle_height; \n\
2273 int ny = int(ceil(ncycle)) +2; \n\
2274 for(int i=0;i<ny;i++){ \n\
2275 float ffx = fx + float(i-2)*cycle_height; \n\
2276 inside = either(inside,step(ffx,curpos)-step(ffx+linewidth,curpos)); \n\
2278 }else if(cycle_height > 1.0){ \n\
2279 float ncycle = cycle_height; \n\
2280 int ny = int(ceil(ncycle)) +1; \n\
2281 for(int i=0;i<ny;i++){ \n\
2282 float ffx = fx - float(i); \n\
2283 inside = either(inside,step(ffx,curpos)-step(ffx+linewidth,curpos)); \n\
2286 inside = either(step(fx,curpos) - step(fx+linewidth,curpos),step(fx-1.0,curpos) - step(fx+linewidth-1.0,curpos)); \n\
2290float rand(float n){return fract(sin(n) * 43758.5453123);} \n\
2291float noise(float p){ \n\
2292 float fl = floor(p); \n\
2293 float fc = fract(p); \n\
2294 return mix(rand(fl), rand(fl + 1.0), fc); \n\
2296float rand(vec2 c){ \n\
2297 return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453); \n\
2299//literal string size break \n" "\
2301void PLUG_fragment_fillPropertiesApply(inout vec4 prevColour, vec2 MCposition) { \n\
2302 // written as procedural texture \n\
2303 // http://learnwebgl.brown37.net/10_surface_properties/texture_mapping_procedural.html \n\
2304 // https://thebookofshaders.com/05/ \n\
2305 // https://isotc.iso.org/livelink/livelink/fetch/-8916524/8916549/8916590/6208440/class_pages/hatchstyle.html \n\
2306 // instead of y = f(x), you set fx = f(current_x)); (where y would need to be, to be on the line) \n\
2307 // then test if current_y is in range(fx-linewidth/2,fx+linewidth/2) \n\
2308 // the x and y are more conveniently processed in cycle-space if you have a repeating pattern \n\
2309 // so if your pattern repeats 10 times per 1 unit of texture coordinates, your cycle is 1/10 = .1 in size \n\
2311 vec2 position; // position in cycle, as cycle fraction \n\
2312 float cyclesize; //in texcoords \n\
2313 float linewidth; //in cycle space \n\
2314 position = MCposition; // /HatchScale; \n\
2315 vec2 percent = vec2(0); //fraction of background color to show, usually 1 or 0 \n\
2316 float fx; // f(x) evaluated at x = cyclepostion.x \n\
2317 float fxrange; //normally the pattern is square, if not fxrange is the height, assuming width is 1 \n\
2319 int ha = fillprops.HatchAlgo; \n\
2321 case 0: // horizontal lines \n\
2325 position = fract(MCposition/cyclesize); \n\
2327 percent.x = 1.0 - inrange(position.y,fx,linewidth); \n\
2329 case 2: // vertical lines \n\
2332 position = fract(MCposition/cyclesize); \n\
2334 percent.x = 1.0 - inrange(position.x,fx,linewidth); \n\
2336 case 3: // positive diagonals \n\
2339 position = fract(MCposition/cyclesize); \n\
2340 fx = position.x; \n\
2341 percent.x = 1.0 - inrange(position.y,fx,linewidth); \n\
2343 case 4: //negative diagonals \n\
2346 position = fract(MCposition/cyclesize); \n\
2347 fx = 1.0-position.x; \n\
2348 percent.x = 1.0 - inrange(position.y,fx,linewidth); \n\
2350 case 5: // # hv cross hatching \n\
2352 linewidth = .25; \n\
2353 position = fract(MCposition/cyclesize); \n\
2355 percent.y = inrange(position.y,fx,linewidth); \n\
2356 percent.x = inrange(position.x,fx,linewidth); \n\
2357 percent.x = 1.0 - either(percent.x, percent.y); \n\
2359 case 6: // diagonal crosshatch \n\
2361 linewidth = .25; \n\
2362 position = fract(MCposition/cyclesize); \n\
2363 fx = position.x; \n\
2364 percent.x = inrange(position.y,fx,linewidth); \n\
2365 fx = 1.0-position.x; \n\
2366 percent.y = inrange(position.y,fx,linewidth); \n\
2367 percent.x = 1.0 - either(percent.x,percent.y); \n\
2369 case 7: //7 positive diagonals wide \n\
2371 linewidth = .25; \n\
2372 position = fract(MCposition/cyclesize); \n\
2373 fx = position.x; \n\
2374 percent.x = 1.0 - inrange(position.y,fx,linewidth); \n\
2376 case 8: //8 double positive diagonals, candycane \n\
2378 linewidth = .15; \n\
2379 position = fract(MCposition/cyclesize); \n\
2380 fx = position.x; \n\
2381 percent.x = inrange(position.y,fx,linewidth); \n\
2383 linewidth = .15; \n\
2384 position = fract(MCposition/cyclesize); \n\
2385 fx = position.x + .25; \n\
2386 percent.y = inrange(position.y,fx,linewidth); \n\
2387 percent.x = 1.0 - either(percent.x,percent.y); \n\
2389 case 9: //9 positive diagonal dash-diagonal \n\
2390 //solid diagonal \n\
2392 linewidth = .15; \n\
2393 position = fract(MCposition/cyclesize); \n\
2394 fx = position.x; \n\
2395 percent.x = inrange(position.y,fx,linewidth); \n\
2396 //dash it with negative diagonal \n\
2399 fx = 1.0 - position.x; \n\
2400 percent.y = inrange(position.y,fx,linewidth); \n\
2401 percent.x = percent.x*percent.y; \n\
2402 //solid diagonal \n\
2404 linewidth = .15; \n\
2405 position = fract(MCposition/cyclesize); \n\
2406 fx = position.x + .5; \n\
2407 percent.y = inrange(position.y,fx,linewidth); \n\
2408 percent.x = 1.0 - either(percent.x,percent.y); \n\
2410 case 10: //10 wide diagonal crosshatch \n\
2413 position = fract(MCposition/cyclesize); \n\
2414 fx = position.x; \n\
2415 percent.x = inrange(position.y,fx,linewidth); \n\
2416 fx = 1.0-position.x; \n\
2417 percent.y = inrange(position.y,fx,linewidth); \n\
2418 percent.x = 1.0 - either(percent.x,percent.y); \n\
2420 case 11: //11 positive diagonal railroad \n\
2421 //negative diagonal for railroad ties \n\
2423 linewidth = .15; \n\
2424 position = fract(MCposition/cyclesize); \n\
2425 fx = 1.0 - position.x; \n\
2426 percent.x = inrange(position.y,fx,linewidth); \n\
2427 //dash it with positive diagonal \n\
2430 fx = position.x; \n\
2431 percent.y = inrange(position.y,fx,linewidth); \n\
2432 percent.x = percent.x*percent.y; \n\
2433 //HV cross hatch to remove every second tie \n\
2436 position = fract(MCposition/cyclesize); \n\
2438 percent.y = inrange(position.y,fx,linewidth); \n\
2439 percent.x = percent.x*percent.y; \n\
2440 //add solid diagonals \n\
2442 linewidth = .25; \n\
2443 position = fract(MCposition/cyclesize); \n\
2444 fx = position.x + .5; \n\
2445 percent.y = inrange(position.y,fx,linewidth); \n\
2446 percent.x = 1.0 - either(percent.x,percent.y); \n\
2448 case 12: // 12 4 +diag, 4 spaces \n\
2452 position = fract(MCposition/cyclesize); \n\
2453 fx = position.x; \n\
2454 percent.x = inrange(position.y,fx,linewidth); \n\
2455 //remove diagonals \n\
2458 position = fract(MCposition/cyclesize); \n\
2459 fx = position.x; \n\
2460 percent.y = inrange(position.y,fx,linewidth); \n\
2461 percent.x = 1.0 - percent.x*percent.y; \n\
2463 case 13: //13 cork horizontal dashes \n\
2466 linewidth = .25; \n\
2467 position = fract(MCposition/cyclesize); \n\
2469 percent.x = inrange(position.y,fx,linewidth); \n\
2470 //dash using +ve diags \n\
2472 linewidth = .25; \n\
2473 position = fract(MCposition/cyclesize); \n\
2474 fx = .5 * position.x; \n\
2475 fxrange = .5 * 1.0; \n\
2476 percent.y = 1.0 - inrange3(position.y,fx,linewidth,fxrange); \n\
2477 percent.x = 1.0 - percent.x*percent.y; \n\
2479 case 14: //steps over +ve diags \n\
2480 //HV grid for steps \n\
2482 linewidth = .25; \n\
2483 position = fract(MCposition/cyclesize); \n\
2485 percent.y = inrange(position.y,fx,linewidth); \n\
2486 percent.x = inrange(position.x,fx,linewidth); \n\
2487 percent.x = either(percent.x, percent.y); \n\
2488 //clear out parts of grid with +ve diag \n\
2490 linewidth = .45; \n\
2491 position = fract(MCposition/cyclesize); \n\
2492 fx = position.x + .52; \n\
2493 percent.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2494 percent.x = percent.x*percent.y; \n\
2495 //add +ve diag over steps \n\
2497 linewidth = .15; \n\
2498 position = fract(MCposition/cyclesize); \n\
2499 fx = position.x + .2; \n\
2500 percent.y = inrange(position.y,fx,linewidth); \n\
2501 percent.x = 1.0 - either(percent.x,percent.y); \n\
2503 case 15: // titaniaum diag diag-dash diag \n\
2504 //diagonal for dashing \n\
2506 linewidth = .05; \n\
2507 position = fract(MCposition/cyclesize); \n\
2508 fx = position.x + .25; \n\
2509 percent.x = inrange(position.y,fx,linewidth); \n\
2510 //dash with negative diagonal \n\
2513 position = fract(MCposition/cyclesize); \n\
2514 fx = 1.0 - position.x; \n\
2515 percent.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2516 percent.x = percent.x*percent.y; \n\
2517 //solid diagonals \n\
2520 position = fract(MCposition/cyclesize); \n\
2521 fx = position.x; \n\
2522 percent.y = inrange(position.y,fx,linewidth); \n\
2523 percent.x = 1.0 - either(percent.x,percent.y); \n\
2525 case 16: //marble diag-dash \n\
2526 //diagonal for dashing \n\
2529 position = fract(MCposition/cyclesize); \n\
2530 fx = position.x; \n\
2531 percent.x = inrange(position.y,fx,linewidth); \n\
2532 //dash with negative diagonal \n\
2535 position = fract(MCposition/cyclesize); \n\
2536 fx = 1.0 - position.x; \n\
2537 percent.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2538 percent.x = 1.0 - percent.x*percent.y; \n\
2540 case 17: //earth 5 diags erasing -ve diags \n\
2541 //negaative diags \n\
2544 position = fract(MCposition/cyclesize); \n\
2545 fx = 1.0 - .5*position.x; \n\
2546 fxrange = 1.0 - .5*1.0; \n\
2547 percent.x = inrange3(position.y,fx,linewidth,fxrange); \n\
2548 //clear gaps with thick +ve diags \n\
2551 position = fract(MCposition/cyclesize); \n\
2552 fx = position.x; \n\
2553 percent.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2554 percent.x = percent.x*percent.y; \n\
2555 // add 5 diagonals in gap \n\
2556 vec2 percent2 = vec2(0.0); \n\
2558 cyclesize = .05; \n\
2560 position = fract(MCposition/cyclesize); \n\
2561 fx = position.x; \n\
2562 percent2.x = inrange(position.y,fx,linewidth); \n\
2563 //remove diagonals \n\
2566 position = fract(MCposition/cyclesize); \n\
2567 fx = position.x +.5; \n\
2568 percent2.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2569 percent2.x = percent2.x*percent2.y; \n\
2570 percent.x = 1.0 - either(percent.x,percent2.x); \n\
2572 case 18: //sand randcom dots \n\
2573 cyclesize = 1.0; \n\
2575 position = fract(MCposition/cyclesize); \n\
2576 fx = rand(position); \n\
2577 position.x = linewidth*floor(position.x/linewidth); \n\
2578 //fx = noise(position.x*position.y); \n\
2579 percent.x = inrange(position.y,fx,linewidth); \n\
2580 percent.y = inrange(position.x,fx,linewidth); \n\
2581 percent.x = 1.0 - either(percent.x,percent.y); \n\
2583 case 19: //repeating stanggerd rows of dots \n\
2584 // use a find diagonal crosshatch \n\
2585 cyclesize = .05; \n\
2587 position = fract(MCposition/cyclesize); \n\
2588 fx = position.x; \n\
2589 percent.x = inrange(position.y,fx,linewidth); \n\
2590 fx = 1.0-position.x; \n\
2591 percent.y = inrange(position.y,fx,linewidth); \n\
2592 percent.x = either(percent.x,percent.y); \n\
2596 if (fillprops.filled) {colour = prevColour;} else { colour=vec4(0.,0.,0.,0); }\n\
2597 if (fillprops.hatched) { \n\
2598 //colour = mix(fillprops.HatchColour, colour, useBrick.x * useBrick.y); \n\
2599 colour = mix(fillprops.HatchColour, colour, percent.x ); \n\
2601 prevColour = colour; \n\
2605static const GLchar *plug_fragment_fillProperties_apply_120 =
"\
2607float either(float x, float y){ \n\
2608 //returns 1 if either are > 0, else 0 \n\
2609 return step(.5,x+y); \n\
2611float inrange(float curpos, float fx, float linewidth){ \n\
2612 //returns 1.0 if on line, else 0.0 \n\
2613 //return step(fx-linewidth*.5,curpos) - step(fx+linewidth*.5,curpos);; \n\
2614 //either in this cycle or (with +linewidth) the prior cycle \n\
2615 float fxfloor = floor(fx+linewidth); \n\
2616 //return step(ffx,curpos) - step(fract(ffx+linewidth),curpos); \n\
2617 return either(step(fx,curpos) - step(fx+linewidth,curpos),step(fx-fxfloor,curpos) - step(fx-fxfloor+linewidth,curpos)); \n\
2618 //return either(step(fx,curpos) - step(fx+linewidth,curpos),step(fx-1.0,curpos) - step(fx+linewidth-1.0,curpos)); \n\
2620float inrange3(float curpos, float fx, float linewidth, float cycle_height){ \n\
2621 //returns 1.0 if on line, else 0.0 \n\
2622 float inside = 0.0; \n\
2623 if(cycle_height < 1.0){ \n\
2624 float ncycle = 1.0/cycle_height; \n\
2625 int ny = int(ceil(ncycle)) +2; \n\
2626 for(int i=0;i<ny;i++){ \n\
2627 float ffx = fx + float(i-2)*cycle_height; \n\
2628 inside = either(inside,step(ffx,curpos)-step(ffx+linewidth,curpos)); \n\
2630 }else if(cycle_height > 1.0){ \n\
2631 float ncycle = cycle_height; \n\
2632 int ny = int(ceil(ncycle)) +1; \n\
2633 for(int i=0;i<ny;i++){ \n\
2634 float ffx = fx - float(i); \n\
2635 inside = either(inside,step(ffx,curpos)-step(ffx+linewidth,curpos)); \n\
2638 inside = either(step(fx,curpos) - step(fx+linewidth,curpos),step(fx-1.0,curpos) - step(fx+linewidth-1.0,curpos)); \n\
2642float rand(float n){return fract(sin(n) * 43758.5453123);} \n\
2643float noise(float p){ \n\
2644 float fl = floor(p); \n\
2645 float fc = fract(p); \n\
2646 return mix(rand(fl), rand(fl + 1.0), fc); \n\
2648float rand(vec2 c){ \n\
2649 return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453); \n\
2651//literal string size break \n" "\
2653//literal string size break \n" "\
2654void PLUG_fragment_fillPropertiesApply(inout vec4 prevColour, vec2 MCposition) { \n\
2655 // written as procedural texture \n\
2656 // http://learnwebgl.brown37.net/10_surface_properties/texture_mapping_procedural.html \n\
2657 // https://thebookofshaders.com/05/ \n\
2658 // https://isotc.iso.org/livelink/livelink/fetch/-8916524/8916549/8916590/6208440/class_pages/hatchstyle.html \n\
2659 // instead of y = f(x), you set fx = f(current_x)); (where y would need to be, to be on the line) \n\
2660 // then test if current_y is in range(fx-linewidth/2,fx+linewidth/2) \n\
2661 // the x and y are more conveniently processed in cycle-space if you have a repeating pattern \n\
2662 // so if your pattern repeats 10 times per 1 unit of texture coordinates, your cycle is 1/10 = .1 in size \n\
2664 vec2 position; // position in cycle, as cycle fraction \n\
2665 float cyclesize; //in texcoords \n\
2666 float linewidth; //in cycle space \n\
2667 position = MCposition; // /HatchScale; \n\
2668 vec2 percent = vec2(0); //fraction of background color to show, usually 1 or 0 \n\
2669 float fx; // f(x) evaluated at x = cyclepostion.x \n\
2670 float fxrange; //normally the pattern is square, if not fxrange is the height, assuming width is 1 \n\
2672 int ha = fillprops.HatchAlgo; \n\
2676 if(ha < 2) { // horizontal lines \n\
2680 position = fract(MCposition/cyclesize); \n\
2682 percent.x = 1.0 - inrange(position.y,fx,linewidth); \n\
2683 }else if(ha == 2) { \n\
2684 //case 2: // vertical lines \n\
2687 position = fract(MCposition/cyclesize); \n\
2689 percent.x = 1.0 - inrange(position.x,fx,linewidth); \n\
2693 //case 3: // positive diagonals \n\
2696 position = fract(MCposition/cyclesize); \n\
2697 fx = position.x; \n\
2698 percent.x = 1.0 - inrange(position.y,fx,linewidth); \n\
2700 //case 4: //negative diagonals \n\
2703 position = fract(MCposition/cyclesize); \n\
2704 fx = 1.0-position.x; \n\
2705 percent.x = 1.0 - inrange(position.y,fx,linewidth); \n\
2707 } //if else ha < 3 \n\
2711 //case 5: // # hv cross hatching \n\
2713 linewidth = .25; \n\
2714 position = fract(MCposition/cyclesize); \n\
2716 percent.y = inrange(position.y,fx,linewidth); \n\
2717 percent.x = inrange(position.x,fx,linewidth); \n\
2718 percent.x = 1.0 - either(percent.x, percent.y); \n\
2719 }else if(ha==6){ \n\
2720 //case 6: // diagonal crosshatch \n\
2722 linewidth = .25; \n\
2723 position = fract(MCposition/cyclesize); \n\
2724 fx = position.x; \n\
2725 percent.x = inrange(position.y,fx,linewidth); \n\
2726 fx = 1.0-position.x; \n\
2727 percent.y = inrange(position.y,fx,linewidth); \n\
2728 percent.x = 1.0 - either(percent.x,percent.y); \n\
2729 }else if(ha==7){ \n\
2730 //case 7: //7 positive diagonals wide \n\
2732 linewidth = .25; \n\
2733 position = fract(MCposition/cyclesize); \n\
2734 fx = position.x; \n\
2735 percent.x = 1.0 - inrange(position.y,fx,linewidth); \n\
2739 //case 8: //8 double positive diagonals, candycane \n\
2741 linewidth = .15; \n\
2742 position = fract(MCposition/cyclesize); \n\
2743 fx = position.x; \n\
2744 percent.x = inrange(position.y,fx,linewidth); \n\
2746 linewidth = .15; \n\
2747 position = fract(MCposition/cyclesize); \n\
2748 fx = position.x + .25; \n\
2749 percent.y = inrange(position.y,fx,linewidth); \n\
2750 percent.x = 1.0 - either(percent.x,percent.y); \n\
2751 }else if(ha==9) { \n\
2752 //case 9: //9 positive diagonal dash-diagonal \n\
2753 //solid diagonal \n\
2755 linewidth = .15; \n\
2756 position = fract(MCposition/cyclesize); \n\
2757 fx = position.x; \n\
2758 percent.x = inrange(position.y,fx,linewidth); \n\
2759 //dash it with negative diagonal \n\
2762 fx = 1.0 - position.x; \n\
2763 percent.y = inrange(position.y,fx,linewidth); \n\
2764 percent.x = percent.x*percent.y; \n\
2765 //solid diagonal \n\
2767 linewidth = .15; \n\
2768 position = fract(MCposition/cyclesize); \n\
2769 fx = position.x + .5; \n\
2770 percent.y = inrange(position.y,fx,linewidth); \n\
2771 percent.x = 1.0 - either(percent.x,percent.y); \n\
2773 } //if-else ha < 8 \n\
2774 } // if-else ha < 5 \n\
2775 } else { //ha<10 \n\
2779 //case 10: //10 wide diagonal crosshatch \n\
2782 position = fract(MCposition/cyclesize); \n\
2783 fx = position.x; \n\
2784 percent.x = inrange(position.y,fx,linewidth); \n\
2785 fx = 1.0-position.x; \n\
2786 percent.y = inrange(position.y,fx,linewidth); \n\
2787 percent.x = 1.0 - either(percent.x,percent.y); \n\
2788 }else if(ha==11){ \n\
2789 //case 11: //11 positive diagonal railroad \n\
2790 //negative diagonal for railroad ties \n\
2792 linewidth = .15; \n\
2793 position = fract(MCposition/cyclesize); \n\
2794 fx = 1.0 - position.x; \n\
2795 percent.x = inrange(position.y,fx,linewidth); \n\
2796 //dash it with positive diagonal \n\
2799 fx = position.x; \n\
2800 percent.y = inrange(position.y,fx,linewidth); \n\
2801 percent.x = percent.x*percent.y; \n\
2802 //HV cross hatch to remove every second tie \n\
2805 position = fract(MCposition/cyclesize); \n\
2807 percent.y = inrange(position.y,fx,linewidth); \n\
2808 percent.x = percent.x*percent.y; \n\
2809 //add solid diagonals \n\
2811 linewidth = .25; \n\
2812 position = fract(MCposition/cyclesize); \n\
2813 fx = position.x + .5; \n\
2814 percent.y = inrange(position.y,fx,linewidth); \n\
2815 percent.x = 1.0 - either(percent.x,percent.y); \n\
2816 }else if(ha==12){ \n\
2817 //case 12: // 12 4 +diag, 4 spaces \n\
2821 position = fract(MCposition/cyclesize); \n\
2822 fx = position.x; \n\
2823 percent.x = inrange(position.y,fx,linewidth); \n\
2824 //remove diagonals \n\
2827 position = fract(MCposition/cyclesize); \n\
2828 fx = position.x; \n\
2829 percent.y = inrange(position.y,fx,linewidth); \n\
2830 percent.x = 1.0 - percent.x*percent.y; \n\
2832 } else { //ha < 13 \n\
2834 //case 13: //13 cork horizontal dashes \n\
2837 linewidth = .25; \n\
2838 position = fract(MCposition/cyclesize); \n\
2840 percent.x = inrange(position.y,fx,linewidth); \n\
2841 //dash using +ve diags \n\
2843 linewidth = .25; \n\
2844 position = fract(MCposition/cyclesize); \n\
2845 fx = .5 * position.x; \n\
2846 fxrange = .5 * 1.0; \n\
2847 percent.y = 1.0 - inrange3(position.y,fx,linewidth,fxrange); \n\
2848 percent.x = 1.0 - percent.x*percent.y; \n\
2850 //case 14: //steps over +ve diags \n\
2851 //HV grid for steps \n\
2853 linewidth = .25; \n\
2854 position = fract(MCposition/cyclesize); \n\
2856 percent.y = inrange(position.y,fx,linewidth); \n\
2857 percent.x = inrange(position.x,fx,linewidth); \n\
2858 percent.x = either(percent.x, percent.y); \n\
2859 //clear out parts of grid with +ve diag \n\
2861 linewidth = .45; \n\
2862 position = fract(MCposition/cyclesize); \n\
2863 fx = position.x + .52; \n\
2864 percent.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2865 percent.x = percent.x*percent.y; \n\
2866 //add +ve diag over steps \n\
2868 linewidth = .15; \n\
2869 position = fract(MCposition/cyclesize); \n\
2870 fx = position.x + .2; \n\
2871 percent.y = inrange(position.y,fx,linewidth); \n\
2872 percent.x = 1.0 - either(percent.x,percent.y); \n\
2874 } //if-else ha < 13 \n\
2875 } else { //ha < 15 \n\
2878 //case 15: // titaniaum diag diag-dash diag \n\
2879 //diagonal for dashing \n\
2881 linewidth = .05; \n\
2882 position = fract(MCposition/cyclesize); \n\
2883 fx = position.x + .25; \n\
2884 percent.x = inrange(position.y,fx,linewidth); \n\
2885 //dash with negative diagonal \n\
2888 position = fract(MCposition/cyclesize); \n\
2889 fx = 1.0 - position.x; \n\
2890 percent.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2891 percent.x = percent.x*percent.y; \n\
2892 //solid diagonals \n\
2895 position = fract(MCposition/cyclesize); \n\
2896 fx = position.x; \n\
2897 percent.y = inrange(position.y,fx,linewidth); \n\
2898 percent.x = 1.0 - either(percent.x,percent.y); \n\
2899 }else if(ha == 16) { \n\
2900 //case 16: //marble diag-dash \n\
2901 //diagonal for dashing \n\
2904 position = fract(MCposition/cyclesize); \n\
2905 fx = position.x; \n\
2906 percent.x = inrange(position.y,fx,linewidth); \n\
2907 //dash with negative diagonal \n\
2910 position = fract(MCposition/cyclesize); \n\
2911 fx = 1.0 - position.x; \n\
2912 percent.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2913 percent.x = 1.0 - percent.x*percent.y; \n\
2914 } else if(ha == 17) { \n\
2915 //case 17: //earth 5 diags erasing -ve diags \n\
2916 //negaative diags \n\
2919 position = fract(MCposition/cyclesize); \n\
2920 fx = 1.0 - .5*position.x; \n\
2921 fxrange = 1.0 - .5*1.0; \n\
2922 percent.x = inrange3(position.y,fx,linewidth,fxrange); \n\
2923 //clear gaps with thick +ve diags \n\
2926 position = fract(MCposition/cyclesize); \n\
2927 fx = position.x; \n\
2928 percent.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2929 percent.x = percent.x*percent.y; \n\
2930 // add 5 diagonals in gap \n\
2931 vec2 percent2 = vec2(0.0); \n\
2933 cyclesize = .05; \n\
2935 position = fract(MCposition/cyclesize); \n\
2936 fx = position.x; \n\
2937 percent2.x = inrange(position.y,fx,linewidth); \n\
2938 //remove diagonals \n\
2941 position = fract(MCposition/cyclesize); \n\
2942 fx = position.x +.5; \n\
2943 percent2.y = 1.0 - inrange(position.y,fx,linewidth); \n\
2944 percent2.x = percent2.x*percent2.y; \n\
2945 percent.x = 1.0 - either(percent.x,percent2.x); \n\
2947 }else{ //ha < 18 \n\
2949 //case 18: //sand randcom dots \n\
2950 cyclesize = 1.0; \n\
2952 position = fract(MCposition/cyclesize); \n\
2953 fx = rand(position); \n\
2954 position.x = linewidth*floor(position.x/linewidth); \n\
2955 //fx = noise(position.x*position.y); \n\
2956 percent.x = inrange(position.y,fx,linewidth); \n\
2957 percent.y = inrange(position.x,fx,linewidth); \n\
2958 percent.x = 1.0 - either(percent.x,percent.y); \n\
2959 } else if(ha == 19) { \n\
2960 //case 19: //repeating stanggerd rows of dots \n\
2961 // use a find diagonal crosshatch \n\
2962 cyclesize = .05; \n\
2964 position = fract(MCposition/cyclesize); \n\
2965 fx = position.x; \n\
2966 percent.x = inrange(position.y,fx,linewidth); \n\
2967 fx = 1.0-position.x; \n\
2968 percent.y = inrange(position.y,fx,linewidth); \n\
2969 percent.x = either(percent.x,percent.y); \n\
2971 } //if-else ha < 18 \n\
2972 } //if-else ha < 15 \n\
2973 } //if-else ha < 10 \n\
2975 if (fillprops.filled) {colour = prevColour;} else { colour=vec4(0.,0.,0.,0); }\n\
2976 if (fillprops.hatched) { \n\
2977 //colour = mix(fillprops.HatchColour, colour, useBrick.x * useBrick.y); \n\
2978 colour = mix(fillprops.HatchColour, colour, percent.x ); \n\
2980 prevColour = colour; \n\
2986static const GLchar *plug_finalColCalc =
"\
2987#if defined(MTEX) || defined(PROJTEX) \n\
2988#define MTMODE_ADD 1\n \
2989#define MTMODE_ADDSIGNED 2\n \
2990#define MTMODE_ADDSIGNED2X 3\n \
2991#define MTMODE_ADDSMOOTH 4\n \
2992#define MTMODE_BLENDCURRENTALPHA 5\n \
2993#define MTMODE_BLENDDIFFUSEALPHA 6\n \
2994#define MTMODE_BLENDFACTORALPHA 7\n \
2995#define MTMODE_BLENDTEXTUREALPHA 8\n \
2996#define MTMODE_DOTPRODUCT3 9\n \
2997#define MTMODE_MODULATE 10\n \
2998#define MTMODE_MODULATE2X 11\n \
2999#define MTMODE_MODULATE4X 12\n \
3000#define MTMODE_MODULATEALPHA_ADDCOLOR 13\n \
3001#define MTMODE_MODULATEINVALPHA_ADDCOLOR 14\n \
3002#define MTMODE_MODULATEINVCOLOR_ADDALPHA 15\n \
3003#define MTMODE_OFF 16\n \
3004#define MTMODE_REPLACE 17\n \
3005#define MTMODE_SELECTARG1 18\n \
3006#define MTMODE_SELECTARG2 19\n \
3007#define MTMODE_SUBTRACT 20\n \
3008#define MTSRC_DIFFUSE 1 \n\
3009#define MTSRC_FACTOR 2 \n\
3010#define MTSRC_SPECULAR 3 \n\
3011#define MTFN_ALPHAREPLICATE 0 \n\
3012#define MTFN_COMPLEMENT 1 \n\
3013#define MT_DEFAULT -1 \n\
3015void PLUG_finalColCalc0(inout vec4 prevColour, in int mode, in int modea, in int func, in vec4 texel) { \n\
3016 vec4 rv = vec4(1.,0.,1.,1.); \n\
3017 if (mode==MTMODE_OFF) { \n\
3018 rv = vec4(prevColour); \n\
3019 } else if (mode==MTMODE_REPLACE) { \n\
3021 }else if (mode==MTMODE_MODULATE) { \n\
3024 cf = prevColour.rgb; \n\
3025 af = prevColour.a; \n\
3028 rv = vec4(ct*cf, at*af); \n\
3029 } else if (mode==MTMODE_MODULATE2X) { \n\
3032 cf = prevColour.rgb; \n\
3033 af = prevColour.a; \n\
3036 rv = vec4(vec4(ct*cf, at*af)*vec4(2.,2.,2.,2.)); \n\
3037 }else if (mode==MTMODE_MODULATE4X) { \n\
3040 cf = prevColour.rgb; \n\
3041 af = prevColour.a; \n\
3044 rv = vec4(vec4(ct*cf, at*af)*vec4(4.,4.,4.,4.)); \n\
3045 }else if (mode== MTMODE_ADDSIGNED) { \n\
3046 rv = vec4 (prevColour + texel - vec4 (0.5, 0.5, 0.5, -.5)); \n\
3047 } else if (mode== MTMODE_ADDSIGNED2X) { \n\
3048 rv = vec4 ((prevColour + texel - vec4 (0.5, 0.5, 0.5, -.5))*vec4(2.,2.,2.,2.)); \n\
3049 } else if (mode== MTMODE_ADD) { \n\
3050 rv= vec4 (prevColour + texel); \n\
3051 } else if (mode== MTMODE_SUBTRACT) { \n\
3052 rv = vec4 (texel - prevColour); //jas had prev - tex \n\
3053 } else if (mode==MTMODE_ADDSMOOTH) { \n\
3054 rv = vec4 (prevColour + (prevColour - vec4 (1.,1.,1.,1.)) * texel); \n\
3055 } else if (mode==MTMODE_BLENDDIFFUSEALPHA) { \n\
3056 rv = vec4 (mix(prevColour,texel,castle_Color.a)); \n\
3057 } else if (mode==MTMODE_BLENDTEXTUREALPHA) { \n\
3058 rv = vec4 (mix(prevColour,texel,texel.a)); \n\
3059 } else if (mode==MTMODE_BLENDFACTORALPHA) { \n\
3060 rv = vec4 (mix(prevColour,texel,mt_Color.a)); \n\
3061 } else if (mode==MTMODE_BLENDCURRENTALPHA) { \n\
3062 rv = vec4 (mix(prevColour,texel,prevColour.a)); \n\
3063 } else if (mode==MTMODE_SELECTARG1) { \n\
3065 } else if (mode==MTMODE_SELECTARG2) { \n\
3066 rv = prevColour; \n\
3069 if (modea==MTMODE_OFF) { \n\
3070 rv.a = prevColour.a; \n\
3071 } else if (modea==MTMODE_REPLACE) { \n\
3073 }else if (modea==MTMODE_MODULATE) { \n\
3075 af = prevColour.a; \n\
3078 } else if (modea==MTMODE_MODULATE2X) { \n\
3080 af = prevColour.a; \n\
3082 rv.a = at*af*2.0; \n\
3083 }else if (modea==MTMODE_MODULATE4X) { \n\
3085 af = prevColour.a; \n\
3087 rv.a = at*af*4.0; \n\
3088 }else if (modea== MTMODE_ADDSIGNED) { \n\
3089 rv.a = (prevColour.a + texel.a + .5); \n\
3090 } else if (modea== MTMODE_ADDSIGNED2X) { \n\
3091 rv.a = ((prevColour.a + texel.a + .5))*2.0; \n\
3092 } else if (modea== MTMODE_ADD) { \n\
3093 rv.a = prevColour.a + texel.a; \n\
3094 } else if (modea== MTMODE_SUBTRACT) { \n\
3095 rv.a = texel.a - prevColour.a; //jas had prev - texel \n\
3096 } else if (modea==MTMODE_ADDSMOOTH) { \n\
3097 rv.a = (prevColour.a + (prevColour.a - 1.)) * texel.a; \n\
3098 } else if (modea==MTMODE_BLENDDIFFUSEALPHA) { \n\
3099 rv.a = mix(prevColour.a,texel.a,castle_Color.a); \n\
3100 } else if (modea==MTMODE_BLENDTEXTUREALPHA) { \n\
3101 rv.a = mix(prevColour.a,texel.a,texel.a); \n\
3102 } else if (modea==MTMODE_BLENDFACTORALPHA) { \n\
3103 rv.a = mix(prevColour.a,texel.a,mt_Color.a); \n\
3104 } else if (modea==MTMODE_BLENDCURRENTALPHA) { \n\
3105 rv.a = mix(prevColour.a,texel.a,prevColour.a); \n\
3106 } else if (modea==MTMODE_SELECTARG1) { \n\
3108 } else if (modea==MTMODE_SELECTARG2) { \n\
3109 rv.a = prevColour.a; \n\
3112 if(func == MTFN_COMPLEMENT){ \n\
3113 //rv = vec4(1.0,1.0,1.0,1.0) - rv; \n\
3114 rv = vec4( vec3(1.0,1.0,1.0) - rv.rgb, rv.a); \n\
3115 }else if(func == MTFN_ALPHAREPLICATE){ \n\
3116 rv = vec4(rv.a,rv.a,rv.a,rv.a); \n\
3118 prevColour = rv; \n\
3120#endif //defined(MTEX) || defined(PROJTEX) \n\
3121#if defined(MTEXA) || defined(PROJTEX) \n\
3122void PLUG_finalColCalc(inout vec4 prevColour, in int mode, in int modea, in int func, in sampler2D tex, in vec2 texcoord) { \n\
3123 vec4 texel = texture2D(tex,texcoord); \n\
3124 PLUG_finalColCalc0(prevColour, mode, modea, func, texel); \n\
3126#endif //defined(MTEX) || defined(PROJTEX) \n";
3131const char *getGenericVertex(
void){
3132 return genericVertexGLES2;
3134const char *getGenericFragment(){
3135 return genericFragmentGLES2;
3137#include "../scenegraph/Component_Shape.h"
3139static const GLchar *plug_fragment_end_anaglyph =
"\
3140void PLUG_fragment_end (inout vec4 finalFrag){ \n\
3141 float gray = dot(finalFrag.rgb, vec3(0.299, 0.587, 0.114)); \n\
3142 finalFrag = vec4(gray,gray,gray, finalFrag.a); \n\
3184static const GLchar *plug_fragment_texture3D_apply_volume_uber =
"\n\
3185vec4 texture3Demu0( sampler2D sampler, in vec3 texcoord3, in int magfilter){ \n\
3186 vec4 rgba = vec4(0.0); \n\
3188 //TILED method (vs Y strip method) \n\
3189 vec3 texcoord = texcoord3; \n\
3190 //texcoord.z = 1.0 - texcoord.z; //flip z from RHS to LHS\n\
3191 float depth = max(1.0,float(tex3dTiles[2])); \n\
3192 if(repeatSTR[0] == 0) texcoord.x = clamp(texcoord.x,0.0001,.9999); \n\
3193 else texcoord.x = mod(texcoord.x,1.0); \n\
3194 if(repeatSTR[1] == 0) texcoord.y = clamp(texcoord.y,0.0001,.9999); \n\
3195 else texcoord.y = mod(texcoord.y,1.0); \n\
3196 if(repeatSTR[2] == 0) texcoord.z = clamp(texcoord.z,0.0001,.9999); \n\
3197 else texcoord.z = mod(texcoord.z,1.0); \n\
3199 int izf = int(floor(texcoord.z*depth)); //floor z \n\
3200 int izc = int(ceil(texcoord.z*depth)); //ceiling z \n\
3201 izc = izc == tex3dTiles[2] ? izc - 1 : izc; //clamp int z \n\
3202 vec4 ftexel, ctexel; \n\
3204 int nx = tex3dTiles[0]; //0-11 \n\
3205 int ny = tex3dTiles[1]; \n\
3206 float fnx = 1.0/float(nx); //.1\n\
3207 float fny = 1.0/float(ny); \n\
3208 int ix = izc / ny; //60/11=5\n\
3209 int ixny = ix * ny; //5*11=55\n\
3210 int iy = izc - ixny; //60-55=5 modulus remainder \n\
3211 float cix = float(ix); //5 \n\
3212 float ciy = float(iy); \n\
3213 float xxc = (cix + texcoord.s)*fnx; //(5 + .5)*.1 = .55\n\
3214 float yyc = (ciy + texcoord.t)*fny; \n\
3217 iy = izf - ixny; //modulus remainder \n\
3218 float fix = float(ix); \n\
3219 float fiy = float(iy); \n\
3220 float xxf = (fix + texcoord.s)*fnx; \n\
3221 float yyf = (fiy + texcoord.t)*fny; \n\
3223 vec2 ftexcoord, ctexcoord; //texcoord is 3D, ftexcoord and ctexcoord are 2D coords\n\
3224 ftexcoord.s = xxf; \n\
3225 ftexcoord.t = yyf; \n\
3226 ctexcoord.s = xxc; \n\
3227 ctexcoord.t = yyc; \n\
3228 ftexel = texture2D(sampler,ftexcoord.st); \n\
3229 ctexel = texture2D(sampler,ctexcoord.st); \n\
3230 float fraction = mod(texcoord.z*depth,1.0); \n\
3231 if(magfilter == 1) \n\
3232 texel = mix(ctexel,ftexel,1.0-fraction); //lerp GL_LINEAR \n\
3234 texel = ftexel; //fraction > .5 ? ctexel : ftexel; //GL_NEAREST \n\
3239vec4 texture3Demu( sampler2D sampler, in vec3 texcoord3){ \n\
3240 //use uniform magfilter \n\
3241 return texture3Demu0( sampler, texcoord3, magFilter); \n\
3243void PLUG_texture3D( inout vec4 rgba, in vec3 texcoord3 ){ \n\
3244 rgba = texture3Demu(fw_Texture_unit0,texcoord3); \n\
3246void PLUG_texture_apply (inout vec4 finalFrag, in int iuse ){ \n\
3248int tex_index = mat.tindex[mat.tstart[iuse] ]; \n\
3249int coord_index = mat.cmap[mat.tstart[iuse] ]; \n\
3250int samplr = mat.samplr[mat.tstart[iuse] ]; \n\
3252rgba = texture3Demu(textureUnit[tex_index],fw_TexCoord[coord_index]); \n\
3253 //rgba = texture3Demu(fw_Texture_unit0,fw_TexCoord[0]); \n\
3254 //rgba = texture2D(textureUnit[tex_index],fw_TexCoord[coord_index].xy); \n\
3255 finalFrag *= rgba; \n\
3261static const GLchar *plug_fragment_texture3Dlayer_apply_uber =
"\
3262void PLUG_texture_apply (inout vec4 finalFrag, in int iuse ){ \n\
3265int tex_index = mat.tindex[mat.tstart[iuse] ]; \n\
3266int coord_index = mat.cmap[mat.tstart[iuse] ]; \n\
3267int samplr = mat.samplr[mat.tstart[iuse] ]; \n\
3268 vec3 texcoord = fw_TexCoord[coord_index]; \n\
3269 texcoord.z = 1.0 - texcoord.z; //flip z from RHS to LHS\n\
3270 float depth = max(1.0,float(textureCount-1)); \n\
3271 float delta = 1.0/depth; \n\
3272 if(repeatSTR[0] == 0) texcoord.x = clamp(texcoord.x,0.0001,.9999); \n\
3273 else texcoord.x = mod(texcoord.x,1.0); \n\
3274 if(repeatSTR[1] == 0) texcoord.y = clamp(texcoord.y,0.0001,.9999); \n\
3275 else texcoord.y = mod(texcoord.y,1.0); \n\
3276 if(repeatSTR[2] == 0) texcoord.z = clamp(texcoord.z,0.0001,.9999); \n\
3277 else texcoord.z = mod(texcoord.z,1.0); \n\
3278 int flay = int(floor(texcoord.z*depth)); \n\
3279 int clay = int(ceil(texcoord.z*depth)); \n\
3280 vec4 ftexel, ctexel; \n\
3283 if(flay == 0) ftexel = texture2D(textureUnit[tex_index+0],texcoord.st); \n\
3284 if(clay == 0) ctexel = texture2D(textureUnit[tex_index+0],texcoord.st); \n\
3285 if(flay == 1) ftexel = texture2D(textureUnit[tex_index+1],texcoord.st); \n\
3286 if(clay == 1) ctexel = texture2D(textureUnit[tex_index+1],texcoord.st); \n\
3287 if(flay == 2) ftexel = texture2D(textureUnit[tex_index+2],texcoord.st); \n\
3288 if(clay == 2) ctexel = texture2D(textureUnit[tex_index+2],texcoord.st); \n\
3289 if(flay == 3) ftexel = texture2D(textureUnit[tex_index+3],texcoord.st); \n\
3290 if(clay == 3) ctexel = texture2D(textureUnit[tex_index+3],texcoord.st); \n\
3291 float fraction = mod(texcoord.z*depth,1.0); \n\
3293 if(magFilter == 1) \n\
3294 texel = mix(ctexel,ftexel,(1.0-fraction)); //lerp GL_LINEAR \n\
3296 texel = fraction > .5 ? ctexel : ftexel; //GL_NEAREST \n\
3297 finalFrag *= texel; \n\
3298 #endif //TEX3DLAY \n\
3302static const GLchar* plug_fragment_texture3D_apply_volume =
"\n\
3303vec4 texture3Demu0( sampler2D sampler, in vec3 texcoord3, in int magfilter){ \n\
3304 vec4 sampled = vec4(0.0); \n\
3306 //TILED method (vs Y strip method) \n\
3307 vec3 texcoord = texcoord3; \n\
3308 //texcoord.z = 1.0 - texcoord.z; //flip z from RHS to LHS\n\
3309 float depth = max(1.0,float(tex3dTiles[2])); \n\
3310 if(repeatSTR[0] == 0) texcoord.x = clamp(texcoord.x,0.0001,.9999); \n\
3311 else texcoord.x = mod(texcoord.x,1.0); \n\
3312 if(repeatSTR[1] == 0) texcoord.y = clamp(texcoord.y,0.0001,.9999); \n\
3313 else texcoord.y = mod(texcoord.y,1.0); \n\
3314 if(repeatSTR[2] == 0) texcoord.z = clamp(texcoord.z,0.0001,.9999); \n\
3315 else texcoord.z = mod(texcoord.z,1.0); \n\
3317 int izf = int(floor(texcoord.z*depth)); //floor z \n\
3318 int izc = int(ceil(texcoord.z*depth)); //ceiling z \n\
3319 izc = izc == tex3dTiles[2] ? izc - 1 : izc; //clamp int z \n\
3320 vec4 ftexel, ctexel; \n\
3322 int nx = tex3dTiles[0]; //0-11 \n\
3323 int ny = tex3dTiles[1]; \n\
3324 float fnx = 1.0/float(nx); //.1\n\
3325 float fny = 1.0/float(ny); \n\
3326 int ix = izc / ny; //60/11=5\n\
3327 int ixny = ix * ny; //5*11=55\n\
3328 int iy = izc - ixny; //60-55=5 modulus remainder \n\
3329 float cix = float(ix); //5 \n\
3330 float ciy = float(iy); \n\
3331 float xxc = (cix + texcoord.s)*fnx; //(5 + .5)*.1 = .55\n\
3332 float yyc = (ciy + texcoord.t)*fny; \n\
3335 iy = izf - ixny; //modulus remainder \n\
3336 float fix = float(ix); \n\
3337 float fiy = float(iy); \n\
3338 float xxf = (fix + texcoord.s)*fnx; \n\
3339 float yyf = (fiy + texcoord.t)*fny; \n\
3341 vec2 ftexcoord, ctexcoord; //texcoord is 3D, ftexcoord and ctexcoord are 2D coords\n\
3342 ftexcoord.s = xxf; \n\
3343 ftexcoord.t = yyf; \n\
3344 ctexcoord.s = xxc; \n\
3345 ctexcoord.t = yyc; \n\
3346 ftexel = texture2D(sampler,ftexcoord.st); \n\
3347 ctexel = texture2D(sampler,ctexcoord.st); \n\
3348 float fraction = mod(texcoord.z*depth,1.0); \n\
3349 if(magfilter == 1) \n\
3350 texel = mix(ctexel,ftexel,1.0-fraction); //lerp GL_LINEAR \n\
3352 texel = ftexel; //fraction > .5 ? ctexel : ftexel; //GL_NEAREST \n\
3353 sampled = texel; \n\
3357vec4 texture3Demu( sampler2D sampler, in vec3 texcoord3){ \n\
3358 //use uniform magfilter \n\
3359 return texture3Demu0( sampler, texcoord3, magFilter); \n\
3361void PLUG_texture3D( inout vec4 sampled, in vec3 texcoord3 ){ \n\
3362 sampled = texture3Demu(fw_Texture_unit0,texcoord3); \n\
3364void PLUG_texture_apply (inout vec4 finalFrag, in int iuse ){ \n\
3367 sampled = texture3Demu(fw_Texture_unit0,fw_TexCoord[0]); \n\
3368 finalFrag *= sampled; \n\
3374static const GLchar* plug_fragment_texture3Dlayer_apply =
"\
3375void PLUG_texture_apply (inout vec4 finalFrag, in int iuse ){ \n\
3378 vec3 texcoord = fw_TexCoord[0]; \n\
3379 texcoord.z = 1.0 - texcoord.z; //flip z from RHS to LHS\n\
3380 float depth = max(1.0,float(textureCount-1)); \n\
3381 float delta = 1.0/depth; \n\
3382 if(repeatSTR[0] == 0) texcoord.x = clamp(texcoord.x,0.0001,.9999); \n\
3383 else texcoord.x = mod(texcoord.x,1.0); \n\
3384 if(repeatSTR[1] == 0) texcoord.y = clamp(texcoord.y,0.0001,.9999); \n\
3385 else texcoord.y = mod(texcoord.y,1.0); \n\
3386 if(repeatSTR[2] == 0) texcoord.z = clamp(texcoord.z,0.0001,.9999); \n\
3387 else texcoord.z = mod(texcoord.z,1.0); \n\
3388 int flay = int(floor(texcoord.z*depth)); \n\
3389 int clay = int(ceil(texcoord.z*depth)); \n\
3390 vec4 ftexel, ctexel; \n\
3393 if(flay == 0) ftexel = texture2D(fw_Texture_unit0,texcoord.st); \n\
3394 if(clay == 0) ctexel = texture2D(fw_Texture_unit0,texcoord.st); \n\
3395 if(flay == 1) ftexel = texture2D(fw_Texture_unit1,texcoord.st); \n\
3396 if(clay == 1) ctexel = texture2D(fw_Texture_unit1,texcoord.st); \n\
3397 if(flay == 2) ftexel = texture2D(fw_Texture_unit2,texcoord.st); \n\
3398 if(clay == 2) ctexel = texture2D(fw_Texture_unit2,texcoord.st); \n\
3399 if(flay == 3) ftexel = texture2D(fw_Texture_unit3,texcoord.st); \n\
3400 if(clay == 3) ctexel = texture2D(fw_Texture_unit3,texcoord.st); \n\
3401 float fraction = mod(texcoord.z*depth,1.0); \n\
3403 if(magFilter == 1) \n\
3404 texel = mix(ctexel,ftexel,(1.0-fraction)); //lerp GL_LINEAR \n\
3406 texel = fraction > .5 ? ctexel : ftexel; //GL_NEAREST \n\
3407 finalFrag *= texel; \n\
3408 #endif //TEX3DLAY \n\
3432 //int index = mat.tindex[mat.tstart[iunit]]; \n\
3433 //vec2 tc = fw_TexCoord[mat.cindex[iunit]].xy; \n\
3436 vec2 ptex = fw_TexCoord[mat.cindex[iunit]].xy; \n\
3437 for(int j=0;j<ndesc;j++,k++){ \n\
3438 //if(j==ndesc) break; \n\
3439 int kk = mat.tindex[k]; \n\
3440 int modea = int(mat.mode[k] / 100); \n\
3441 int mode = mat.mode[k] - 100*modea; \n\
3442 //vec4 cur = sample_map0(kk,false); \n\
3443 vec4 cur = texture2D(textureUnit[kk],ptex); \n\
3445 finalColCalcB(prev, mode, modea, mat.func[k], cur); \n\
3450 //vec4 ncc = texture2D(textureUnit[kk],ptex.xy); \n\
3451 //prev.rgb = clamp(prev.rgb + ncc.rgb,0.0,1.0); \n\
3453 //prev = vec4(0.5,1.0,0.5,1.0); \n\
3458static const GLchar *plug_fragment_texture_apply =
"\
3459void PLUG_texture_apply (inout vec4 finalFrag, in int iuse ){ \n\
3462 int ndesc = mat.tcount[iuse]; \n\
3463 int k = mat.tstart[iuse]; \n\
3464 if(ndesc > 1){ //multitex \n\
3466 int isource,iasource, mode, modea, j; \n\
3467 for(j=0;j<ndesc;j++,k++){ \n\
3468 modea = int(mat.mode[k] / 100); \n\
3469 mode = mat.mode[k] - 100*modea; \n\
3470 if(mode != MTMODE_OFF) { \n\
3471 iasource = int(mat.source[k] / 100); \n\
3472 isource = mat.source[k] - 100*iasource; \n\
3473 if(isource == MT_DEFAULT) source = finalFrag; \n\
3474 else if(isource == MTSRC_DIFFUSE) source = mtex_diffuse; \n\
3475 else if(isource == MTSRC_SPECULAR) source = vec4(mtex_specular,1.0); \n\
3476 else if(isource == MTSRC_FACTOR) source = mt_Color; \n\
3477 if(iasource != 0){ \n\
3478 if(iasource == MT_DEFAULT) source.a = finalFrag.a; \n\
3479 else if(iasource == MTSRC_DIFFUSE) source.a = mtex_diffuse.a; \n\
3480 else if(iasource == MTSRC_SPECULAR) source.a = 1.0; \n\
3481 else if(iasource == MTSRC_FACTOR) source.a = mt_Color.a; \n\
3483 vec4 cur = sample_map(iuse,j,false); \n\
3484 finalColCalcB(source,mode,modea,mat.func[k], cur); \n\
3485 finalFrag = source; \n\
3489 /* ONE TEXTURE */ \n\
3490 finalFrag = sample_map(iuse,0,false) * finalFrag; \n\
3493 /* ONE TEXTURE */ \n\
3494 finalFrag = sample_map(iuse,0,false) * finalFrag; \n\
3502static const GLchar *plug_frag_lighting_physical =
"\n\
3505#define M_PI 3.14159265358979 \n\
3507struct AngularInfo \n\
3509 float NdotL; // cos angle between normal and light direction \n\
3510 float NdotV; // cos angle between normal and view direction \n\
3511 float NdotH; // cos angle between normal and half vector \n\
3512 float LdotH; // cos angle between light direction and half vector \n\
3513 float VdotH; // cos angle between view direction and half vector \n\
3516AngularInfo getAngularInfo(vec3 pointToLight, vec3 normal, vec3 view) \n\
3518 // Standard one-letter names \n\
3519 vec3 n = normalize(normal); // Outward direction of surface point \n\
3520 vec3 v = normalize(view); // Direction from surface point to view \n\
3521 vec3 l = normalize(pointToLight); // Direction from surface point to light \n\
3522 vec3 h = normalize(l + v); // Direction of the vector between l and v \n\
3523 float NdotL = clamp(dot(n, l), 0.0, 1.0); \n\
3524 float NdotV = clamp(dot(n, v), 0.0, 1.0); \n\
3525 float NdotH = clamp(dot(n, h), 0.0, 1.0); \n\
3526 float LdotH = clamp(dot(l, h), 0.0, 1.0); \n\
3527 float VdotH = clamp(dot(v, h), 0.0, 1.0); \n\
3528 AngularInfo ai = AngularInfo( \n\
3538// Lambert lighting \n\
3539// see https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ \n\
3540vec3 diffuse(MaterialInfo materialInfo) \n\
3542 return materialInfo.diffuseColor / M_PI; \n\
3544// TFresnel reflectance F() \n\
3545vec3 specularReflection(MaterialInfo materialInfo, AngularInfo angularInfo) \n\
3547 return materialInfo.reflectance0 + (materialInfo.reflectance90 - materialInfo.reflectance0) * pow(clamp(1.0 - angularInfo.VdotH, 0.0, 1.0), 5.0); \n\
3549// Smith Joint GGX \n\
3550// Note: Vis = G / (4 * NdotL * NdotV) \n\
3551float visibilityOcclusion(MaterialInfo materialInfo, AngularInfo angularInfo) \n\
3553 float NdotL = angularInfo.NdotL; \n\
3554 float NdotV = angularInfo.NdotV; \n\
3555 float alphaRoughnessSq = materialInfo.alphaRoughness * materialInfo.alphaRoughness; \n\
3556 float GGXV = NdotL * sqrt(NdotV * NdotV * (1.0 - alphaRoughnessSq) + alphaRoughnessSq); \n\
3557 float GGXL = NdotV * sqrt(NdotL * NdotL * (1.0 - alphaRoughnessSq) + alphaRoughnessSq); \n\
3559 float GGX = GGXV + GGXL; \n\
3562 return 0.5 / GGX; \n\
3566// model the distribution of microfacet normals (aka D()) \n\
3567float microfacetDistribution(MaterialInfo materialInfo, AngularInfo angularInfo) \n\
3569 float alphaRoughnessSq = materialInfo.alphaRoughness * materialInfo.alphaRoughness; \n\
3570 float f = (angularInfo.NdotH * alphaRoughnessSq - angularInfo.NdotH) * angularInfo.NdotH + 1.0; \n\
3571 return alphaRoughnessSq / (M_PI * f * f); \n\
3573vec3 getPointShade(vec3 pointToLight, MaterialInfo materialInfo, vec3 normal, vec3 view) \n\
3575 AngularInfo angularInfo = getAngularInfo(pointToLight, normal, view); \n\
3576 if (angularInfo.NdotL > 0.0 || angularInfo.NdotV > 0.0) \n\
3578 // microfacet specular shading model \n\
3579 vec3 F = specularReflection(materialInfo, angularInfo); \n\
3580 float Vis = visibilityOcclusion(materialInfo, angularInfo); \n\
3581 float D = microfacetDistribution(materialInfo, angularInfo); \n\
3582 // Calculation of analytical lighting contribution \n\
3583 vec3 diffuseContrib = (1.0 - F) * diffuse(materialInfo); \n\
3584 vec3 specContrib = F * Vis * D; \n\
3585 // reflectance (BRDF) scaled by the energy of the light (cosine law) \n\
3586 return angularInfo.NdotL * (diffuseContrib + specContrib); \n\
3588 return vec3(0.0, 0.0, 0.0); \n\
3590void PLUG_add_light_physical (inout vec3 vertexcolor, in vec3 myPosition, in vec3 myNormal, in struct MaterialInfo mat){ \n\
3591 //working in eye space: eye is at 0,0,0 looking generally in direction 0,0,-1 \n\
3592 //myPosition, myNormal - of surface vertex, in eyespace \n\
3594 vec3 N = normalize (myNormal); \n\
3596 vec3 E = -normalize(myPosition.xyz); \n \
3598 // apply the lights to this material \n\
3599 // weird but ANGLE needs constant loop \n\
3600 for (i=0; i<lightcount; i++) {\n\
3601 float on = 1.0; //we only send active/on lights to shader, so this is for radius \n\
3602 float spot = 1.0; \n\
3603 float attenuation = 1.0; //directional default \n\
3604 fw_LightSourceParameters light = fw_LightSource[i]; \n\
3605 int myLightType = lightType[i]; \n\
3606 // VP vector of light direction and distance \n\
3607 vec3 VP = light.location.xyz - myPosition.xyz; \n\
3608 vec3 L = -light.direction; //directional light \n\
3609 if(myLightType < 2){ \n\
3610 //point and spot \n\
3611 L = normalize(VP); \n\
3612 float D = length(VP); // distance to vertex \n\
3613 // are we within range? \n\
3614 if (D > light.lightRadius) on = 0.0; \n\
3615 attenuation = 1.0/max(1.0,(light.Attenuations.x + (light.Attenuations.y * D) + (light.Attenuations.z *D*D))); \n\
3617 vec3 shade = getPointShade(-VP, mat, -N, -E); \n\
3618 if (myLightType==1) { \n\
3621 float cosCut = cos(light.spotCutoff); \n\
3622 float cosBeam = cos(light.spotBeamWidth); \n\
3623 float rayAngle = dot(normalize(-L),normalize(light.direction)); \n\
3624 // check against spotCosCutoff \n\
3625 if (rayAngle > cosCut) { \n\
3626 if(rayAngle > cosBeam) { \n\
3629 //spot = (rayAngle - cosCut)/(cosBeam - cosCut); \n\
3630 float rayradians = acos(rayAngle); \n\
3631 spot = (light.spotCutoff - rayradians)/(light.spotCutoff - light.spotBeamWidth); \n\
3635 float shadowtest = 1.0; \n\
3637 if (light.shadows) { \n\
3638 shadowtest = 1.0 - light.shadowIntensity*ShadowCalculation(i,VP); \n\
3641 vertexcolor += on * shadowtest * attenuation * spot * light.color * light.intensity * shade; \n\
3642 //vertexcolor += shade; //vec3(0.0,1.0,1.0); \n\
3644 vertexcolor = clamp(vertexcolor, 0.0, 1.0); \n\
3658 static const GLchar* plug_vertex_lighting_ADSLightModel =
"\n\
3659/* use ADSLightModel here the ADS colour is returned from the function. */ \n\
3662void PLUG_add_light_contribution2 (inout vec3 vertexcolor, inout vec3 specularcolor, in vec4 myPosition, in vec3 myNormal, \n\
3663 in float mat_shininess, in float mat_ambient, in vec3 mat_diffuse, in vec3 mat_specular){ \n\
3664 //working in eye space: eye is at 0,0,0 looking generally in direction 0,0,-1 \n\
3665 //myPosition, myNormal - of surface vertex, in eyespace \n\
3666 //vertexcolor - diffuse+ambient -will be replaced or modulated by texture color \n\
3667 //specularcolor - specular+emissive or non-diffuse (emissive added outside this function) \n\
3668 //algo: uses Blinn-Phong specular reflection: half-vector pow(N*H,shininess) \n\
3669 // https://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/lighting.html#Lightingequations \n\
3670 // fog and emissive are done elsewhere, this function does: \n\
3671 // SUM(on[i] x attenuation[i] x spot[i] x ILrgb[i] x (ambient[i] + diffuse[i] + specular[i])) \n\
3673 vec3 N = normalize (myNormal); \n\
3675 vec3 E = -normalize(myPosition.xyz); \n \
3677 // apply the lights to this material \n\
3678 // weird but ANGLE needs constant loop \n\
3679 vec3 sum_vertex = vec3(0.,0.,0.); \n\
3680 vec3 sum_specular = vec3(0.,0.,0.); \n\
3681 for (i=0; i<lightcount; i++) {\n\
3682 vec3 diffuse = vec3(0., 0., 0.); \n\
3683 vec3 ambient = vec3(0., 0., 0.); \n\
3684 vec3 specular = vec3(0., 0., 0.); \n\
3685 float on = 1.0; //we only send active/on lights to shader, so this is for radius \n\
3686 float spot = 1.0; \n\
3687 float attenuation = 1.0; //directional default \n\
3688 fw_LightSourceParameters light = fw_LightSource[i]; \n\
3689 int myLightType = lightType[i]; \n\
3690 // VP vector of light direction and distance \n\
3691 vec3 VP = light.location.xyz - myPosition.xyz; \n\
3692 vec3 L = -light.direction; //directional light \n\
3693 if(myLightType < 2){ \n\
3694 //point and spot \n\
3695 L = normalize(VP); \n\
3696 float D = length(VP); // distance to vertex \n\
3697 // are we within range? \n\
3698 if (D > light.lightRadius) on = 0.0; \n\
3699 attenuation = 1.0/max(1.0,(light.Attenuations.x + (light.Attenuations.y * D) + (light.Attenuations.z *D*D))); \n\
3701 float NdotL = max(dot(N, L), 0.0); //Lambertian diffuse term \n\
3702 //specular reflection models, phong or blinn-phong \n\
3703 //#define PHONG 1 \n\
3706 vec3 R = normalize(-reflect(L,N)); \n\
3707 float RdotE = max(dot(R,E),0.0); \n\
3708 float specbase = RdotE; \n\
3709 // assume shader gets shininess in 0 to 1 range, and scales it to 0 to 128 range here \n\
3710 float specpow = mat_shininess*128.0; \n\
3713 vec3 H = normalize(L + E); //halfvector x3d specs this is L+v/|L+v|\n\
3714 float NdotH = max(dot(N,H),0.0); \n\
3715 float specbase = NdotH; \n\
3716 float specpow = mat_shininess*128.0; \n\
3718 float powerFactor = 0.0; // for light dropoff \n\
3719 if (specbase > 0.0) { \n\
3720 powerFactor = pow(specbase,specpow); \n\
3721 // tone down the power factor if mat_shininess borders 0 \n\
3724 ambient += light.ambient * mat_diffuse * mat_ambient; \n\
3725 specular += light.intensity * mat_specular *powerFactor; \n\
3726 diffuse += light.intensity * mat_diffuse * NdotL; \n\
3727 if (myLightType==1) { \n\
3730 float cosCut = cos(light.spotCutoff); \n\
3731 float cosBeam = cos(light.spotBeamWidth); \n\
3732 float rayAngle = dot(normalize(-L),normalize(light.direction)); \n\
3733 // check against spotCosCutoff \n\
3734 if (rayAngle > cosCut) { \n\
3735 if(rayAngle > cosBeam) { \n\
3738 //spot = (rayAngle - cosCut)/(cosBeam - cosCut); \n\
3739 float rayradians = acos(rayAngle); \n\
3740 spot = (light.spotCutoff - rayradians)/(light.spotCutoff - light.spotBeamWidth); \n\
3744 float shadowtest = 1.0; \n\
3746 if (light.shadows) { \n\
3747 shadowtest = 1.0 - light.shadowIntensity*ShadowCalculation(i,VP); \n\
3750 sum_vertex += on * shadowtest * attenuation * spot * light.color * (ambient + diffuse); \n\
3751 sum_specular += on * shadowtest * attenuation * spot * light.color * (specular); \n\
3753 vertexcolor = clamp(sum_vertex + vertexcolor, 0.0, 1.0); \n\
3754 specularcolor = clamp(sum_specular + specularcolor, 0.0, 1.0); \n\
3761static const GLchar *plug_fog_apply =
"\
3762void PLUG_fog_apply (inout vec4 finalFrag, in vec3 normal_eye_fragment ){ \n\
3764 float depth = abs(castle_vertex_eye.z/castle_vertex_eye.w); \n\
3765 if(fw_fogparams.fogType > 0){ \n\
3767 if(fw_fogparams.fogType == 1){ //FOGTYPE_LINEAR \n\
3768 if(depth < fw_fogparams.visibilityRange) \n\
3769 ff = (fw_fogparams.visibilityRange-depth)/fw_fogparams.visibilityRange; \n\
3770 } else { //FOGTYPE_EXPONENTIAL \n\
3771 if(depth < fw_fogparams.visibilityRange){ \n\
3772 ff = exp(-depth/(fw_fogparams.visibilityRange -depth) ); \n\
3773 ff = clamp(ff, 0.0, 1.0); \n\
3776 finalFrag = mix(finalFrag,fw_fogparams.fogColor,1.0 - ff); \n\
3781static const GLchar *vertex_plug_clip_apply =
"\
3783#define FW_MAXCLIPPLANES 4 \n\
3784uniform int fw_nclipplanes; \n\
3785uniform vec4 fw_clipplanes[FW_MAXCLIPPLANES]; \n\
3786varying float fw_ClipDistance[FW_MAXCLIPPLANES]; \n\
3788void PLUG_vertex_object_space (in vec4 vertex_object, in vec3 normal_object){ \n\
3789 for ( int i=0; i<fw_nclipplanes; i++ ) \n\
3790 fw_ClipDistance[i] = dot( fw_clipplanes[i], vertex_object); \n\
3795static const GLchar *frag_plug_clip_apply =
"\
3797#define FW_MAXCLIPPLANES 4 \n\
3798uniform int fw_nclipplanes; \n\
3799varying float fw_ClipDistance[FW_MAXCLIPPLANES]; \n\
3800void PLUG_fog_apply (inout vec4 finalFrag, in vec3 normal_eye_fragment ){ \n\
3801 for(int i=0;i<fw_nclipplanes;i++) { \n\
3802 //if(normal_eye_fragment.z > fw_ClipDistance[i]) discard; \n\
3803 if(fw_ClipDistance[i] < 0.0) discard; \n\
3811void printBitsB(
size_t const size,
void const *
const ptr)
3813 unsigned char *b = (
unsigned char*) ptr;
3817 for (i=size-1;i>=0;i--)
3821 byte = (b[i] >> j) & 1;
3830#if defined(GL_ES_VERSION_2_0)
3831static int isMobile = TRUE;
3833static int isMobile = FALSE;
3835int get_GLSL_max_version(){
3836 static int once = FALSE;
3837 static float glsl_version = 0.0f;
3838 static int max_shader_version = 130;
3840 const GLubyte * glsl_version_str = glGetString ( GL_SHADING_LANGUAGE_VERSION);
3841 sscanf(glsl_version_str,
"%f",&glsl_version);
3842 max_shader_version = (int)(glsl_version * 100.0f + .4f);
3843 ConsoleMessage(
"GLSL shader max version %s %d\n", glsl_version_str, max_shader_version );
3846 return max_shader_version;
3848#define DESIRE(whichOne,zzz) ((whichOne & zzz)==zzz)
3849static int GLSL_max_version = 0;
3850int getSpecificShaderSourceCastlePlugs (
const GLchar **vertexSource,
const GLchar **fragmentSource,
shaderflagsstruct whichOne)
3856 int retval, unique_int;
3857 char *CompleteCode[3];
3861 if(whichOne.usershaders )
3864 if(!GLSL_max_version){
3870 GLSL_max_version = get_GLSL_max_version();
3873 vs = strdup(getGenericVertex());
3874 fs = strdup(getGenericFragment());
3877 CompleteCode[SHADERPART_VERTEX] = vs;
3878 CompleteCode[SHADERPART_GEOMETRY] = NULL;
3879 CompleteCode[SHADERPART_FRAGMENT] = fs;
3893 AddVersion0(SHADERPART_VERTEX, iver, aver, CompleteCode);
3894 AddVersion0(SHADERPART_FRAGMENT, iver, aver, CompleteCode);
3895 AddDefine(SHADERPART_FRAGMENT,
"MOBILE",CompleteCode);
3897 if(GLSL_max_version >= 130) {
3901 iver = GLSL_max_version;
3902 AddVersion(SHADERPART_VERTEX, iver, CompleteCode);
3903 AddVersion(SHADERPART_FRAGMENT, iver, CompleteCode);
3904 AddDefine(SHADERPART_VERTEX,
"FULL", CompleteCode);
3905 AddDefine(SHADERPART_FRAGMENT,
"FULL", CompleteCode);
3907 AddVersion(SHADERPART_VERTEX, GLSL_max_version, CompleteCode);
3908 AddVersion(SHADERPART_FRAGMENT, GLSL_max_version, CompleteCode);
3920 if(DESIRE(whichOne.base,WANT_ANAGLYPH))
3921 Plug(SHADERPART_FRAGMENT,plug_fragment_end_anaglyph,CompleteCode,&unique_int);
3923 if DESIRE(whichOne.base,COLOUR_MATERIAL_SHADER) {
3924 AddDefine(SHADERPART_VERTEX,
"CPV",CompleteCode);
3925 AddDefine(SHADERPART_FRAGMENT,
"CPV",CompleteCode);
3927 if(DESIRE(whichOne.base,MODULATE_COLOR)){
3929 AddDefine(SHADERPART_VERTEX,
"MODC",CompleteCode);
3930 AddDefine(SHADERPART_FRAGMENT,
"MODC",CompleteCode);
3932 if(DESIRE(whichOne.base,MODULATE_ALPHA)){
3934 AddDefine(SHADERPART_FRAGMENT,
"MODA",CompleteCode);
3936 if(DESIRE(whichOne.base,MODULATE_TEXTURE)){
3938 AddDefine(SHADERPART_FRAGMENT,
"MODT",CompleteCode);
3943 if(DESIRE(whichOne.base,MATERIAL_APPEARANCE_SHADER) || DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER)
3944 || DESIRE(whichOne.base,PHYSICAL_MATERIAL_APPEARANCE_SHADER) || DESIRE(whichOne.base,UNLIT_MATERIAL_APPEARANCE_SHADER)){
3946 AddDefine(SHADERPART_VERTEX,
"LIT",CompleteCode);
3947 AddDefine(SHADERPART_FRAGMENT,
"LIT",CompleteCode);
3949 if(DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER)){
3950 AddDefine(SHADERPART_FRAGMENT,
"TWO",CompleteCode);
3951 AddDefine(SHADERPART_VERTEX,
"TWO",CompleteCode);
3953 if(DESIRE(whichOne.base,SHADINGSTYLE_GOURAUD) ){
3955 AddDefine(SHADERPART_VERTEX,
"LITE",CompleteCode);
3957 if(DESIRE(whichOne.base,MATERIAL_APPEARANCE_SHADER) || DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER))
3958 Plug(SHADERPART_VERTEX,plug_vertex_lighting_ADSLightModel,CompleteCode,&unique_int);
3959 if (DESIRE(whichOne.base, PHYSICAL_MATERIAL_APPEARANCE_SHADER))
3960 Plug(SHADERPART_VERTEX, plug_frag_lighting_physical, CompleteCode, &unique_int);
3962 if(DESIRE(whichOne.base,SHADINGSTYLE_PHONG)){
3964 AddDefine(SHADERPART_FRAGMENT,
"LITE",CompleteCode);
3965 AddDefine(SHADERPART_FRAGMENT,
"SHADOW", CompleteCode);
3967 if(DESIRE(whichOne.base,PHYSICAL_MATERIAL_APPEARANCE_SHADER))
3968 Plug(SHADERPART_FRAGMENT,plug_frag_lighting_physical,CompleteCode,&unique_int);
3969 if(DESIRE(whichOne.base,MATERIAL_APPEARANCE_SHADER) || DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER))
3970 Plug(SHADERPART_FRAGMENT,plug_vertex_lighting_ADSLightModel,CompleteCode,&unique_int);
3971 AddDefine(SHADERPART_FRAGMENT,
"PHONG",CompleteCode);
3972 AddDefine(SHADERPART_VERTEX,
"PHONG", CompleteCode);
3975 if( DESIRE(whichOne.base,HAVE_LINEPOINTS_COLOR) ) {
3976 AddDefine(SHADERPART_VERTEX,
"LINE",CompleteCode);
3977 AddDefine(SHADERPART_FRAGMENT,
"LINE",CompleteCode);
3997 int colCalc_loaded = FALSE;
3998 if(DESIRE(whichOne.base,HAVE_UNLIT_COLOR)){
4000 AddDefine(SHADERPART_VERTEX,
"UNLIT",CompleteCode);
4001 AddDefine(SHADERPART_FRAGMENT,
"UNLIT",CompleteCode);
4003 if(DESIRE(whichOne.base,HAVE_PROJECTIVETEXTURE)){
4005 AddDefine(SHADERPART_FRAGMENT,
"PROJTEX",CompleteCode);
4006 AddDefine(SHADERPART_FRAGMENT,
"TEX",CompleteCode);
4007 if(!colCalc_loaded) Plug(SHADERPART_FRAGMENT,plug_finalColCalc,CompleteCode,&unique_int);
4008 colCalc_loaded = TRUE;
4010 if (DESIRE(whichOne.base,ONE_TEX_APPEARANCE_SHADER) ||
4011 DESIRE(whichOne.base,HAVE_TEXTURECOORDINATEGENERATOR) ||
4012 DESIRE(whichOne.base,HAVE_CUBEMAP_TEXTURE) ||
4013 DESIRE(whichOne.base,MULTI_TEX_APPEARANCE_SHADER)) {
4015 AddDefine(SHADERPART_VERTEX,
"TEX",CompleteCode);
4016 AddDefine(SHADERPART_FRAGMENT,
"TEX",CompleteCode);
4017 if(DESIRE(whichOne.base,HAVE_TEXTURECOORDINATEGENERATOR) )
4018 AddDefine(SHADERPART_VERTEX,
"TGEN",CompleteCode);
4019 if(DESIRE(whichOne.base,TEX3D_SHADER)){
4026 AddDefine(SHADERPART_VERTEX,
"TEX3D",CompleteCode);
4027 AddDefine(SHADERPART_FRAGMENT,
"TEX3D",CompleteCode);
4029 if(DESIRE(whichOne.base,TEX3D_LAYER_SHADER)){
4031 AddDefine(SHADERPART_FRAGMENT,
"TEX3DLAY",CompleteCode);
4032 Plug(SHADERPART_FRAGMENT,plug_fragment_texture3Dlayer_apply_uber,CompleteCode,&unique_int);
4036 Plug(SHADERPART_FRAGMENT,plug_fragment_texture3D_apply_volume_uber,CompleteCode,&unique_int);
4039 if(DESIRE(whichOne.base,HAVE_CUBEMAP_TEXTURE)){
4040 AddDefine(SHADERPART_VERTEX,
"CUB",CompleteCode);
4041 AddDefine(SHADERPART_FRAGMENT,
"CUB",CompleteCode);
4044 if(DESIRE(whichOne.base,MULTI_TEX_APPEARANCE_SHADER)){
4047 AddDefine(SHADERPART_VERTEX,
"MTEX",CompleteCode);
4048 AddDefine(SHADERPART_FRAGMENT,
"MTEX",CompleteCode);
4051 if(!colCalc_loaded) Plug(SHADERPART_FRAGMENT,plug_finalColCalc,CompleteCode,&unique_int);
4052 colCalc_loaded = TRUE;
4053 Plug(SHADERPART_FRAGMENT,plug_fragment_texture_apply,CompleteCode,&unique_int);
4059 if(DESIRE(whichOne.base,FILL_PROPERTIES_SHADER)) {
4060 AddDefine(SHADERPART_VERTEX,
"FILL",CompleteCode);
4061 AddDefine(SHADERPART_FRAGMENT,
"FILL",CompleteCode);
4062 if(GLSL_max_version >= 130) {
4063 Plug(SHADERPART_FRAGMENT,plug_fragment_fillProperties_apply,CompleteCode,&unique_int);
4065 Plug(SHADERPART_FRAGMENT,plug_fragment_fillProperties_apply_120,CompleteCode,&unique_int);
4069 if(DESIRE(whichOne.base,LINE_PROPERTIES_SHADER)) {
4070 AddDefine(SHADERPART_VERTEX,
"LINETYPE",CompleteCode);
4071 AddDefine(SHADERPART_FRAGMENT,
"LINETYPE",CompleteCode);
4074 if(DESIRE(whichOne.base,POINT_PROPERTIES_SHADER)) {
4075 AddDefine(SHADERPART_VERTEX,
"POINTP",CompleteCode);
4076 AddDefine(SHADERPART_FRAGMENT,
"POINTP",CompleteCode);
4079 if(DESIRE(whichOne.base,FOG_APPEARANCE_SHADER)){
4080 AddDefine(SHADERPART_VERTEX,
"FOG",CompleteCode);
4081 AddDefine(SHADERPART_FRAGMENT,
"FOG",CompleteCode);
4082 if(DESIRE(whichOne.base,HAVE_FOG_COORDS))
4083 AddDefine(SHADERPART_VERTEX,
"FOGCOORD",CompleteCode);
4084 Plug(SHADERPART_FRAGMENT,plug_fog_apply,CompleteCode,&unique_int);
4088 if(DESIRE(whichOne.base,CLIPPLANE_SHADER)){
4089 AddDefine(SHADERPART_VERTEX,
"CLIP",CompleteCode);
4090 Plug(SHADERPART_VERTEX,vertex_plug_clip_apply,CompleteCode,&unique_int);
4091 AddDefine(SHADERPART_FRAGMENT,
"CLIP",CompleteCode);
4092 Plug(SHADERPART_FRAGMENT,frag_plug_clip_apply,CompleteCode,&unique_int);
4094 if(DESIRE(whichOne.base,PARTICLE_SHADER)){
4095 AddDefine(SHADERPART_VERTEX,
"PARTICLE",CompleteCode);
4097 if (DESIRE(whichOne.base, SKINNING_SHADER)) {
4098 AddDefine(SHADERPART_VERTEX,
"SKINNING", CompleteCode);
4099 if(DESIRE(whichOne.base,DISPLACER_SHADER))
4100 AddDefine(SHADERPART_VERTEX,
"DISPLACER", CompleteCode);
4104 EnableEffects(CompleteCode,&unique_int);
4111 *fragmentSource = CompleteCode[SHADERPART_FRAGMENT];
4112 *vertexSource = CompleteCode[SHADERPART_VERTEX];
4120 if (0)
if (DESIRE(whichOne.base, HAVE_CUBEMAP_TEXTURE)) {
4121 *fragmentSource = genericFragmentCube;
4123 if(0)
if (DESIRE(whichOne.base, HAVE_CUBEMAP_TEXTURE)) {
4124 char* fragbuf = malloc(64000);
4125 memset(fragbuf, 0, 64000);
4126 FILE* fp = fopen(
"C:\\Users\\dougs\\Documents\\dev\\source2\\freewrk_tmp\\hacked_frag.txt",
"r+");
4127 int ir = fread(fragbuf, 1, 64000, fp);
4132 *fragmentSource = fragbuf;
4142 FILE *fp = fopen(
"C:/tmp/composed_shader.vert",
"w+");
4143 fwrite(*vertexSource,strlen(*vertexSource),1,fp);
4145 fp = fopen(
"C:/tmp/composed_shader.frag",
"w+");
4146 fwrite(*fragmentSource,strlen(*fragmentSource),1,fp);
4148 printf(
"wrote shader\n");
4157static const GLchar* plug_vertex_lighting_ADSLightModel_volume =
"\n\
4158/* use ADSLightModel here the ADS colour is returned from the function. */ \n\
4159void PLUG_add_light_contribution2 (inout vec3 vertexcolor, inout vec3 specularcolor, in vec4 myPosition, in vec3 myNormal, \n\
4160 in float mat_shininess, in float mat_ambient, in vec3 mat_diffuse, in vec3 mat_specular){ \n\
4161 //working in eye space: eye is at 0,0,0 looking generally in direction 0,0,-1 \n\
4162 //myPosition, myNormal - of surface vertex, in eyespace \n\
4163 //vertexcolor - diffuse+ambient -will be replaced or modulated by texture color \n\
4164 //specularcolor - specular+emissive or non-diffuse (emissive added outside this function) \n\
4165 //algo: uses Blinn-Phong specular reflection: half-vector pow(N*H,shininess) \n\
4166 // https://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/lighting.html#Lightingequations \n\
4167 // fog and emissive are done elsewhere, this function does: \n\
4168 // SUM(on[i] x attenuation[i] x spot[i] x ILrgb[i] x (ambient[i] + diffuse[i] + specular[i])) \n\
4170 vec3 N = normalize (myNormal); \n\
4172 vec3 E = -normalize(myPosition.xyz); \n \
4174 // apply the lights to this material \n\
4175 // weird but ANGLE needs constant loop \n\
4176 vec3 sum_vertex = vec3(0.,0.,0.); \n\
4177 vec3 sum_specular = vec3(0.,0.,0.); \n\
4178 for (i=0; i<lightcount; i++) {\n\
4179 vec3 diffuse = vec3(0., 0., 0.); \n\
4180 vec3 ambient = vec3(0., 0., 0.); \n\
4181 vec3 specular = vec3(0., 0., 0.); \n\
4182 float on = 1.0; //we only send active/on lights to shader, so this is for radius \n\
4183 float spot = 1.0; \n\
4184 float attenuation = 1.0; //directional default \n\
4185 fw_LightSourceParameters light = fw_LightSource[i]; \n\
4186 int myLightType = lightType[i]; \n\
4187 // VP vector of light direction and distance \n\
4188 vec3 VP = light.location.xyz - myPosition.xyz; \n\
4189 vec3 L = -light.direction; //directional light \n\
4190 if(myLightType < 2){ \n\
4191 //point and spot \n\
4192 L = normalize(VP); \n\
4193 float D = length(VP); // distance to vertex \n\
4194 // are we within range? \n\
4195 if (D > light.lightRadius) on = 0.0; \n\
4196 attenuation = 1.0/max(1.0,(light.Attenuations.x + (light.Attenuations.y * D) + (light.Attenuations.z *D*D))); \n\
4198 float NdotL = max(dot(N, L), 0.0); //Lambertian diffuse term \n\
4199 //specular reflection models, phong or blinn-phong \n\
4200 //#define PHONG 1 \n\
4203 vec3 R = normalize(-reflect(L,N)); \n\
4204 float RdotE = max(dot(R,E),0.0); \n\
4205 float specbase = RdotE; \n\
4206 // assume shader gets shininess in 0 to 1 range, and scales it to 0 to 128 range here \n\
4207 float specpow = mat_shininess*128.0; \n\
4210 vec3 H = normalize(L + E); //halfvector x3d specs this is L+v/|L+v|\n\
4211 float NdotH = max(dot(N,H),0.0); \n\
4212 float specbase = NdotH; \n\
4213 float specpow = mat_shininess*128.0; \n\
4215 float powerFactor = 0.0; // for light dropoff \n\
4216 if (specbase > 0.0) { \n\
4217 powerFactor = pow(specbase,specpow); \n\
4218 // tone down the power factor if mat_shininess borders 0 \n\
4221 ambient += light.ambient * mat_diffuse * mat_ambient; \n\
4222 specular += light.intensity * mat_specular *powerFactor; \n\
4223 diffuse += light.intensity * mat_diffuse * NdotL; \n\
4224 if (myLightType==1) { \n\
4227 float spotDot = dot (-L,light.direction); \n\
4228 // check against spotCosCutoff \n\
4229 if (spotDot > light.spotCutoff) { \n\
4230 if(spotDot > light.spotBeamWidth) { \n\
4233 spot = (spotDot - light.spotCutoff)/(light.spotBeamWidth - light.spotCutoff); \n\
4237 sum_vertex += on * attenuation * spot * light.color * (ambient + diffuse); \n\
4238 sum_specular += on * attenuation * spot * light.color * (specular); \n\
4240 vertexcolor = clamp(sum_vertex + vertexcolor, 0.0, 1.0); \n\
4241 specularcolor = clamp(sum_specular + specularcolor, 0.0, 1.0); \n\
4246static const GLchar *volumeVertexGLES2 =
" \n\
4247#define varying out \n\
4248#define atribute in \n\
4249uniform mat4 fw_ModelViewMatrix; \n\
4250uniform mat4 fw_ProjectionMatrix; \n\
4251attribute vec4 fw_Vertex; \n\
4253/* PLUG-DECLARATIONS */ \n\
4255varying vec4 castle_vertex_eye; \n\
4256varying vec4 castle_Color; \n\
4260 vec4 vertex_object = fw_Vertex; \n\
4261 vec3 normal_object = vec3(0.0); \n\
4262 /* PLUG: vertex_object_space (vertex_object, normal_object) */ \n\
4263 castle_vertex_eye = fw_ModelViewMatrix * vertex_object; \n\
4265 castle_Color = vec4(1.0,.5,.5,1.0); \n\
4267 gl_Position = fw_ProjectionMatrix * castle_vertex_eye; \n\
4277static const GLchar *volumeFragmentGLES2 =
" \n\
4281//precision highp float; \n\
4282precision mediump float; \n\
4284#define varying in \n\
4285#define texture2D texture \n\
4286#define texture3D texture \n\
4287#define textureCube texture \n\
4288#define texture2DProj textureProj \n\
4289#define texture3DProj textureProj \n\
4290out vec4 FragColor; \n\
4292 vec4 HeatMapColor(float value, float minValue, float maxValue) \n\
4294 //used for debugging. If min=0,max=1 then magenta is 0, blue,green,yellow, red is 1 \n\
4296 int HEATMAP_COLORS_COUNT; \n\
4298 HEATMAP_COLORS_COUNT = 6; \n\
4299 colors[0] = vec4(0.32, 0.00, 0.32, 1.0); \n\
4300 colors[1] = vec4( 0.00, 0.00, 1.00, 1.00); \n\
4301 colors[2] = vec4(0.00, 1.00, 0.00, 1.00); \n\
4302 colors[3] = vec4(1.00, 1.00, 0.00, 1.00); \n\
4303 colors[4] = vec4(1.00, 0.60, 0.00, 1.00); \n\
4304 colors[5] = vec4(1.00, 0.00, 0.00, 1.00); \n\
4305 float ratio=(float(HEATMAP_COLORS_COUNT)-1.0)*clamp((value-minValue)/(maxValue-minValue),0.0,1.0); \n\
4306 int indexMin=int(floor(ratio)); \n\
4307 int indexMax= indexMin+1 < HEATMAP_COLORS_COUNT-1 ? indexMin+1 : HEATMAP_COLORS_COUNT-1; \n\
4308 ret = mix(colors[indexMin], colors[indexMax], ratio-float(indexMin)); \n\
4309 if(value < minValue) ret = vec4(0.0,0.0,0.0,1.0); \n\
4310 if(value > maxValue) ret = vec4(1.0,1.0,1.0,1.0); \n\
4313vec4 debug_color; \n\
4314float hash( float n ) \n\
4316 return fract(sin(n)*43758.5453); \n\
4318float noise( vec3 xyz ) \n\
4320 // The noise function returns a value in the range -1.0f -> 1.0f \n\
4321 vec3 p = floor(xyz); \n\
4322 vec3 f = fract(xyz); \n\
4324 f = f*f*(3.0-2.0*f); \n\
4325 float n = p.x + p.y*57.0 + 113.0*p.z; \n\
4327 return mix(mix(mix( hash(n+0.0), hash(n+1.0),f.x), \n\
4328 mix( hash(n+57.0), hash(n+58.0),f.x),f.y), \n\
4329 mix(mix( hash(n+113.0), hash(n+114.0),f.x), \n\
4330 mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z); \n\
4332vec3 noise3( in vec3 xyz, in float range ){ \n\
4333 vec3 rxyz = vec3(xyz); \n\
4334 rxyz.x += noise(xyz)*range; \n\
4335 rxyz.y += noise(xyz)*range; \n\
4336 rxyz.z += noise(xyz)*range; \n\
4340varying vec4 castle_vertex_eye; \n\
4341varying vec4 castle_Color; \n\
4342uniform mat4 fw_ModelViewProjInverse; \n\
4343//uniform float fw_FocalLength; \n\
4344uniform vec4 fw_viewport; \n\
4345uniform vec3 fw_dimensions; \n\
4346//uniform vec3 fw_RayOrigin; \n\
4347uniform sampler2D fw_Texture_unit0; \n\
4348uniform sampler2D fw_Texture_unit1; \n\
4349uniform sampler2D fw_Texture_unit2; \n\
4350uniform sampler2D fw_Texture_unit3; \n\
4351uniform int fw_gradTexture; \n\
4352vec4 texture3Demu0( sampler2D sampler, in vec3 texcoord3, int magfilter); \n\
4353uniform int magFilter; \n\
4355uniform int tex3dTiles[3]; \n\
4356uniform int repeatSTR[3]; \n\
4359uniform int fw_nIDs; \n\
4360uniform int fw_enableIDs[10]; \n\
4361uniform int fw_surfaceStyles[2]; \n\
4362uniform int fw_nStyles; \n\
4363vec4 texture3Demu( sampler2D sampler, in vec3 texcoord3); \n\
4364bool inEnabledSegment(in vec3 texcoords, inout int jstyle){ \n\
4365 bool inside = true; \n\
4366 jstyle = 1; //DEFAULT \n\
4367 vec4 segel = texture3Demu0(fw_Texture_unit1,texcoords,0); \n\
4368 //convert from GL_FLOAT 0-1 to int 0-255 \n\
4369 //Q. is there a way to do int images in GLES2? \n\
4370 int ID = int(floor(segel.a * 255.0 + .1)); \n\
4371 //debug_color = HeatMapColor(float(ID),0.0,5.0); \n\
4372 //debug_color.a = .2; \n\
4373 if(ID < fw_nIDs){ \n\
4374 //specs: The indices of this array corresponds to the segment identifier. \n\
4375 inside = fw_enableIDs[ID] == 0 ? false : true; \n\
4378 int kstyle = fw_nStyles-1; \n\
4379 kstyle = ID < fw_nStyles ? ID : kstyle; \n\
4380 jstyle = fw_surfaceStyles[kstyle]; \n\
4381 jstyle = jstyle == 1 ? 0 : jstyle; \n\
4387uniform float fw_stepSize; \n\
4388uniform float fw_tolerance; \n\
4389uniform float fw_surfaceVals[]; \n\
4390uniform int fw_nVals; \n\
4391uniform int fw_surfaceStyles[]; \n\
4392uniform int fw_nStyles; \n\
4403bool IntersectBox(Ray r, AABB aabb, out float t0, out float t1) \n\
4405 vec3 invR = 1.0 / r.Dir; \n\
4406 vec3 tbot = invR * (aabb.Min-r.Origin); \n\
4407 vec3 ttop = invR * (aabb.Max-r.Origin); \n\
4408 vec3 tmin = min(ttop, tbot); \n\
4409 vec3 tmax = max(ttop, tbot); \n\
4410 vec2 t = max(tmin.xx, tmin.yz); \n\
4411 t0 = max(t.x, t.y); \n\
4412 t = min(tmax.xx, tmax.yz); \n\
4413 t1 = min(t.x, t.y); \n\
4414 return t0 <= t1; \n\
4416/* PLUG-DECLARATIONS */ \n\
4418vec3 fw_TexCoord[1]; \n\
4420#define FW_MAXCLIPPLANES 4 \n\
4421uniform int fw_nclipplanes; \n\
4422uniform vec4 fw_clipplanes[FW_MAXCLIPPLANES]; \n\
4423bool clip (in vec3 vertex_object){ \n\
4424 bool iclip = false; \n\
4425 for ( int i=0; i<fw_nclipplanes; i++ ) { \n\
4426 if( dot( fw_clipplanes[i], vec4(vertex_object,1.0)) < 0.0) \n\
4437 debug_color = vec4(0.0); \n\
4438 float maxDist = length(fw_dimensions); //1.414214; //sqrt(2.0); \n\
4439 int numSamples = 128; \n\
4440 float fnumSamples = float(numSamples); \n\
4441 float stepSize = maxDist/fnumSamples; \n\
4442 float densityFactor = 5.0/fnumSamples; //.88; // 1.0=normal H3D, .5 see deeper \n\
4444 vec4 fragment_color; \n\
4446 vec3 rayDirection; \n\
4447 //convert window to frustum \n\
4448 rayDirection.xy = 2.0 * (gl_FragCoord.xy - fw_viewport.xy) / fw_viewport.zw - vec2(1.0); \n\
4449 rayDirection.z = 0.0; \n\
4450 vec3 rayOrigin; // = fw_RayOrigin; \n\
4451 //the equivalent of gluUnproject \n\
4452 //by unprojecting 2 points on ray here, this should also work with ortho viewpoint \n\
4453 vec4 ray4 = vec4(rayDirection,1.0); \n\
4454 vec4 org4 = ray4; \n\
4455 //if I back up the ray origin by -1.0 the front plane clipping works properly \n\
4456 ray4.z = 0.0; //1.0; \n\
4457 org4.z = -1.0; //0.0; \n\
4458 ray4 = fw_ModelViewProjInverse * ray4; \n\
4459 org4 = fw_ModelViewProjInverse * org4; \n\
4462 rayDirection = normalize(ray4.xyz - org4.xyz); \n\
4463 rayOrigin = org4.xyz; \n\
4465 Ray eye = Ray( rayOrigin, rayDirection); \n\
4466 vec3 half_dimensions = fw_dimensions * .5; \n\
4467 vec3 minus_half_dimensions = half_dimensions * -1.0; \n\
4468 AABB aabb = AABB(minus_half_dimensions,half_dimensions); \n\
4470 float tnear, tfar; \n\
4471 IntersectBox(eye, aabb, tnear, tfar); \n\
4472 if (tnear < 0.0) tnear = 0.0; \n\
4473 vec3 rayStart = eye.Origin + eye.Dir * tnear; \n\
4474 vec3 rayStop = eye.Origin + eye.Dir * tfar; \n\
4475 // Perform the ray marching: \n\
4476 vec3 pos = rayStart; \n\
4477 vec3 step = normalize(rayStop-rayStart) * stepSize; \n\
4478 float totaltravel = distance(rayStop, rayStart); \n\
4479 float travel = totaltravel; \n\
4481 vec3 Lo = vec3(0.0); \n\
4482 normal_eye = rayDirection; \n\
4483 vec3 pos2 = pos; \n\
4484 // Transform from object space to texture coordinate space: \n\
4485 pos2 = (pos2+half_dimensions)/fw_dimensions; \n\
4486 pos2 = clamp(pos2,0.001,.999); \n\
4487 raysum = vec4(0.0); \n\
4488 float depth = 0.0; \n\
4489 float lastdensity; \n\
4490 float lastdensity_iso; \n\
4492 for (int i=0; i < numSamples; ++i) { \n\
4493 //raysum = HeatMapColor(travel,0.0,2.0); \n\
4495 // ...lighting and absorption stuff here... \n\
4497 vertex_eye = pos2; \n\
4498 // Transform from object space to texture coordinate space: \n\
4499 pos2 = (pos2+half_dimensions)/fw_dimensions; \n\
4500 //pos2.z = 1.0 - pos2.z; //RHS to LHS \n\
4501 pos2 = clamp(pos2,0.001,.999); \n\
4502 vec3 texcoord3 = pos2; \n\
4503 bool iclip = false; \n\
4505 iclip = clip(vertex_eye); //clip(totaltravel - travel); \n\
4508 fragment_color = vec4(1.0,0.0,1.0,1.0); //do I need a default? seems not \n\
4509 /* UNP_LUG: texture3D ( fragment_color, texcoord3) */ \n\
4510 fragment_color = texture3Demu0( fw_Texture_unit0, texcoord3, magFilter); \n\
4513 if(inEnabledSegment(texcoord3,jstyle)){ \n\
4514 #endif //SEGMENT \n\
4515 //assuming we had a scalar input image and put L into .a, \n\
4516 // and computed gradient and put in .rgb : \n\
4517 float density = fragment_color.a; //recover the scalar value \n\
4518 vec3 gradient = fragment_color.rgb - vec3(.5,.5,.5); //we added 127 to (-127 to 127) in CPU gradient computation\n\
4519 if(fw_gradTexture == 1) { \n\
4520 float gradmag = texture3Demu0( fw_Texture_unit3, texcoord3, magFilter).a; \n\
4521 gradient = vec3(gradmag,gradmag,gradmag); \n\
4523 if(fw_gradTexture == 3){ \n\
4524 gradient = texture3Demu0( fw_Texture_unit3, texcoord3, magFilter).xyz - vec3(.5,.5,.5); \n\
4526 //vec4 voxel = vec4(density,density,density,density); //this is where the black visual voxels come from\n\
4527 vec4 voxel = vec4(density,density,density,density); //this is where the black visual voxels come from\n\
4531 lastdensity = density; \n\
4532 lastdensity_iso = 0.0; \n\
4534 int MODE = fw_nVals == 1 ? 1 : 3; \n\
4535 MODE = fw_stepSize != 0.0 && MODE == 1 ? 2 : 1; \n\
4536 #ifdef ISO_MODE3 \n\
4538 for(int i=0;i<fw_nVals;i++){ \n\
4539 float iso = fw_surfaceVals[i]; \n\
4540 if( sign( density - iso) != sign( lastdensity - iso) && length(gradient) > fw_tolerance ){ \n\
4542 int jstyle = min(i,fw_nStyles-1); \n\
4543 jstyle = fw_surfaceStyles[jstyle]; \n\
4544 if(jstyle == 1){ \n\
4545 /* PLUG: voxel_apply_DEFAULT (voxel, gradient) */ \n\
4546 } else if(jstyle == 2) { \n\
4547 /* PLUG: voxel_apply_OPACITY (voxel, gradient) */ \n\
4548 } else if(jstyle == 3) { \n\
4549 /* PLUG: voxel_apply_BLENDED (voxel, gradient) */ \n\
4550 } else if(jstyle == 4) { \n\
4551 /* PLUG: voxel_apply_BOUNDARY (voxel, gradient) */ \n\
4552 } else if(jstyle == 5) { \n\
4553 /* PLUG: voxel_apply_CARTOON (voxel, gradient) */ \n\
4554 } else if(jstyle == 6) { \n\
4555 /* PLUG: voxel_apply_DEFAULT (voxel, gradient) */ \n\
4556 } else if(jstyle == 7) { \n\
4557 /* PLUG: voxel_apply_EDGE (voxel, gradient) */ \n\
4558 } else if(jstyle == 8) { \n\
4559 /* PLUG: voxel_apply_PROJECTION (voxel, gradient) */ \n\
4560 } else if(jstyle == 9) { \n\
4561 /* PLUG: voxel_apply_SHADED (voxel, gradient) */ \n\
4562 } else if(jstyle == 10) { \n\
4563 /* PLUG: voxel_apply_SILHOUETTE (voxel, gradient) */ \n\
4564 } else if(jstyle == 11) { \n\
4565 /* PLUG: voxel_apply_TONE (voxel, gradient) */ \n\
4568 voxel = vec4(0.0); //similar to discard \n\
4571 lastdensity = density; \n\
4573 #else //ISO_MODE3 \n\
4575 float iso = fw_surfaceVals[0]; \n\
4576 if( sign( density - iso) != sign( lastdensity - iso) && length(gradient) > fw_tolerance ){ \n\
4577 //debug_color = HeatMapColor(iso,0.0,.3); \n\
4579 /* PLUG: voxel_apply (voxel, gradient) */ \n\
4581 voxel = vec4(0.0); //similar to discard \n\
4583 lastdensity = density; \n\
4584 } else if(MODE == 2){ \n\
4585 float iso = fw_surfaceVals[0]; \n\
4586 float density_iso = density / fw_stepSize; \n\
4587 if( sign( density_iso - iso) != sign( lastdensity_iso - iso) && length(gradient) > fw_tolerance ){ \n\
4589 /* PLUG: voxel_apply (voxel, gradient) */ \n\
4591 voxel = vec4(0.0); //similar to discard \n\
4593 lastdensity = density; \n\
4594 lastdensity_iso = density_iso; \n\
4596 #endif //ISO_MODE3 \n\
4599 //debug_color = HeatMapColor(float(jstyle),1.0,12.0); \n\
4600 //debug_color.a = .2; \n\
4601 if(jstyle == 1){ \n\
4602 /* PLUG: voxel_apply_DEFAULT (voxel, gradient) */ \n\
4603 } else if(jstyle == 2) { \n\
4604 /* PLUG: voxel_apply_OPACITY (voxel, gradient) */ \n\
4605 } else if(jstyle == 3) { \n\
4606 /* PLUG: voxel_apply_BLENDED (voxel, gradient) */ \n\
4607 } else if(jstyle == 4) { \n\
4608 /* PLUG: voxel_apply_BOUNDARY (voxel, gradient) */ \n\
4609 } else if(jstyle == 5) { \n\
4610 /* PLUG: voxel_apply_CARTOON (voxel, gradient) */ \n\
4611 } else if(jstyle == 6) { \n\
4612 /* PLUG: voxel_apply_DEFAULT (voxel, gradient) */ \n\
4613 } else if(jstyle == 7) { \n\
4614 /* PLUG: voxel_apply_EDGE (voxel, gradient) */ \n\
4615 } else if(jstyle == 8) { \n\
4616 /* PLUG: voxel_apply_PROJECTION (voxel, gradient) */ \n\
4617 } else if(jstyle == 9) { \n\
4618 /* PLUG: voxel_apply_SHADED (voxel, gradient) */ \n\
4619 } else if(jstyle == 10) { \n\
4620 /* PLUG: voxel_apply_SILHOUETTE (voxel, gradient) */ \n\
4621 } else if(jstyle == 11) { \n\
4622 /* PLUG: voxel_apply_TONE (voxel, gradient) */ \n\
4625 //non-iso rendering styles \n\
4626 //void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) \n\
4627 /* PLUG: voxel_apply (voxel, gradient) */ \n\
4628 #endif //SEGMENT \n\
4630 density = voxel.a; \n\
4631 //debug_color = HeatMapColor(densityFactor,0.134,.135); \n\
4632 T = (1.0 - raysum.a); \n\
4633 raysum.a += density * T; \n\
4634 raysum.rgb += voxel.rgb * T * density; \n\
4635 if(raysum.a > .99) { \n\
4639 } //if inEnabledSegment \n\
4640 #endif //SEGMENT \n\
4642 travel -= stepSize; \n\
4643 depth += stepSize; \n\
4644 if(travel <= 0.0) break; \n\
4648 //void PLUG_ray_apply (inout vec4 raysum) \n\
4649 /* PLUG: ray_apply (raysum) */ \n\
4650 if(true) FragColor = raysum; \n\
4651 else FragColor = debug_color; \n\
4661static const GLchar *plug_voxel_DEFAULT =
"\
4662void voxel_apply_DEFAULT (inout vec4 voxel, inout vec3 gradient) { \n\
4663 float alpha = voxel.a; \n\
4664 //voxel.a = voxel.r; \n\
4665 //voxel.rgb = vec3(alpha); \n\
4667void PLUG_voxel_apply_DEFAULT (inout vec4 voxel, inout vec3 gradient) { \n\
4668 voxel_apply_DEFAULT(voxel,gradient); \n\
4670void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4671 voxel_apply_DEFAULT(voxel,gradient); \n\
4676static const GLchar *plug_voxel_OPACITY =
"\
4677uniform int fw_opacTexture; \n\
4678//uniform sampler2D fw_Texture_unit3; \n\
4679void voxel_apply_OPACITY (inout vec4 voxel, inout vec3 gradient) { \n\
4680 if(fw_opacTexture == 1){ \n\
4681 vec4 lookup_color; \n\
4682 float lum = voxel.r; \n\
4683 vec2 texcoord = vec2(lum,0.0); \n\
4684 //this is too simple for the lookups in the specs \n\
4685 //http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#t-transferFunctionTextureCoordinateMapping \n\
4686 lookup_color = texture2D(fw_Texture_unit3,texcoord); \n\
4687 voxel.rgb = lookup_color.rgb; \n\
4691 float alpha = voxel.a; \n\
4692 voxel.a = voxel.r; \n\
4693 voxel.rgb = vec3(alpha); \n\
4696void PLUG_voxel_apply_OPACITY (inout vec4 voxel, inout vec3 gradient) { \n\
4697 voxel_apply_OPACITY(voxel, gradient); \n\
4699void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4700 voxel_apply_OPACITY(voxel, gradient); \n\
4705static const GLchar *plug_voxel_BLENDED =
"\
4706void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4711static const GLchar *plug_voxel_BOUNDARY =
"\n\
4712uniform float fw_boundaryOpacity; \n\
4713uniform float fw_retainedOpacity; \n\
4714uniform float fw_opacityFactor; \n\
4715void voxel_apply_BOUNDARY (inout vec4 voxel, inout vec3 gradient) { \n\
4716 float magnitude = length(gradient); \n\
4717 float factor = (fw_retainedOpacity + fw_boundaryOpacity*pow(magnitude,fw_opacityFactor) ); \n\
4718 voxel.a = voxel.a * factor; \n\
4719 //debug_color = HeatMapColor(factor,0.0,1.0); \n\
4721void PLUG_voxel_apply_BOUNDARY (inout vec4 voxel, inout vec3 gradient) { \n\
4722 voxel_apply_BOUNDARY(voxel, gradient); \n\
4724void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4725 voxel_apply_BOUNDARY(voxel, gradient); \n\
4730static const GLchar *plug_voxel_CARTOON =
"\n\
4731uniform int fw_colorSteps; \n\
4732uniform vec4 fw_orthoColor; \n\
4733uniform vec4 fw_paraColor; \n\
4734void voxel_apply_CARTOON (inout vec4 voxel, inout vec3 gradient) { \n\
4735 float len = length(gradient); \n\
4736 if(len > 0.01) { \n\
4737 vec3 ng = normalize(gradient); \n\
4738 float ndotv = dot(normal_eye,ng); \n\
4739 if(ndotv > 0.01 && voxel.a > 0.0) { \n\
4740 ndotv = floor(ndotv/float(fw_colorSteps))*float(fw_colorSteps); \n\
4741 vec4 color = mix(fw_orthoColor,fw_paraColor,ndotv); \n\
4742 //voxel.rgb = color.rgb*voxel.a; \n\
4743 voxel.rgb = color.rgb; \n\
4745 voxel = vec4(0.0); //similar to discard \n\
4748 voxel = vec4(0.0); //similar to discard \n\
4751void PLUG_voxel_apply_CARTOON (inout vec4 voxel, inout vec3 gradient) { \n\
4752 voxel_apply_CARTOON(voxel, gradient); \n\
4754void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4755 voxel_apply_CARTOON(voxel, gradient); \n\
4760static const GLchar *plug_voxel_COMPOSED =
"\
4761void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4766static const GLchar *plug_voxel_EDGE =
"\
4767uniform float fw_cosGradientThreshold; \n\
4768uniform vec4 fw_edgeColor; \n\
4769void voxel_apply_EDGE (inout vec4 voxel, inout vec3 gradient) { \n\
4770 float len = length(gradient); \n\
4771 if(len > 0.01) { \n\
4772 vec3 ng = normalize(gradient); \n\
4773 float ndotv = abs(dot(normal_eye,ng)); \n\
4774 if( ndotv < fw_cosGradientThreshold ) { \n\
4775 voxel = mix(voxel,fw_edgeColor,1.0 -ndotv); \n\
4779void PLUG_voxel_apply_EDGE (inout vec4 voxel, inout vec3 gradient) { \n\
4780 voxel_apply_EDGE(voxel, gradient); \n\
4782void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4783 voxel_apply_EDGE(voxel, gradient); \n\
4788static const GLchar *plug_voxel_PROJECTION =
"\n\
4789uniform float fw_intensityThreshold; \n\
4790uniform int fw_projType; \n\
4791float MAXPROJ = 0.0; \n\
4792float MINPROJ = 1.0; \n\
4793float AVEPROJ = 0.0; \n\
4794float LMIP = 0.0; \n\
4796int PROJCOUNT = 0; \n\
4797void voxel_apply_PROJECTION (inout vec4 voxel, inout vec3 gradient) { \n\
4799 float cval = length(voxel.rgb); \n\
4800 if(fw_projType == 1){ \n\
4802 if(cval < MINPROJ){ \n\
4804 RGBAPROJ = voxel; \n\
4806 }else if(fw_projType == 2){ \n\
4808 if(fw_intensityThreshold > 0.0){ \n\
4810 if(LMIP == 0.0) { \n\
4812 RGBAPROJ = voxel; \n\
4816 if(cval > MAXPROJ){ \n\
4818 RGBAPROJ = voxel; \n\
4821 }else if(fw_projType==3){ \n\
4823 AVEPROJ += cval; \n\
4824 RGBAPROJ += voxel; \n\
4827void PLUG_voxel_apply_PROJECTION (inout vec4 voxel, inout vec3 gradient) { \n\
4828 voxel_apply_PROJECTION(voxel, gradient); \n\
4830void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4831 voxel_apply_PROJECTION(voxel, gradient); \n\
4833void PLUG_ray_apply (inout vec4 raysum) { \n\
4834 float value = 0.0; \n\
4835 vec4 color = vec4(1.0); \n\
4836 if(fw_projType == 1){ \n\
4838 value = MINPROJ; \n\
4839 color = RGBAPROJ; \n\
4840 }else if(fw_projType == 2){ \n\
4842 if(fw_intensityThreshold > 0.0){ \n\
4845 color = RGBAPROJ; \n\
4848 value = MAXPROJ; \n\
4849 color = RGBAPROJ; \n\
4851 }else if(fw_projType==3){ \n\
4853 value = AVEPROJ / float(PROJCOUNT); \n\
4854 color = RGBAPROJ / float(PROJCOUNT); \n\
4856 //raysum.rgb = color.rgb * color.a; \n\
4857 //raysum.a = color.a; \n\
4859 raysum.rgb = vec3(value,value,value); \n\
4860// raysum.a = 1.0 - value; \n\
4861 //raysum.a = value;\n\
4862 //raysum.a = color.a; \n\
4863 //raysum = color; \n\
4868static const GLchar *plug_voxel_SHADED =
"\
4870#define MAX_LIGHTS 8 \n\
4871uniform int lightcount; \n\
4872//uniform float lightRadius[MAX_LIGHTS]; \n\
4873uniform int lightType[MAX_LIGHTS];//ANGLE like this \n\
4874struct fw_LightSourceParameters { \n\
4877 float intensity; \n\
4879 vec3 halfVector; \n\
4881 float spotBeamWidth; \n\
4882 float spotCutoff; \n\
4883 vec3 Attenuations; \n\
4884 float lightRadius; \n\
4886 float shadowIntensity; \n\
4890uniform fw_LightSourceParameters fw_LightSource[MAX_LIGHTS] /* gl_MaxLights */ ;\n\
4897 float visibilityRange; \n\
4899 int fogType; // 0 None, 1= FOGTYPE_LINEAR, 2 = FOGTYPE_EXPONENTIAL \n\
4900 // ifdefed int haveFogCoords; \n\
4902uniform fogParams fw_fogparams; \n\
4906//per-fragment lighting ie phong \n\
4907struct fw_MaterialParameters { \n\
4912 float shininess; \n\
4913 float occlusion; \n\
4914 float transparency; \n\
4917 float roughness; \n\
4919 // multitextures are disaggregated \n\
4924 int samplr[10]; //0 texture2D 1 cubeMap \n\
4926 int nt; //total single textures \n\
4927 //iunit [0] normal [1] emissive [2] occlusion [3] diffuse OR base [4] shininess OR metallicRoughness [5] specular [6] ambient \n\
4928 int tcount[7]; //num single textures 1= one texture 0=no texture 2+ = multitexture \n\
4929 int tstart[7]; // where in packed tindex list to start looping \n\
4930 //int cindex[7]; // which geometry multitexcoord channel 0=default \n\
4932uniform fw_MaterialParameters fw_FrontMaterial; \n\
4934uniform fw_MaterialParameters fw_BackMaterial; \n\
4936vec3 castle_ColorES; \n\
4938//per-vertex lighting - interpolated Emissive-specular \n\
4939varying vec3 castle_ColorES; //emissive shininess term \n\
4942uniform int fw_phase; \n\
4943uniform int fw_lighting; \n\
4944uniform int fw_shadows; \n\
4945void voxel_apply_SHADED (inout vec4 voxel, inout vec3 gradient) { \n\
4946 float len = length(gradient); \n\
4947 vec3 ng = vec3(0.0); \n\
4949 ng = normalize(gradient); \n\
4950 vec3 color = vec3(1.0); \n\
4952 vec3 castle_ColorES = fw_FrontMaterial.specular; \n\
4953 color.rgb = fw_FrontMaterial.diffuse.rgb; \n\
4955 color.rgb = vec3(0,0,0.0,0.0); \n\
4956 vec3 castle_ColorES = vec3(0.0,0.0,0.0); \n\
4958 // void add_light_contribution2(inout vec3 vertexcolor, inout vec3 specularcolor, in vec4 myPosition, in vec3 myNormal, \n\
4959 // in float mat_shininess, in float mat_ambient, in vec3 mat_diffuse, in vec3 mat_specular); \n\
4960 vec4 vertex_eye4 = vec4(vertex_eye,1.0); \n\
4961 /* PLUG: add_light_contribution2 (color, castle_ColorES, vertex_eye4, ng, fw_FrontMaterial.shininess, fw_FrontMaterial.ambient, fw_FrontMaterial.diffuse, fw_FrontMaterial.specular) */ \n\
4962 // voxel.rgb = color.rgb; \n\
4963 color = mix(color,castle_ColorES,dot(ng,normal_eye)); \n\
4964 voxel.rgb = color.rgb; \n\
4965 //voxel.rgb = voxel.rgb * color.rgb; \n\
4967void PLUG_voxel_apply_SHADED (inout vec4 voxel, inout vec3 gradient) { \n\
4968 voxel_apply_SHADED(voxel, gradient); \n\
4970void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4971 voxel_apply_SHADED(voxel, gradient); \n\
4976static const GLchar *plug_voxel_SILHOUETTE =
"\n\
4977uniform float fw_BoundaryOpacity; \n\
4978uniform float fw_RetainedOpacity; \n\
4979uniform float fw_Sharpness; \n\
4980void voxel_apply_SILHOUETTE (inout vec4 voxel, inout vec3 gradient) { \n\
4981 float len = length(gradient); \n\
4982 if(len > 0.01) { \n\
4983 vec3 ng = normalize(gradient); \n\
4984 float ndotv = abs(dot(ng,normal_eye)); \n\
4985 float factor = (fw_RetainedOpacity + fw_BoundaryOpacity*pow(1.0 - ndotv,fw_Sharpness)); \n\
4986 //float factor = (fw_RetainedOpacity + pow(fw_BoundaryOpacity*(1.0 - ndotv),fw_Sharpness)); \n\
4987 //debug_color = HeatMapColor(factor,0.0,1.0); \n\
4988 voxel.a = voxel.a * factor; \n\
4991void PLUG_voxel_apply_SILHOUETTE (inout vec4 voxel, inout vec3 gradient) { \n\
4992 voxel_apply_SILHOUETTE(voxel, gradient); \n\
4994void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
4995 voxel_apply_SILHOUETTE(voxel, gradient); \n\
5000static const GLchar *plug_voxel_TONE =
"\
5001uniform vec4 fw_coolColor; \n\
5002uniform vec4 fw_warmColor; \n\
5003void voxel_apply_TONE (inout vec4 voxel, inout vec3 gradient) { \n\
5004 float len = length(gradient); \n\
5007 vec3 ng = normalize(gradient); \n\
5008 //vec3 L = normalize(vec3(-.707,-.707,.707)); \n\
5009 float cc = (1.0 + dot(normal_eye,ng))*.5; \n\
5010 //float cc = (1.0 + dot(L,ng))*.5; \n\
5011 //debug_color = HeatMapColor(cc,0.0,1.0); \n\
5012 color = mix(fw_coolColor.rgb,fw_warmColor.rgb,cc); \n\
5013 voxel = vec4(color,voxel.a); \n\
5016 //debug_color = vec4(0.0); \n\
5019void PLUG_voxel_apply_TONE (inout vec4 voxel, inout vec3 gradient) { \n\
5020 voxel_apply_TONE(voxel, gradient); \n\
5022void PLUG_voxel_apply (inout vec4 voxel, inout vec3 gradient) { \n\
5023 voxel_apply_TONE(voxel, gradient); \n\
5034static const GLchar *volumeBlendedFragmentGLES2 =
" \n\
5037//precision highp float; \n\
5038precision mediump float; \n\
5040#define varying in \n\
5041#define texture2D texture \n\
5042#define texture3D texture \n\
5043#define textureCube texture \n\
5044#define texture2DProj textureProj \n\
5045#define texture3DProj textureProj \n\
5046out vec4 FragColor; \n\
5047 vec4 HeatMapColor(float value, float minValue, float maxValue) \n\
5049 //used for debugging. If min=0,max=1 then magenta is 0, blue,green,yellow, red is 1 \n\
5051 int HEATMAP_COLORS_COUNT; \n\
5053 HEATMAP_COLORS_COUNT = 6; \n\
5054 colors[0] = vec4(0.32, 0.00, 0.32, 1.0); \n\
5055 colors[1] = vec4( 0.00, 0.00, 1.00, 1.00); \n\
5056 colors[2] = vec4(0.00, 1.00, 0.00, 1.00); \n\
5057 colors[3] = vec4(1.00, 1.00, 0.00, 1.00); \n\
5058 colors[4] = vec4(1.00, 0.60, 0.00, 1.00); \n\
5059 colors[5] = vec4(1.00, 0.00, 0.00, 1.00); \n\
5060 float ratio=(float(HEATMAP_COLORS_COUNT)-1.0)*clamp((value-minValue)/(maxValue-minValue),0.0,1.0); \n\
5061 int indexMin=int(floor(ratio)); \n\
5062 int indexMax= indexMin+1 < HEATMAP_COLORS_COUNT-1 ? indexMin+1 : HEATMAP_COLORS_COUNT-1; \n\
5063 ret = mix(colors[indexMin], colors[indexMax], ratio-float(indexMin)); \n\
5064 if(value < minValue) ret = vec4(0.0,0.0,0.0,1.0); \n\
5065 if(value > maxValue) ret = vec4(1.0,1.0,1.0,1.0); \n\
5068vec4 debug_color; \n\
5070uniform vec4 fw_viewport; \n\
5071uniform sampler2D fw_Texture_unit0; \n\
5072uniform sampler2D fw_Texture_unit1; \n\
5073uniform sampler2D fw_Texture_unit2; \n\
5074uniform sampler2D fw_Texture_unit3; \n\
5075uniform float fw_iwtc1; \n\
5076uniform float fw_iwtc2; \n\
5077uniform int fw_iwtf1; \n\
5078uniform int fw_iwtf2; \n\
5079uniform int fw_haveTransfers; \n\
5080vec3 weightcolor( in vec3 color, in int func, in float wt, in float ov, in float oblend, in sampler2D table){ \n\
5083 ret = color * wt; \n\
5084 }else if(func == 2){ \n\
5085 ret = color * ov; \n\
5086 }else if(func == 3){ \n\
5087 ret = color * oblend; \n\
5088 }else if(func == 4){ \n\
5089 ret = color * (1.0 - oblend); \n\
5090 }else if(func == 5){ \n\
5091 vec2 texcoord = color.rg;\n\
5092 ret = color * texture2D(table,texcoord).r; \n\
5096float weightalpha( in float alpha, in int func, in float wt, in float ov, in float oblend, in sampler2D table){ \n\
5099 ret = alpha * wt; \n\
5100 }else if(func == 2){ \n\
5101 ret = alpha * ov; \n\
5102 }else if(func == 3){ \n\
5103 ret = alpha * oblend; \n\
5104 }else if(func == 4){ \n\
5105 ret = alpha * (1.0 - oblend); \n\
5106 }else if(func == 5){ \n\
5107 vec2 texcoord = vec2(alpha,0);\n\
5108 ret = alpha * texture2D(table,texcoord).r; \n\
5114 vec2 fc = (gl_FragCoord.xy - fw_viewport.xy) / fw_viewport.zw; \n\
5115 vec4 frag0 = texture2D(fw_Texture_unit0,fc); \n\
5116 vec4 frag1 = texture2D(fw_Texture_unit1,fc); \n\
5117 vec3 cv = frag0.rgb; \n\
5118 float ov = frag0.a; \n\
5119 vec3 cblend = frag1.rgb; \n\
5120 float oblend = frag1.a; \n\
5123 cvw = weightcolor(cv,fw_iwtf1,fw_iwtc1,ov,oblend,fw_Texture_unit2); \n\
5124 ovw = weightalpha(ov,fw_iwtf1,fw_iwtc1,ov,oblend,fw_Texture_unit2); \n\
5125 cbw = weightcolor(cblend,fw_iwtf2,fw_iwtc2,ov,oblend,fw_Texture_unit3); \n\
5126 obw = weightalpha(oblend,fw_iwtf2,fw_iwtc2,ov,oblend,fw_Texture_unit3); \n\
5127 vec3 cg = clamp( cvw + cbw, 0.0, 1.0); \n\
5128 float og = clamp(ovw + obw, 0.0, 1.0); \n\
5130 FragColor = vec4(cg,og); \n\
5135const char *getVolumeVertex(
void){
5136 return volumeVertexGLES2;
5138const char *getVolumeFragment(){
5139 return volumeFragmentGLES2;
5141int getSpecificShaderSourceVolume (
const GLchar **vertexSource,
const GLchar **fragmentSource,
shaderflagsstruct whichOne)
5147 int retval, unique_int;
5148 unsigned int volflags;
5149 unsigned char volflag[7];
5151 char *CompleteCode[3];
5154 if(whichOne.usershaders )
5159 vs = strdup(getVolumeVertex());
5160 fs = strdup(getVolumeFragment());
5162 CompleteCode[SHADERPART_VERTEX] = vs;
5163 CompleteCode[SHADERPART_GEOMETRY] = NULL;
5164 if(whichOne.volume == SHADERFLAGS_VOLUME_STYLE_BLENDED << 4){
5165 CompleteCode[SHADERPART_FRAGMENT] = STRDUP(volumeBlendedFragmentGLES2);
5168 CompleteCode[SHADERPART_FRAGMENT] = fs;
5175 if (!GLSL_max_version) {
5181 GLSL_max_version = get_GLSL_max_version();
5191 AddVersion0(SHADERPART_VERTEX, iver, aver, CompleteCode);
5192 AddVersion0(SHADERPART_FRAGMENT, iver, aver, CompleteCode);
5193 AddDefine(SHADERPART_FRAGMENT,
"MOBILE", CompleteCode);
5196 if (GLSL_max_version >= 130) {
5201 iver = GLSL_max_version;
5203 AddVersion(SHADERPART_VERTEX, iver, CompleteCode);
5204 AddVersion(SHADERPART_FRAGMENT, iver, CompleteCode);
5205 AddDefine(SHADERPART_VERTEX,
"FULL", CompleteCode);
5206 AddDefine(SHADERPART_FRAGMENT,
"FULL", CompleteCode);
5209 AddVersion(SHADERPART_VERTEX, GLSL_max_version, CompleteCode);
5210 AddVersion(SHADERPART_FRAGMENT, GLSL_max_version, CompleteCode);
5214 if(whichOne.volume == SHADERFLAGS_VOLUME_STYLE_BLENDED << 4){
5215 *fragmentSource = CompleteCode[SHADERPART_FRAGMENT];
5216 *vertexSource = CompleteCode[SHADERPART_VERTEX];
5223 AddDefine(SHADERPART_FRAGMENT,
"TEX3D",CompleteCode);
5224 Plug(SHADERPART_FRAGMENT,plug_fragment_texture3D_apply_volume,CompleteCode,&unique_int);
5227 if(DESIRE(whichOne.volume,SHADERFLAGS_VOLUME_DATA_BASIC)){
5228 AddDefine(SHADERPART_FRAGMENT,
"BASIC",CompleteCode);
5230 if(DESIRE(whichOne.volume,SHADERFLAGS_VOLUME_DATA_ISO)){
5231 AddDefine(SHADERPART_FRAGMENT,
"ISO",CompleteCode);
5232 if(DESIRE(whichOne.volume,SHADERFLAGS_VOLUME_DATA_ISO_MODE3)){
5233 AddDefine(SHADERPART_FRAGMENT,
"ISO_MODE3",CompleteCode);
5236 if(DESIRE(whichOne.volume,SHADERFLAGS_VOLUME_DATA_SEGMENT)){
5237 AddDefine(SHADERPART_FRAGMENT,
"SEGMENT",CompleteCode);
5239 if(DESIRE(whichOne.base,CLIPPLANE_SHADER)){
5240 AddDefine(SHADERPART_FRAGMENT,
"CLIP",CompleteCode);
5246 volflags = whichOne.volume;
5250 int iflag = (volflags >> (7-i)*4) & 0xF;
5252 volflag[kflags] = iflag;
5257 for(k=0;k<kflags;k++){
5259 case SHADERFLAGS_VOLUME_STYLE_DEFAULT:
5260 AddDefine(SHADERPART_FRAGMENT,
"DEFAULT",CompleteCode);
5261 Plug(SHADERPART_FRAGMENT,plug_voxel_DEFAULT,CompleteCode,&unique_int);
5263 case SHADERFLAGS_VOLUME_STYLE_OPACITY:
5264 AddDefine(SHADERPART_FRAGMENT,
"OPACITY",CompleteCode);
5265 Plug(SHADERPART_FRAGMENT,plug_voxel_OPACITY,CompleteCode,&unique_int);
5267 case SHADERFLAGS_VOLUME_STYLE_BLENDED:
5268 AddDefine(SHADERPART_FRAGMENT,
"BLENDED",CompleteCode);
5269 Plug(SHADERPART_FRAGMENT,plug_voxel_BLENDED,CompleteCode,&unique_int);
5271 case SHADERFLAGS_VOLUME_STYLE_BOUNDARY:
5272 AddDefine(SHADERPART_FRAGMENT,
"BOUNDARY",CompleteCode);
5273 Plug(SHADERPART_FRAGMENT,plug_voxel_BOUNDARY,CompleteCode,&unique_int);
5275 case SHADERFLAGS_VOLUME_STYLE_CARTOON:
5276 AddDefine(SHADERPART_FRAGMENT,
"CARTOON",CompleteCode);
5277 Plug(SHADERPART_FRAGMENT,plug_voxel_CARTOON,CompleteCode,&unique_int);
5279 case SHADERFLAGS_VOLUME_STYLE_COMPOSED:
5280 AddDefine(SHADERPART_FRAGMENT,
"COMPOSED",CompleteCode);
5281 Plug(SHADERPART_FRAGMENT,plug_voxel_COMPOSED,CompleteCode,&unique_int);
5283 case SHADERFLAGS_VOLUME_STYLE_EDGE:
5284 AddDefine(SHADERPART_FRAGMENT,
"EDGE",CompleteCode);
5285 Plug(SHADERPART_FRAGMENT,plug_voxel_EDGE,CompleteCode,&unique_int);
5287 case SHADERFLAGS_VOLUME_STYLE_PROJECTION:
5288 AddDefine(SHADERPART_FRAGMENT,
"PROJECTION",CompleteCode);
5289 Plug(SHADERPART_FRAGMENT,plug_voxel_PROJECTION,CompleteCode,&unique_int);
5291 case SHADERFLAGS_VOLUME_STYLE_SHADED:
5292 AddDefine(SHADERPART_FRAGMENT,
"SHADED",CompleteCode);
5293 Plug(SHADERPART_FRAGMENT,plug_voxel_SHADED,CompleteCode,&unique_int);
5296 AddDefine(SHADERPART_FRAGMENT,
"LIT",CompleteCode);
5297 AddDefine(SHADERPART_FRAGMENT,
"LITE",CompleteCode);
5298 Plug(SHADERPART_FRAGMENT,plug_vertex_lighting_ADSLightModel_volume,CompleteCode,&unique_int);
5300 case SHADERFLAGS_VOLUME_STYLE_SILHOUETTE:
5301 AddDefine(SHADERPART_FRAGMENT,
"SILHOUETTE",CompleteCode);
5302 Plug(SHADERPART_FRAGMENT,plug_voxel_SILHOUETTE,CompleteCode,&unique_int);
5304 case SHADERFLAGS_VOLUME_STYLE_TONE:
5305 AddDefine(SHADERPART_FRAGMENT,
"TONE",CompleteCode);
5306 Plug(SHADERPART_FRAGMENT,plug_voxel_TONE,CompleteCode,&unique_int);
5318 *fragmentSource = CompleteCode[SHADERPART_FRAGMENT];
5319 *vertexSource = CompleteCode[SHADERPART_VERTEX];
5326 FILE *fp = fopen(
"C:/tmp/composed_shader.vert",
"w+");
5327 fwrite(*vertexSource,strlen(*vertexSource),1,fp);
5329 fp = fopen(
"C:/tmp/composed_shader.frag",
"w+");
5330 fwrite(*fragmentSource,strlen(*fragmentSource),1,fp);
5342char* vertexDepth =
"#version 330 core \n\
5343//layout(location = 0) in vec3 fw_Vertex; \n\
5344in vec4 fw_Vertex; \n\
5346uniform mat4 fw_ModelViewMatrix; \n\
5347uniform mat4 fw_ProjectionMatrix; \n\
5351 gl_Position = fw_ProjectionMatrix * fw_ModelViewMatrix * fw_Vertex; \n\
5353char* vertexDepthParticle =
"#version 330 core \n\
5354//layout(location = 0) in vec3 fw_Vertex; \n\
5355#define PARTICLE 1 \n\
5356in vec4 fw_Vertex; \n\
5358uniform mat4 fw_ModelViewMatrix; \n\
5359uniform mat4 fw_ProjectionMatrix; \n\
5361uniform vec3 particlePosition; \n\
5362uniform vec3 particleDirection; \n\
5363unifomr mat4 particleTransform; \n\
5364uniform int fw_ParticleGeomType; \n\
5365#endif //PARTICLE \n\
5369 vec4 vertex = fw_Vertex; \n\
5371 if(fw_ParticleGeomType != 4){ \n\
5373 rot = mat4(1.0); \n\
5374 rot2 = mat4(1.0); \n\
5375 float yaw = atan(particleDirection.y,particleDirection.x); \n\
5376 float pitch = asin(particleDirection.z); \n\
5377 rot[0][0] = cos(yaw); \n\
5378 rot[1][1] = rot[0][0]; \n\
5379 rot[0][1] = sin(yaw); \n\
5380 rot[1][0] = -rot[0][1]; \n\
5381 rot2[0][0] = cos(pitch); \n\
5382 rot2[2][2] = rot2[0][0]; \n\
5383 rot2[0][2] = sin(pitch); \n\
5384 rot2[2][0] = -rot2[0][2]; \n\
5385 rot = rot * rot2; \n\
5386 vertex_object = rot * particleTransform * vertex_object; \n\
5387 //vertex_object.xyz /= vertex_object.w; \n\
5388 //vertex_object.w = 1.0; \n\
5390 //vertex_object = particleTransform * vertex_object; \n\
5391 vertex.xyz += particlePosition; \n\
5393 //sprite: align to viewer \n\
5394 if(fw_ParticleGeomType == 4){ \n\
5395 vec4 ppos = vec4(particlePosition,1.0); \n\
5396 vec4 particle_eye = fw_ModelViewMatrix * ppos; \n\
5398 vec4 particle_eye1 = fw_ModelViewMatrix * ppos; \n\
5399 float pscal = length(particle_eye1.xyz - particle_eye.xyz); \n\
5400 vertex = particle_eye + pscal*vertex; \n\
5402 #endif //PARTICLE \n\
5403 vertex = fw_ProjectionMatrix * fw_ModelViewMatrix * vertex; \n\
5404 gl_Position = vertex; \n\
5407char* fragDepth =
"#version 330 core \n\
5411 gl_FragDepth = gl_FragCoord.z; \n\
5412 //gl_FragColor = vec4(vec3(gl_FragCoord.z),1.0); \n\
5414int getSpecificShaderSourceDepth(
const GLchar** vertexSource,
const GLchar** fragmentSource,
shaderflagsstruct whichOne) {
5415 if(DESIRE(whichOne.base, PARTICLE_SHADER))
5416 *vertexSource = strdup(vertexDepthParticle);
5418 *vertexSource = strdup(vertexDepth);
5419 *fragmentSource = strdup(fragDepth);
5424char* vertexQuad =
"#version 330 core \n\
5425layout(location = 0) in vec3 aPos; \n\
5426layout(location = 1) in vec2 aTexCoords; \n\
5428out vec2 TexCoords; \n\
5432 TexCoords = aTexCoords; \n\
5433 gl_Position = vec4(aPos, 1.0); \n\
5436char* vertexQuadMatrix =
"#version 330 core \n\
5437layout(location = 0) in vec3 aPos; \n\
5438layout(location = 1) in vec2 aTexCoords; \n\
5439uniform mat4 fw_ModelViewMatrix; \n\
5441out vec2 TexCoords; \n\
5445 TexCoords = aTexCoords; \n\
5446 gl_Position = fw_ModelViewMatrix * vec4(aPos, 1.0); \n\
5449char* fragmentQuadNormal =
"#version 330 core \n\
5450out vec4 FragColor; \n\
5451in vec2 TexCoords; \n\
5452uniform sampler2D textureUnit; \n\
5455 FragColor = texture(textureUnit, TexCoords); \n\
5458char* fragmentQuadDepthOrtho =
"#version 330 core \n\
5459out vec4 FragColor; \n\
5460in vec2 TexCoords; \n\
5461uniform sampler2D textureUnit; \n\
5464 float depthValue = texture(textureUnit, TexCoords).r; \n\
5465 FragColor = vec4(vec3(depthValue), 1.0); // orthographic \n\
5468char* fragmentQuadDepthPerspective =
"#version 330 core \n\
5469out vec4 FragColor; \n\
5470in vec2 TexCoords; \n\
5471uniform sampler2D textureUnit; \n\
5472uniform float near_plane; \n\
5473uniform float far_plane; \n\
5475// required when using a perspective projection matrix \n\
5476float LinearizeDepth(float depth) \n\
5478 float z = depth * 2.0 - 1.0; // Back to NDC \n\
5479 return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane)); \n\
5484 float depthValue = texture(textureUnit, TexCoords).r; \n\
5485 FragColor = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective \n\
5486 //FragColor = vec4(vec3(depthValue), 1.0); // orthographic \n\
5489char* fragmentQuadDepthCube =
"#version 330 core \n\
5490out vec4 FragColor; \n\
5491in vec2 TexCoords; \n\
5492uniform samplerCube textureUnit; \n\
5493//uniform samplerCube textureUnitCube[16]; //challenge test to see if [16] cubemaps is a problem \n\
5494//uniform int depthunit; \n\
5495uniform float near_plane; \n\
5496uniform float far_plane; \n\
5498// required when using a perspective projection matrix \n\
5499float LinearizeDepth(float depth) \n\
5501 float z = depth * 2.0 - 1.0; // Back to NDC \n\
5502 return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane)); \n\
5507 float phi = (TexCoords.x * 2.0 -1.0)*.5*3.14159623; \n\
5508 float theta = (TexCoords.y * 2.0 -.5)*3.14159623; \n\
5509 vec3 tc = vec3(cos(theta)*cos(phi),sin(theta)*cos(phi),sin(phi)); \n\
5510 //float depthValue = texture(textureUnitCube[depthunit], tc).r; \n\
5511 float depthValue = texture(textureUnit, tc).r; \n\
5512 //vec3 cc = (tc*.5 +.5)*depthValue;\n\
5513 //vec3 cc = vec3(TexCoords.x,TexCoords.y,depthValue); \n\
5514 //FragColor = vec4(cc,1.0); \n\
5515 //if(depthValue == 1.0) depthValue = 0.0; \n\
5516 //depthValue = (depthValue - .8)*4.0; \n\
5517 //FragColor = vec4(vec3(depthValue),1.0); \n\
5518 FragColor = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective \n\
5519 //FragColor = vec4(vec3(depthValue), 1.0); // orthographic \n\
5523char* fragmentQuadColorCube =
"#version 330 core \n\
5524out vec4 FragColor; \n\
5525in vec2 TexCoords; \n\
5526uniform samplerCube textureUnit; \n\
5529 float phi = (TexCoords.x * 2.0 -1.0)*.5*3.14159623; \n\
5530 float theta = (TexCoords.y * 2.0 -.5)*3.14159623; \n\
5531 vec3 tc = vec3(cos(theta)*cos(phi),sin(theta)*cos(phi),sin(phi)); \n\
5532 FragColor = texture(textureUnit, tc); \n\
5536char* fragmentQuadDepthCubeTee =
"#version 330 core \n\
5537out vec4 FragColor; \n\
5538in vec2 TexCoords; \n\
5539uniform samplerCube textureUnit; \n\
5540uniform float near_plane; \n\
5541uniform float far_plane; \n\
5543// required when using a perspective projection matrix \n\
5544float LinearizeDepth(float depth) \n\
5546 float z = depth * 2.0 - 1.0; // Back to NDC \n\
5547 return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane)); \n\
5552 float row = floor(TexCoords.y * 3.0); \n\
5553 int irow = int(round(row)); \n\
5554 float y = min((TexCoords.y*3.0 - row),1.0)*2.0 - 1.0; \n\
5555 float col = floor(TexCoords.x * 4.0); \n\
5556 int icol = int(round(col));\n\
5557 float x = min((TexCoords.x*4.0 - col),1.0)*2.0 - 1.0; \n\
5558 if(irow == 0 || irow == 2) \n\
5559 if (icol != 1) discard; \n\
5561 if(irow == 1 && icol == 0) tc = vec3(-1.0,y,-x); \n\
5562 if (irow == 1 && icol == 1) tc = vec3(x, y, -1.0); \n\
5563 if (irow == 1 && icol == 2) tc = vec3(1.0, y, x); \n\
5564 if (irow == 1 && icol == 3) tc = vec3(-x, y, 1.0); \n\
5565 if (irow == 0 && icol == 1) tc = vec3(x, -1.0, -y); \n\
5566 if (irow == 2 && icol == 1) tc = vec3(x, 1.0, y); \n\
5567 tc = normalize(tc); \n\
5568 float depthValue = texture(textureUnit, tc).r; \n\
5569 FragColor = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective \n\
5573int getSpecificShaderSourceDebug(
const GLchar** vertexSource,
const GLchar** fragmentSource,
shaderflagsstruct whichOne) {
5574 if(whichOne.debug == 7)
5575 *vertexSource = strdup(vertexQuadMatrix);
5577 *vertexSource = strdup(vertexQuad);
5579 switch (whichOne.debug) {
5582 *fragmentSource = strdup(fragmentQuadNormal);
5585 *fragmentSource = strdup(fragmentQuadDepthOrtho);
5588 *fragmentSource = strdup(fragmentQuadDepthPerspective);
5591 *fragmentSource = strdup(fragmentQuadDepthCube);
5594 *fragmentSource = strdup(fragmentQuadColorCube);
5597 *fragmentSource = strdup(fragmentQuadDepthCubeTee);