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