ecere/gfx/drivers/GL/defaultShader: Fixed restoring lights state
[sdk] / ecere / src / gfx / drivers / gl3 / defaultShader.ec
1 import "shaders"
2
3 #include "gl123es.h"
4
5 namespace gfx::drivers;
6
7 // **********   Default Shader   **********
8 public enum LightMode { off, dir, pos, posAtt, posSpot, posSpotAtt };
9 public enum SwizzleMode { off, alpha, red };
10
11 public class DefaultShaderBits : uint64
12 {
13 public:
14    bool lighting:1;
15    bool nonLocalViewer:1;
16    bool twoSided:1;
17    bool specular:1;
18    bool separateSpecular:1;
19    bool blinnSpecular:1;
20    uint lightBits:24;
21    bool perVertexColor:1;
22    SwizzleMode swizzle:2;
23    bool textureMatrix:1;
24    bool texturing:1;
25    bool cubeMap:1;
26    bool modelView:1;
27    bool fog:1;
28    bool normalsMapping:1;
29    bool specularMapping:1;
30    bool environmentMapping:1;
31    bool reflection:1;
32    bool reflectionMap:1;
33    bool refraction:1;
34    bool debugging:1;
35 };
36
37 public class CompiledDefaultShader : CompiledShader
38 {
39 public:
40    // Uniforms
41    int uPrjMatrix;
42    int uMVMatrix;
43    int uTextureMatrix;
44    int uNormalsMatrix;
45    int uFogDensity;
46    int uFogColor;
47    int uGlobalAmbient;
48    int uNearPlane;
49    int uLightsPos[8];
50    int uLightsDiffuse[8];
51    int uLightsAmbient[8];
52    int uLightsSpecular[8];
53    int uLightsAtt[8];
54    int uLightsSpotDir[8];
55    int uLightsSpotCutOffCos[8];
56    int uLightsSpotExp[8];
57    int uMatDiffuse;
58    int uMatAmbient;
59    int uMatSpecular;
60    int uMatEmissive;
61    int uMatPower;
62    int uMatOpacity;
63    int uDiffuseTex;
64    int uBumpTex;
65    int uSpecularTex;
66    int uEnvTex;
67    int uReflectTex;
68    int uRefractionETA;
69    int uMatReflectivity;
70    int uCubeMapMatrix;
71
72    void registerUniforms(int program, DefaultShaderBits state)
73    {
74 #if ENABLE_GL_SHADERS
75       uPrjMatrix        = glGetUniformLocation(program, "projection_matrix");
76       uMatDiffuse       = glGetUniformLocation(program, "matDiffuse");
77
78       if(state.modelView)
79          uMVMatrix         = glGetUniformLocation(program, "modelview_matrix");
80
81       if(state.lighting)
82       {
83          int i;
84
85          for(i = 0; i < 8; i++)
86          {
87             char name[100];
88
89             sprintf(name, "lightsPos[%d]", i);
90             uLightsPos[i] = glGetUniformLocation(program, name);
91
92             sprintf(name, "lightsDiffuse[%d]", i);
93             uLightsDiffuse[i] = glGetUniformLocation(program, name);
94
95             sprintf(name, "lightsAmbient[%d]", i);
96             uLightsAmbient[i] = glGetUniformLocation(program, name);
97
98             sprintf(name, "lightsSpecular[%d]", i);
99             uLightsSpecular[i] = glGetUniformLocation(program, name);
100
101             sprintf(name, "lightsAtt[%d]", i);
102             uLightsAtt[i] = glGetUniformLocation(program, name);
103
104             sprintf(name, "lightsSpotDir[%d]", i);
105             uLightsSpotDir[i] = glGetUniformLocation(program, name);
106
107             sprintf(name, "lightsSpotCutOffCos[%d]", i);
108             uLightsSpotCutOffCos[i] = glGetUniformLocation(program, name);
109
110             sprintf(name, "lightsSpotExp[%d]", i);
111             uLightsSpotExp[i] = glGetUniformLocation(program, name);
112          }
113
114          uNearPlane        = glGetUniformLocation(program, "nearPlane");
115          uNormalsMatrix    = glGetUniformLocation(program, "normals_matrix");
116          uGlobalAmbient    = glGetUniformLocation(program, "globalAmbient");
117          uMatAmbient       = glGetUniformLocation(program, "matAmbient");
118          uMatEmissive      = glGetUniformLocation(program, "matEmissive");
119          if(state.specular)
120          {
121             uMatSpecular      = glGetUniformLocation(program, "matSpecular");
122             uMatPower         = glGetUniformLocation(program, "matPower");
123          }
124       }
125
126       if((state.specularMapping || state.normalsMapping || state.texturing || state.reflectionMap || state.cubeMap) && state.textureMatrix)
127          uTextureMatrix    = glGetUniformLocation(program, "texture_matrix");
128       if(state.texturing || state.cubeMap)
129          uDiffuseTex    = glGetUniformLocation(program, "diffuseTex");
130       if(state.normalsMapping)
131          uBumpTex       = glGetUniformLocation(program, "bumpTex");
132       if(state.specularMapping)
133          uSpecularTex   = glGetUniformLocation(program, "specularTex");
134       if(state.environmentMapping)
135       {
136          uEnvTex = glGetUniformLocation(program, "envTex");
137          uCubeMapMatrix = glGetUniformLocation(program, "cubemap_matrix");
138
139          if(state.refraction)
140             uRefractionETA = glGetUniformLocation(program, "matRefractionETA");
141          if(state.reflection)
142             uMatReflectivity = glGetUniformLocation(program, "matReflectivity");
143          if(state.reflectionMap)
144             uReflectTex  = glGetUniformLocation(program, "reflectTex");
145       }
146
147       if(state.fog)
148       {
149          uFogDensity       = glGetUniformLocation(program, "fogDensity");
150          uFogColor         = glGetUniformLocation(program, "fogColor");
151       }
152 #endif
153    }
154 };
155
156 public class DefaultShader : Shader
157 {
158    vertexShaderFile   = "<:ecere>shaders/default.vert";
159    fragmentShaderFile = "<:ecere>shaders/default.frag";
160
161 public:
162    float modelView[16];
163    float projection[16];
164    float matTexture[16];
165    float cubemap_matrix[9];
166
167    float normalsMatrix[9];
168    float nearPlane;
169    float globalAmbient[3];
170
171    // Lights
172    float lDiffuse [8][4];
173    float lAmbient [8][3];
174    float lSpecular[8][3];
175    float lPosition[8][3];
176    float lAtt[8][3];
177    float lCutOffCos[8];
178    float lSpotDir[8][3];
179    float lSpotExp[8];
180
181    // Material
182    float diffuse[4];
183    float ambient[3];
184    float specular[3];
185    float emissive[3];
186    float power;
187    float refractionETA, reflectivity;
188
189    bool fogOn;
190    uint lightBits;
191    float fogDensity;
192    float fogColor[3];
193
194    float color[4];
195
196    DefaultShaderBits backLightState; backLightState = DefaultShaderBits { separateSpecular = true };
197
198    DefaultShader()
199    {
200       color[0] = 1, color[1] = 1, color[2] = 1, color[3] = 1;
201       diffuse[0] = 1, diffuse[1] = 1, diffuse[2] = 1, diffuse[3] = 1;
202       ambient[0] = 1, ambient[1] = 1, ambient[2] = 1;
203
204       // state = DefaultShaderBits { blinnSpecular = true };
205    }
206
207    void bindAttribs(int program)
208    {
209 #if ENABLE_GL_SHADERS
210       DefaultShaderBits state = this.state;
211       glBindAttribLocation(program, GLBufferContents::vertex,    "vertex");
212       if(state.perVertexColor)
213          glBindAttribLocation(program, GLBufferContents::color,     "color");
214       if(state.texturing || state.normalsMapping || state.specularMapping || state.reflectionMap)
215          glBindAttribLocation(program, GLBufferContents::texCoord,  "texCoord");
216       if(state.lighting)
217          glBindAttribLocation(program, GLBufferContents::normal,    "normal");
218       if(state.normalsMapping)
219       {
220          glBindAttribLocation(program, GLBufferContents::tangent1,  "tangent1");
221          glBindAttribLocation(program, GLBufferContents::tangent2,  "tangent2");
222       }
223 #endif
224    }
225
226    CompiledDefaultShader registerShader(int program, uint64 state)
227    {
228       CompiledDefaultShader shader { };
229       shader.registerUniforms(program, state);
230       return shader;
231    }
232
233    ZString getDefinitions(uint64 _state)
234    {
235       DefaultShaderBits state = _state;
236       ZString defs { allocType = heap, minSize = 5000 };
237       int i;
238
239 #ifdef _DEBUG
240        //PrintLn("Compiling shader for state: ", state);
241 #endif
242
243 #if defined(__EMSCRIPTEN__)
244       defs.concatf("#version 100\n");
245       defs.concatf("#define GLSL_FLOAT_PRECISION   1\n");
246 #else
247       defs.concatf("#version 110\n");
248       defs.concatf("#define GLSL_FLOAT_PRECISION   0\n");
249 #endif
250       defs.concatf("\n#define NUM_LIGHTS %d",               8);
251       defs.concatf("\n#define MODELVIEW %d",                state.modelView          ? 1 : 0);
252       defs.concatf("\n#define PER_VERTEX_COLOR %d",         state.perVertexColor     ? 1 : 0);
253       defs.concatf("\n#define LIGHTING_ON %d",              state.lighting           ? 1 : 0);
254       defs.concatf("\n#define NON_LOCAL_VIEWER %d",         state.nonLocalViewer     ? 1 : 0);
255       defs.concatf("\n#define MAT_TWOSIDED %d",             state.twoSided           ? 1 : 0);
256       defs.concatf("\n#define MAT_SPECULAR %d",             state.specular           ? 1 : 0);
257       defs.concatf("\n#define MAT_SEPARATE_SPECULAR %d",    state.separateSpecular   ? 1 : 0);
258       defs.concatf("\n#define SPECULAR_MAPPING %d",         state.specularMapping    ? 1 : 0);
259       defs.concatf("\n#define ENVIRONMENT_MAPPING %d",      state.environmentMapping ? 1 : 0);
260       defs.concatf("\n#define ENVIRONMENT_REFLECTION %d",   state.reflection         ? 1 : 0);
261       defs.concatf("\n#define ENVIRONMENT_REFRACTION %d",   state.refraction         ? 1 : 0);
262       defs.concatf("\n#define REFLECTION_MAP %d",           state.reflectionMap      ? 1 : 0);
263       defs.concatf("\n#define NORMALS_MAPPING %d",          state.normalsMapping     ? 1 : 0);
264       defs.concatf("\n#define CUBEMAP_ON %d",               state.cubeMap            ? 1 : 0);
265       defs.concatf("\n#define LIGHTING_SPECULAR_BLINN %d",  state.blinnSpecular      ? 1 : 0);
266       defs.concatf("\n#define TEXTURE_ON %d",               state.texturing          ? 1 : 0);
267       defs.concatf("\n#define TEXTURE_MATRIX %d",           state.textureMatrix      ? 1 : 0);
268       defs.concatf("\n#define SWIZZLE_ALPHA %d",            state.swizzle == alpha   ? 1 : 0);
269       defs.concatf("\n#define SWIZZLE_RED %d",              state.swizzle == red     ? 1 : 0);
270       defs.concatf("\n#define FOG_ON %d\n",                 state.fog                ? 1 : 0);
271       defs.concatf("\n#define DEBUGGING %d\n",              state.debugging          ? 1 : 0);
272       for(i = 0; i < 8; i++)
273       {
274          LightMode mode = (LightMode)((state.lightBits & (0x7 << (3*i))) >> (3*i));
275          defs.concatf("\n#define LIGHT%d_ON %d",         i, mode                                 ? 1 : 0);
276          defs.concatf("\n#define LIGHT%d_POSITIONAL %d", i, mode >= pos                          ? 1 : 0);
277          defs.concatf("\n#define LIGHT%d_SPOT %d",       i, mode >= posSpot                      ? 1 : 0);
278          defs.concatf("\n#define LIGHT%d_ATT %d\n",      i, mode == posAtt || mode == posSpotAtt ? 1 : 0);
279       }
280       defs.concatf("\n\n#line 0\n");
281
282 #ifdef _DEBUG
283       //puts((String)defs._string);
284 #endif
285       return defs;
286    }
287
288    void uploadUniforms(CompiledDefaultShader shader)
289    {
290 #if ENABLE_GL_SHADERS
291       DefaultShaderBits state = this.state;
292
293       // Upload Uniforms
294
295 /*
296       if(prjViewModified)
297       {
298          Matrix * mv = &mvMatrix;
299          Matrix * prj = &prjMatrix;
300          Matrix mat;
301          mat.Multiply(mv, prj);
302          {
303             float m[16] =
304             {
305                (float)mat.m[0][0], (float)mat.m[0][1], (float)mat.m[0][2], (float)mat.m[0][3],
306                (float)mat.m[1][0], (float)mat.m[1][1], (float)mat.m[1][2], (float)mat.m[1][3],
307                (float)mat.m[2][0], (float)mat.m[2][1], (float)mat.m[2][2], (float)mat.m[2][3],
308                (float)mat.m[3][0], (float)mat.m[3][1], (float)mat.m[3][2], (float)mat.m[3][3]
309             };
310             float mvz[4] = { (float)mv->m[0][2], (float)mv->m[1][2], (float)mv->m[2][2], (float)mv->m[3][2] };
311             glUniformMatrix4fv(shader.uPrjMatrix, 1, GL_FALSE, m);
312             if(mvModified)
313                glUniform3fv(uMVZ, 1, mvz);
314          }
315       }
316 */
317
318       glUniformMatrix4fv(shader.uPrjMatrix, 1, GL_FALSE, projection);
319
320       if(state.modelView)
321          glUniformMatrix4fv(shader.uMVMatrix, 1, GL_FALSE, modelView);
322
323       if(state.lighting)
324       {
325          // Lights
326          int i;
327          for(i = 0; i < 8; i++)
328          {
329             LightMode mode = (LightMode)((state.lightBits & (0x7 << (3*i))) >> (3*i));
330             if(mode)
331             {
332                if(mode == posSpot || mode == posSpotAtt)
333                {
334                   glUniform3fv(shader.uLightsSpotDir[i], 1, lSpotDir[i]);
335                   glUniform1f(shader.uLightsSpotCutOffCos[i], lCutOffCos[i]);
336                   glUniform1f(shader.uLightsSpotExp[i], lSpotExp[i]);
337                }
338                if(mode == posAtt || mode == posSpotAtt)
339                   glUniform3fv(shader.uLightsAtt[i], 1, lAtt[i]);
340                if(state.specular)
341                   glUniform3fv(shader.uLightsSpecular[i], 1, lSpecular[i]);
342                glUniform3fv(shader.uLightsPos[i], 1, lPosition[i]);
343                glUniform3fv(shader.uLightsDiffuse[i], 1, lDiffuse[i]);
344                glUniform3fv(shader.uLightsAmbient[i], 1, lAmbient[i]);
345             }
346          }
347
348          // Material
349          glUniform4fv(shader.uMatDiffuse,  1, diffuse);
350          glUniform3fv(shader.uMatAmbient,  1, ambient);
351          glUniform3fv(shader.uMatEmissive, 1, emissive);
352          if(state.specular)
353          {
354             glUniform3fv(shader.uMatSpecular, 1, specular);
355             glUniform1f(shader.uMatPower, state.blinnSpecular ? power : power / 4.0f);
356          }
357
358          glUniform1f(shader.uNearPlane, nearPlane);
359          glUniform3fv(shader.uGlobalAmbient, 1, globalAmbient);
360
361          glUniformMatrix3fv(shader.uNormalsMatrix, 1, GL_FALSE, normalsMatrix);
362
363          if(state.normalsMapping)
364             glUniform1i(shader.uBumpTex, 1);
365
366          if(state.specularMapping)
367             glUniform1i(shader.uSpecularTex, 2);
368       }
369       else
370          glUniform4fv(shader.uMatDiffuse, 1, color);
371
372       if(state.environmentMapping)
373       {
374          glUniform1i(shader.uEnvTex, 3);
375          glUniformMatrix3fv(shader.uCubeMapMatrix, 1, GL_FALSE, cubemap_matrix);
376          if(state.reflection)
377             glUniform1f(shader.uMatReflectivity, reflectivity);
378          if(state.refraction)
379             glUniform1f(shader.uRefractionETA, refractionETA);
380          if(state.reflectionMap)
381             glUniform1i(shader.uReflectTex, 4);
382       }
383
384       if(state.texturing || state.cubeMap)
385          glUniform1i(shader.uDiffuseTex, 0);
386       if((state.texturing || state.normalsMapping || state.specularMapping || state.reflectionMap || state.cubeMap) && state.textureMatrix)
387          glUniformMatrix4fv(shader.uTextureMatrix, 1, GL_FALSE, matTexture);
388
389       if(state.fog)
390       {
391          glUniform1f(shader.uFogDensity, fogDensity);
392          glUniform3fv(shader.uFogColor, 1, fogColor);
393       }
394 #endif
395    }
396
397    void setCamera(Camera camera)
398    {
399       double * c = camera.inverseTranspose.array;
400       float m[9] =
401       {
402          (float) c[0], (float) c[1], (float)-c[2],
403          (float)-c[4], (float) c[5], (float) c[6],
404          (float)-c[8], (float) c[9], (float) c[10]
405       };
406       memcpy(cubemap_matrix, m, 9 * sizeof(float));
407       uniformsModified = true;
408    }
409
410    void updateMatrix(MatrixMode mode, Matrix matrix, bool isIdentity)
411    {
412       float m[16] =
413       {
414          (float)matrix.m[0][0], (float)matrix.m[0][1], (float)matrix.m[0][2], (float)matrix.m[0][3],
415          (float)matrix.m[1][0], (float)matrix.m[1][1], (float)matrix.m[1][2], (float)matrix.m[1][3],
416          (float)matrix.m[2][0], (float)matrix.m[2][1], (float)matrix.m[2][2], (float)matrix.m[2][3],
417          (float)matrix.m[3][0], (float)matrix.m[3][1], (float)matrix.m[3][2], (float)matrix.m[3][3]
418       };
419       if(mode == projection)
420       {
421          memcpy(projection, m, 16 * sizeof(float));
422          nearPlane = (float)::nearPlane;
423          uniformsModified = true;
424       }
425       else if(mode == modelView)
426       {
427          Matrix t, inv;
428          double * i = inv.array;
429
430          memcpy(modelView, m, 16 * sizeof(float));
431          ((DefaultShaderBits)state).modelView = !isIdentity;
432
433          //mvModified = true;
434          //prjViewModified = true;
435
436          inv = matrix;
437          inv.Scale(1, -1, 1);
438          t.Transpose(inv);
439          inv.Inverse(t);
440          {
441             float m[9] =
442             {
443                (float)i[0],(float)i[1],(float)i[2],
444                (float)i[4],(float)i[5],(float)i[6],
445                (float)i[8],(float)i[9],(float)i[10]
446             };
447             memcpy(normalsMatrix, m, 9 * sizeof(float));
448          }
449
450          uniformsModified = true;
451       }
452       else if(mode == texture)
453       {
454          memcpy(matTexture, m, 16 * sizeof(float));
455          ((DefaultShaderBits)state).textureMatrix = !isIdentity;
456          if(((DefaultShaderBits)state).texturing || ((DefaultShaderBits)state).normalsMapping || ((DefaultShaderBits)state).specularMapping ||
457             ((DefaultShaderBits)state).reflectionMap || ((DefaultShaderBits)state).cubeMap)
458             uniformsModified = true;
459       }
460    }
461
462    void setGlobalAmbient(float r, float g, float b, float a)
463    {
464       globalAmbient[0] = r, globalAmbient[1] = g, globalAmbient[2] = b;
465       if(((DefaultShaderBits)state).lighting)
466          uniformsModified = true;
467    }
468
469    void setColor(float r, float g, float b, float a)
470    {
471       color[0] = r, color[1] = g, color[2] = b, color[3] = a;
472       uniformsModified = true;
473    }
474
475    void lighting(bool on)
476    {
477       if(((DefaultShaderBits)state).lighting != on)
478       {
479          ((DefaultShaderBits)state).lighting = on;
480          uniformsModified = true;
481          if(!on)
482          {
483             backLightState = state &
484                DefaultShaderBits
485                {
486                   nonLocalViewer = true;
487                   twoSided = true;
488                   specular = true;
489                   separateSpecular = true;
490                   blinnSpecular = true;
491                   lightBits = 0xFFFFFF;
492                };
493             state &= ~backLightState;
494          }
495          else
496             state |= backLightState;
497       }
498    }
499
500    void fog(bool on)
501    {
502       if(fogOn != on)
503       {
504          fogOn = on;
505          ((DefaultShaderBits)state).fog = fogOn && fogDensity;
506          uniformsModified = true;
507       }
508    }
509
510    void setFogDensity(float density)
511    {
512       if(fogDensity != density)
513       {
514          fogDensity = density;
515          ((DefaultShaderBits)state).fog = fogOn && fogDensity;
516          if(fogOn)
517             uniformsModified = true;
518       }
519    }
520
521    void setFogColor(float r, float g, float b)
522    {
523       fogColor[0] = r, fogColor[1] = g, fogColor[2] = b;
524       if(fogOn)
525          uniformsModified = true;
526    }
527
528    void texturing(bool on)
529    {
530       if(((DefaultShaderBits)state).texturing != on)
531       {
532          ((DefaultShaderBits)state).texturing = on;
533          if(!on)
534             state &= ~DefaultShaderBits { swizzle = (SwizzleMode)0x3 };
535          if(!on && !((DefaultShaderBits)state).normalsMapping && !((DefaultShaderBits)state).specularMapping && !((DefaultShaderBits)state).reflectionMap && !((DefaultShaderBits)state).cubeMap)
536             state &= ~DefaultShaderBits { textureMatrix = true };
537          uniformsModified = true;
538       }
539    }
540
541    void debugging(bool on)
542    {
543       if(((DefaultShaderBits)state).debugging != on)
544       {
545          ((DefaultShaderBits)state).debugging = on;
546          uniformsModified = true;
547       }
548    }
549
550    void swizzle(SwizzleMode swizzle)
551    {
552 #ifdef _DEBUG
553       if(swizzle && !((DefaultShaderBits)state).texturing && !((DefaultShaderBits)state).cubeMap)
554          printf("swizzle() with texturing off\n");
555 #endif
556       if(((DefaultShaderBits)state).swizzle != swizzle)
557       {
558          ((DefaultShaderBits)state).swizzle = swizzle;
559          if(((DefaultShaderBits)state).texturing || ((DefaultShaderBits)state).cubeMap)
560             uniformsModified = true;
561       }
562    }
563
564    void setSimpleMaterial(ColorAlpha color, bool twoSided)
565    {
566       float r = color.color.r / 255.0f;
567       float g = color.color.g / 255.0f;
568       float b = color.color.b / 255.0f;
569 #ifdef _DEBUG
570       if(!((DefaultShaderBits)state).lighting)
571          printf("setSimpleMaterial() with lighting off\n");
572 #endif
573       diffuse[0] = r, diffuse[1] = g, diffuse[2] = b, diffuse[3] = color.a / 255.0f;
574       ambient[0] = r, ambient[1] = g, ambient[2] = b;
575       emissive[0] = 0, emissive[1] = 0, emissive[2] = 0;
576       ((DefaultShaderBits)state).perVertexColor = false;
577       ((DefaultShaderBits)state).normalsMapping = false;
578       ((DefaultShaderBits)state).environmentMapping = false;
579       ((DefaultShaderBits)state).reflectionMap = false;
580       ((DefaultShaderBits)state).specularMapping = false;
581       ((DefaultShaderBits)state).reflection = false;
582       ((DefaultShaderBits)state).refraction = false;
583       ((DefaultShaderBits)state).texturing = false;
584       ((DefaultShaderBits)state).cubeMap = false;
585       ((DefaultShaderBits)state).specular = false;
586       ((DefaultShaderBits)state).twoSided = twoSided;
587       uniformsModified = true;
588    }
589
590    void setPerVertexColor(bool perVertexColor)
591    {
592       if(((DefaultShaderBits)state).perVertexColor != perVertexColor)
593       {
594          ((DefaultShaderBits)state).perVertexColor = perVertexColor;
595          uniformsModified = true;
596       }
597    }
598
599    #if !defined(ECERE_NO3D)
600    void setMaterial(Material material, MeshFeatures flags)
601    {
602 #if ENABLE_GL_SHADERS
603       if(material)
604       {
605          ((DefaultShaderBits)state).specular = material.power && (material.specular.r || material.specular.g || material.specular.b);
606          ((DefaultShaderBits)state).perVertexColor = flags.colors;
607          ((DefaultShaderBits)state).separateSpecular = ((DefaultShaderBits)state).specular && material.flags.separateSpecular;
608          ((DefaultShaderBits)state).cubeMap = material && material.flags.cubeMap && material.baseMap;
609          ((DefaultShaderBits)state).twoSided = material.flags.doubleSided && !material.flags.singleSideLight;
610          ((DefaultShaderBits)state).lightBits = material.flags.noLighting ? 0 : lightBits;
611          ((DefaultShaderBits)state).lighting = (!material.flags.noLighting && lightBits) ? true : false;
612          color[0] = 1, color[1] = 1, color[2] = 1, color[3] = material.opacity;
613          diffuse[0]  = material.diffuse.r,  diffuse[1]  = material.diffuse.g,  diffuse[2]  = material.diffuse.b, diffuse[3] = material.opacity;
614          ambient[0]  = material.ambient.r,  ambient[1]  = material.ambient.g,  ambient[2]  = material.ambient.b;
615          specular[0] = material.specular.r, specular[1] = material.specular.g, specular[2] = material.specular.b;
616          emissive[0] = material.emissive.r, emissive[1] = material.emissive.g, emissive[2] = material.emissive.b;
617          power = material.power;
618       }
619       else
620       {
621          ((DefaultShaderBits)state).cubeMap = false;
622          ((DefaultShaderBits)state).perVertexColor = false;
623          ((DefaultShaderBits)state).separateSpecular = false;
624          ((DefaultShaderBits)state).twoSided = false;
625          ((DefaultShaderBits)state).textureMatrix = false;
626       }
627
628       if(material && material.bumpMap && flags.tangents)
629       {
630          glActiveTexture(GL_TEXTURE1);
631          glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData);
632          if(material.flags.tile)
633          {
634             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
635             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
636          }
637          else
638          {
639             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
640             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
641          }
642
643          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, material.bumpMap.mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
644          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
645          glActiveTexture(GL_TEXTURE0);
646          ((DefaultShaderBits)state).normalsMapping = true;
647       }
648       else
649          ((DefaultShaderBits)state).normalsMapping = false;
650
651       if(material && material.envMap && (material.refractiveIndex || material.refractiveIndexContainer || material.reflectivity || material.reflectMap))
652       {
653          CubeMap cube = material.envMap;
654          glActiveTexture(GL_TEXTURE3);
655          glBindTexture(GL_TEXTURE_CUBE_MAP, (GLuint)(uintptr)cube.driverData);
656          glActiveTexture(GL_TEXTURE0);
657          ((DefaultShaderBits)state).environmentMapping = true;
658
659          if(material.refractiveIndex || material.refractiveIndexContainer)
660          {
661             refractionETA =
662                (material.refractiveIndexContainer ? material.refractiveIndexContainer : 1.0) /
663                (material.refractiveIndex ? material.refractiveIndex : 1.0);
664
665             ((DefaultShaderBits)state).refraction = true;
666          }
667
668          if(material.reflectivity || material.reflectMap)
669          {
670             reflectivity = material.reflectivity;
671             if(!reflectivity && material.reflectMap) reflectivity = 1.0;
672
673             if(material.reflectMap)
674             {
675                glActiveTexture(GL_TEXTURE4);
676                glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.reflectMap.driverData);
677                if(material.flags.tile)
678                {
679                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
680                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
681                }
682                else
683                {
684                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
685                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
686                }
687
688                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, material.reflectMap.mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
689                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
690                glActiveTexture(GL_TEXTURE0);
691
692                ((DefaultShaderBits)state).reflectionMap = true;
693             }
694             else
695                ((DefaultShaderBits)state).reflectionMap = false;
696             ((DefaultShaderBits)state).reflection = true;
697          }
698       }
699       else
700       {
701          ((DefaultShaderBits)state).environmentMapping = false;
702          ((DefaultShaderBits)state).refraction = false;
703          ((DefaultShaderBits)state).reflection = false;
704          ((DefaultShaderBits)state).reflectionMap = false;
705       }
706
707       if(material && material.specularMap)
708       {
709          glActiveTexture(GL_TEXTURE2);
710          glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.specularMap.driverData);
711          if(material.flags.tile)
712          {
713             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
714             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
715          }
716          else
717          {
718             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
719             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
720          }
721
722          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, material.specularMap.mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
723          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
724          glActiveTexture(GL_TEXTURE0);
725          ((DefaultShaderBits)state).specularMapping = true;
726       }
727       else
728          ((DefaultShaderBits)state).specularMapping = false;
729
730       uniformsModified = true;
731 #endif
732    }
733
734    void setLight(Display display, uint id, Light light)
735    {
736       int lShift = 3*id;
737       bool lightOn = light && !light.flags.off;
738       LightMode mode = (LightMode)((((DefaultShaderBits)state).lightBits & (0x7 << lShift)) >> lShift);
739
740       if(lightOn && !((DefaultShaderBits)state).lighting)
741          ((DefaultShaderBits)state).lighting = true;
742
743       if(lightOn || (lightOn != (mode != off)))
744          uniformsModified = true;
745
746       if(lightOn)
747       {
748          Object lightObject = light.lightObject;
749          float multiplier = light.multiplier;
750          Matrix m = matrixStack[0][matrixIndex[0]];
751          Vector3D l;
752          m.Scale(::nearPlane, ::nearPlane, ::nearPlane);
753
754          if(!multiplier) multiplier = 1.0f;
755
756          lDiffuse[id][0] = light.diffuse.r * multiplier;
757          lDiffuse[id][1] = light.diffuse.g * multiplier;
758          lDiffuse[id][2] = light.diffuse.b * multiplier;
759
760          lAmbient[id][0] = light.ambient.r * multiplier;
761          lAmbient[id][1] = light.ambient.g * multiplier;
762          lAmbient[id][2] = light.ambient.b * multiplier;
763
764          lSpecular[id][0] = light.specular.r * multiplier;
765          lSpecular[id][1] = light.specular.g * multiplier;
766          lSpecular[id][2] = light.specular.b * multiplier;
767
768          if(lightObject)
769          {
770             // Positional Lights (Including Spot Lights and Omni with flags.spot not set)
771             Matrix * mat = &lightObject.matrix;
772             Vector3D positionVector { mat->m[3][0], mat->m[3][1], mat->m[3][2] };
773             if(display.display3D.camera)
774                positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
775
776             l.MultMatrix(positionVector, m);
777             lPosition[id][0] = (float)l.x, lPosition[id][1] = (float)-l.y, lPosition[id][2] = (float)l.z;
778
779             // Display Light Position
780             /*
781             GLSetupLighting(false);
782             glDisable(GL_DEPTH_TEST);
783             GLColor3f(
784                light.diffuse.r * multiplier,
785                light.diffuse.g * multiplier,
786                light.diffuse.b * multiplier);
787             glPointSize(10);
788             GLBegin(GL_POINTS);
789             GLVertex3dv((double *)&positionVector);
790             GLEnd();
791             glEnable(GL_DEPTH_TEST);
792             GLSetupLighting(true);
793             */
794
795             // Display Target
796             /*
797             if(light.target)
798             {
799                Vector3D positionVector;
800                if(lightObject.flags.root || !lightObject.parent)
801                {
802                   positionVector = light.target.transform.position;
803                   positionVector.Subtract(positionVector, display.camera.cPosition);
804                }
805                else
806                {
807                   positionVector.MultMatrix(light.target.transform.position,
808                      lightObject.light.target.parent.matrix);
809                   positionVector.Subtract(positionVector, display.camera.cPosition);
810                }
811                GLSetupLighting(false);
812                glDisable(GL_DEPTH_TEST);
813                GLColor3f(1,1,0);
814                glPointSize(10);
815                GLBegin(GL_POINTS);
816                GLVertex3dv((double *)&positionVector);
817                GLEnd();
818                glEnable(GL_DEPTH_TEST);
819                GLSetupLighting(false);
820             }
821             */
822
823             if(light.flags.attenuation)
824             {
825                lAtt[id][0] = light.Kc;
826                lAtt[id][1] = light.Kl;
827                lAtt[id][2] = light.Kq;
828             }
829
830             if((light.flags.spot && light.fallOff < 360) || (lightObject && (light.direction.x || light.direction.y || light.direction.z)))
831             {
832                #define MAXLIGHT  0.9
833                // Figure out exponent out of the hot spot
834                float exponent = light.flags.spot ? (float)(log(MAXLIGHT) / log(cos(light.hotSpot / 2))) : 1;
835                Degrees cutOff = light.flags.spot ? light.fallOff/2 : 90;
836                Vector3D l, n;
837                l.MultMatrix(light.direction, m);
838                n.Normalize(l);
839                n.Scale(n, -1);
840
841                lSpotDir[id][0] = (float)n.x, lSpotDir[id][1] = (float)-n.y, lSpotDir[id][2] = (float)n.z;
842                lCutOffCos[id] = (float)cos(Degrees { cutOff });
843                lSpotExp[id] = exponent;
844
845                mode = light.flags.attenuation ? posSpotAtt : posSpot;
846             }
847             else
848                mode = light.flags.attenuation ? posAtt : pos;
849          }
850          else
851          {
852             // Directional Light
853             Vector3D vector { 0,0,-1 };
854             Vector3D direction, v;
855             Matrix mat;
856             mat.RotationQuaternion(light.orientation);
857             direction.MultMatrix(vector, mat);
858             v.Normalize(direction);
859             l.MultMatrix(v, m);
860
861             lPosition[id][0] = (float)l.x, lPosition[id][1] = (float)-l.y, lPosition[id][2] = (float)l.z;
862             mode = dir;
863          }
864       }
865       else
866          mode = off;
867       lightBits = (lightBits & ~(0x7 << lShift)) | (mode << lShift);
868       ((DefaultShaderBits)state).lightBits = lightBits;
869    }
870    #endif
871
872    DefaultShader ::shader() { return defaultShader; }
873 }
874
875 DefaultShader defaultShader { };