ca968e15e07e036509e76406ac00a21b5dca4915
[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[16];
194
195    float normalsMatrix[16];
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       defs.concatf("#version 100\n");
270       defs.concatf("\n#define NUM_LIGHTS %d",               8);
271       defs.concatf("\n#define MODELVIEW %d",                state.modelView          ? 1 : 0);
272       defs.concatf("\n#define PER_VERTEX_COLOR %d",         state.perVertexColor     ? 1 : 0);
273       defs.concatf("\n#define LIGHTING_ON %d",              state.lighting           ? 1 : 0);
274       defs.concatf("\n#define NON_LOCAL_VIEWER %d",         state.nonLocalViewer     ? 1 : 0);
275       defs.concatf("\n#define MAT_TWOSIDED %d",             state.twoSided           ? 1 : 0);
276       defs.concatf("\n#define MAT_SPECULAR %d",             state.specular           ? 1 : 0);
277       defs.concatf("\n#define MAT_SEPARATE_SPECULAR %d",    state.separateSpecular   ? 1 : 0);
278       defs.concatf("\n#define SPECULAR_MAPPING %d",         state.specularMapping    ? 1 : 0);
279       defs.concatf("\n#define ENVIRONMENT_MAPPING %d",      state.environmentMapping ? 1 : 0);
280       defs.concatf("\n#define ENVIRONMENT_REFLECTION %d",   state.reflection         ? 1 : 0);
281       defs.concatf("\n#define ENVIRONMENT_REFRACTION %d",   state.refraction         ? 1 : 0);
282       defs.concatf("\n#define REFLECTION_MAP %d",           state.reflectionMap      ? 1 : 0);
283       defs.concatf("\n#define NORMALS_MAPPING %d",          state.normalsMapping     ? 1 : 0);
284       defs.concatf("\n#define CUBEMAP_ON %d",               state.cubeMap            ? 1 : 0);
285       defs.concatf("\n#define LIGHTING_SPECULAR_BLINN %d",  state.blinnSpecular      ? 1 : 0);
286       defs.concatf("\n#define TEXTURE_ON %d",               state.texturing          ? 1 : 0);
287       defs.concatf("\n#define TEXTURE_MATRIX %d",           state.textureMatrix      ? 1 : 0);
288       defs.concatf("\n#define SWIZZLE_ALPHA %d",            state.swizzle == alpha   ? 1 : 0);
289       defs.concatf("\n#define SWIZZLE_RED %d",              state.swizzle == red     ? 1 : 0);
290       defs.concatf("\n#define FOG_ON %d\n",                 state.fog                ? 1 : 0);
291       defs.concatf("\n#define DEBUGGING %d\n",              state.debugging          ? 1 : 0);
292       for(i = 0; i < 8; i++)
293       {
294          LightMode mode = (LightMode)((state.lightBits & (0x7 << (3*i))) >> (3*i));
295          defs.concatf("\n#define LIGHT%d_ON %d",         i, mode                                 ? 1 : 0);
296          defs.concatf("\n#define LIGHT%d_POSITIONAL %d", i, mode >= pos                          ? 1 : 0);
297          defs.concatf("\n#define LIGHT%d_SPOT %d",       i, mode >= posSpot                      ? 1 : 0);
298          defs.concatf("\n#define LIGHT%d_ATT %d\n",      i, mode == posAtt || mode == posSpotAtt ? 1 : 0);
299       }
300       defs.concatf("\n\n#line 0\n");
301
302 #ifdef _DEBUG
303         printf((String)defs._string);
304 #endif
305       return defs;
306    }
307
308    void uploadUniforms(CompiledDefaultShader shader)
309    {
310 #if ENABLE_GL_SHADERS
311       DefaultShaderBits state = this.state;
312
313       // Upload Uniforms
314
315 /*
316       if(prjViewModified)
317       {
318          Matrix * mv = &mvMatrix;
319          Matrix * prj = &prjMatrix;
320          Matrix mat;
321          mat.Multiply(mv, prj);
322          {
323             float m[16] =
324             {
325                (float)mat.m[0][0], (float)mat.m[0][1], (float)mat.m[0][2], (float)mat.m[0][3],
326                (float)mat.m[1][0], (float)mat.m[1][1], (float)mat.m[1][2], (float)mat.m[1][3],
327                (float)mat.m[2][0], (float)mat.m[2][1], (float)mat.m[2][2], (float)mat.m[2][3],
328                (float)mat.m[3][0], (float)mat.m[3][1], (float)mat.m[3][2], (float)mat.m[3][3]
329             };
330             float mvz[4] = { (float)mv->m[0][2], (float)mv->m[1][2], (float)mv->m[2][2], (float)mv->m[3][2] };
331             glUniformMatrix4fv(shader.uPrjMatrix, 1, GL_FALSE, m);
332             if(mvModified)
333                glUniform3fv(uMVZ, 1, mvz);
334          }
335       }
336 */
337
338       glUniformMatrix4fv(shader.uPrjMatrix, 1, GL_FALSE, projection);
339
340       if(state.modelView)
341          glUniformMatrix4fv(shader.uMVMatrix, 1, GL_FALSE, modelView);
342
343       if(state.lighting)
344       {
345          // Lights
346          int i;
347          for(i = 0; i < 8; i++)
348          {
349             LightMode mode = (LightMode)((state.lightBits & (0x7 << (3*i))) >> (3*i));
350             if(mode)
351             {
352                if(mode == posSpot || mode == posSpotAtt)
353                {
354                   glUniform3fv(shader.uLightsSpotDir[i], 1, lSpotDir[i]);
355                   glUniform1f(shader.uLightsSpotCutOffCos[i], lCutOffCos[i]);
356                   glUniform1f(shader.uLightsSpotExp[i], lSpotExp[i]);
357                }
358                if(mode == posAtt || mode == posSpotAtt)
359                   glUniform3fv(shader.uLightsAtt[i], 1, lAtt[i]);
360                if(state.specular)
361                   glUniform3fv(shader.uLightsSpecular[i], 1, lSpecular[i]);
362                glUniform3fv(shader.uLightsPos[i], 1, lPosition[i]);
363                glUniform3fv(shader.uLightsDiffuse[i], 1, lDiffuse[i]);
364                glUniform3fv(shader.uLightsAmbient[i], 1, lAmbient[i]);
365             }
366          }
367
368          // Material
369          glUniform4fv(shader.uMatDiffuse,  1, diffuse);
370          glUniform3fv(shader.uMatAmbient,  1, ambient);
371          glUniform3fv(shader.uMatEmissive, 1, emissive);
372          if(state.specular)
373          {
374             glUniform3fv(shader.uMatSpecular, 1, specular);
375             glUniform1f(shader.uMatPower, state.blinnSpecular ? power : power / 4.0f);
376          }
377
378          glUniform1f(shader.uNearPlane, nearPlane);
379          glUniform3fv(shader.uGlobalAmbient, 1, globalAmbient);
380
381          glUniformMatrix4fv(shader.uNormalsMatrix, 1, GL_FALSE, normalsMatrix);
382
383          if(state.normalsMapping)
384             glUniform1i(shader.uBumpTex, 1);
385
386          if(state.specularMapping)
387             glUniform1i(shader.uSpecularTex, 2);
388       }
389       else
390          glUniform4fv(shader.uMatDiffuse, 1, color);
391
392       if(state.environmentMapping)
393       {
394          glUniform1i(shader.uEnvTex, 3);
395          glUniformMatrix4fv(shader.uCubeMapMatrix, 1, GL_FALSE, cubemap_matrix);
396          if(state.reflection)
397             glUniform1f(shader.uMatReflectivity, reflectivity);
398          if(state.refraction)
399             glUniform1f(shader.uRefractionETA, refractionETA);
400          if(state.reflectionMap)
401             glUniform1i(shader.uReflectTex, 4);
402       }
403
404       if(state.texturing || state.cubeMap)
405          glUniform1i(shader.uDiffuseTex, 0);
406       if((state.texturing || state.normalsMapping || state.specularMapping || state.reflectionMap || state.cubeMap) && state.textureMatrix)
407          glUniformMatrix4fv(shader.uTextureMatrix, 1, GL_FALSE, matTexture);
408
409       if(state.fog)
410       {
411          glUniform1f(shader.uFogDensity, fogDensity);
412          glUniform3fv(shader.uFogColor, 1, fogColor);
413       }
414 #endif
415    }
416
417    void setCamera(Camera camera)
418    {
419       double * c = camera.inverseTranspose.array;
420       float m[16] =
421       {
422          (float) c[0], (float) c[1], (float)-c[2], 0,
423          (float)-c[4], (float) c[5], (float) c[6], 0,
424          (float)-c[8], (float) c[9], (float) c[10], 0,
425          0, 0, 0, 1
426       };
427       memcpy(cubemap_matrix, m, 16 * sizeof(float));
428       uniformsModified = true;
429    }
430
431    void updateMatrix(MatrixMode mode, Matrix matrix, bool isIdentity)
432    {
433       float m[16] =
434       {
435          (float)matrix.m[0][0], (float)matrix.m[0][1], (float)matrix.m[0][2], (float)matrix.m[0][3],
436          (float)matrix.m[1][0], (float)matrix.m[1][1], (float)matrix.m[1][2], (float)matrix.m[1][3],
437          (float)matrix.m[2][0], (float)matrix.m[2][1], (float)matrix.m[2][2], (float)matrix.m[2][3],
438          (float)matrix.m[3][0], (float)matrix.m[3][1], (float)matrix.m[3][2], (float)matrix.m[3][3]
439       };
440       if(mode == projection)
441       {
442          memcpy(projection, m, 16 * sizeof(float));
443          nearPlane = (float)::nearPlane;
444          uniformsModified = true;
445       }
446       else if(mode == modelView)
447       {
448          Matrix t, inv;
449          double * i = inv.array;
450
451          memcpy(modelView, m, 16 * sizeof(float));
452          ((DefaultShaderBits)state).modelView = !isIdentity;
453
454          //mvModified = true;
455          //prjViewModified = true;
456
457          inv = matrix;
458          inv.Scale(1, -1, 1);
459          t.Transpose(inv);
460          inv.Inverse(t);
461          {
462             float m[16] =
463             {
464                (float)i[0],(float)i[1],(float)i[2],(float)i[3],
465                (float)i[4],(float)i[5],(float)i[6],(float)i[7],
466                (float)i[8],(float)i[9],(float)i[10],(float)i[11],
467                (float)i[12],(float)i[13],(float)i[14],(float)i[15]
468             };
469             memcpy(normalsMatrix, m, 16 * sizeof(float));
470          }
471
472          uniformsModified = true;
473       }
474       else if(mode == texture)
475       {
476          memcpy(matTexture, m, 16 * sizeof(float));
477          ((DefaultShaderBits)state).textureMatrix = !isIdentity;
478          if(((DefaultShaderBits)state).texturing || ((DefaultShaderBits)state).normalsMapping || ((DefaultShaderBits)state).specularMapping ||
479             ((DefaultShaderBits)state).reflectionMap || ((DefaultShaderBits)state).cubeMap)
480             uniformsModified = true;
481       }
482    }
483
484    void setGlobalAmbient(float r, float g, float b, float a)
485    {
486       globalAmbient[0] = r, globalAmbient[1] = g, globalAmbient[2] = b;
487       if(((DefaultShaderBits)state).lighting)
488          uniformsModified = true;
489    }
490
491    void setColor(float r, float g, float b, float a)
492    {
493       color[0] = r, color[1] = g, color[2] = b, color[3] = a;
494       uniformsModified = true;
495    }
496
497    void lighting(bool on)
498    {
499       if(((DefaultShaderBits)state).lighting != on)
500       {
501          ((DefaultShaderBits)state).lighting = on;
502          uniformsModified = true;
503          if(!on)
504             state &= ~DefaultShaderBits
505             {
506                nonLocalViewer = true;
507                twoSided = true;
508                specular = true;
509                separateSpecular = true;
510                blinnSpecular = true;
511                lightBits = 0xFFFFFF;
512             };
513          else
514             state |= DefaultShaderBits { separateSpecular = true };
515       }
516    }
517
518    void fog(bool on)
519    {
520       if(fogOn != on)
521       {
522          fogOn = on;
523          ((DefaultShaderBits)state).fog = fogOn && fogDensity;
524          uniformsModified = true;
525       }
526    }
527
528    void setFogDensity(float density)
529    {
530       if(fogDensity != density)
531       {
532          fogDensity = density;
533          ((DefaultShaderBits)state).fog = fogOn && fogDensity;
534          if(fogOn)
535             uniformsModified = true;
536       }
537    }
538
539    void setFogColor(float r, float g, float b)
540    {
541       fogColor[0] = r, fogColor[1] = g, fogColor[2] = b;
542       if(fogOn)
543          uniformsModified = true;
544    }
545
546    void texturing(bool on)
547    {
548       if(((DefaultShaderBits)state).texturing != on)
549       {
550          ((DefaultShaderBits)state).texturing = on;
551          if(!on)
552             state &= ~DefaultShaderBits { swizzle = (SwizzleMode)0x3 };
553          if(!on && !((DefaultShaderBits)state).normalsMapping && !((DefaultShaderBits)state).specularMapping && !((DefaultShaderBits)state).reflectionMap && !((DefaultShaderBits)state).cubeMap)
554             state &= ~DefaultShaderBits { textureMatrix = true };
555          uniformsModified = true;
556       }
557    }
558
559    void debugging(bool on)
560    {
561       if(((DefaultShaderBits)state).debugging != on)
562       {
563          ((DefaultShaderBits)state).debugging = on;
564          uniformsModified = true;
565       }
566    }
567
568    void swizzle(SwizzleMode swizzle)
569    {
570 #ifdef _DEBUG
571       if(swizzle && !((DefaultShaderBits)state).texturing && !((DefaultShaderBits)state).cubeMap)
572          printf("swizzle() with texturing off\n");
573 #endif
574       if(((DefaultShaderBits)state).swizzle != swizzle)
575       {
576          ((DefaultShaderBits)state).swizzle = swizzle;
577          if(((DefaultShaderBits)state).texturing || ((DefaultShaderBits)state).cubeMap)
578             uniformsModified = true;
579       }
580    }
581
582    void setSimpleMaterial(ColorAlpha color, bool twoSided)
583    {
584       float r = color.color.r / 255.0f;
585       float g = color.color.g / 255.0f;
586       float b = color.color.b / 255.0f;
587 #ifdef _DEBUG
588       if(!((DefaultShaderBits)state).lighting)
589          printf("setSimpleMaterial() with lighting off\n");
590 #endif
591       diffuse[0] = r, diffuse[1] = g, diffuse[2] = b, diffuse[3] = color.a / 255.0f;
592       ambient[0] = r, ambient[1] = g, ambient[2] = b;
593       emissive[0] = 0, emissive[1] = 0, emissive[2] = 0;
594       ((DefaultShaderBits)state).perVertexColor = false;
595       ((DefaultShaderBits)state).normalsMapping = false;
596       ((DefaultShaderBits)state).environmentMapping = false;
597       ((DefaultShaderBits)state).reflectionMap = false;
598       ((DefaultShaderBits)state).specularMapping = false;
599       ((DefaultShaderBits)state).reflection = false;
600       ((DefaultShaderBits)state).refraction = false;
601       ((DefaultShaderBits)state).texturing = false;
602       ((DefaultShaderBits)state).cubeMap = false;
603       ((DefaultShaderBits)state).specular = false;
604       ((DefaultShaderBits)state).twoSided = twoSided;
605       uniformsModified = true;
606    }
607
608    void setPerVertexColor(bool perVertexColor)
609    {
610       if(((DefaultShaderBits)state).perVertexColor != perVertexColor)
611       {
612          ((DefaultShaderBits)state).perVertexColor = perVertexColor;
613          uniformsModified = true;
614       }
615    }
616
617    #if !defined(ECERE_NO3D)
618    void setMaterial(Material material, MeshFeatures flags)
619    {
620 #if ENABLE_GL_SHADERS
621       if(material)
622       {
623          ((DefaultShaderBits)state).specular = material.power && (material.specular.r || material.specular.g || material.specular.b);
624          ((DefaultShaderBits)state).perVertexColor = flags.colors;
625          ((DefaultShaderBits)state).separateSpecular = ((DefaultShaderBits)state).specular && material.flags.separateSpecular;
626          ((DefaultShaderBits)state).cubeMap = material && material.flags.cubeMap && material.baseMap;
627          ((DefaultShaderBits)state).twoSided = material.flags.doubleSided && !material.flags.singleSideLight;
628          ((DefaultShaderBits)state).lightBits = material.flags.noLighting ? 0 : lightBits;
629          ((DefaultShaderBits)state).lighting = (!material.flags.noLighting && lightBits) ? true : false;
630          diffuse[0]  = material.diffuse.r,  diffuse[1]  = material.diffuse.g,  diffuse[2]  = material.diffuse.b, diffuse[3] = material.opacity;
631          ambient[0]  = material.ambient.r,  ambient[1]  = material.ambient.g,  ambient[2]  = material.ambient.b;
632          specular[0] = material.specular.r, specular[1] = material.specular.g, specular[2] = material.specular.b;
633          emissive[0] = material.emissive.r, emissive[1] = material.emissive.g, emissive[2] = material.emissive.b;
634          power = material.power;
635       }
636       else
637       {
638          ((DefaultShaderBits)state).cubeMap = false;
639          ((DefaultShaderBits)state).perVertexColor = false;
640          ((DefaultShaderBits)state).separateSpecular = false;
641          ((DefaultShaderBits)state).twoSided = false;
642          ((DefaultShaderBits)state).textureMatrix = false;
643       }
644
645       if(material && material.bumpMap && flags.tangents)
646       {
647          glActiveTexture(GL_TEXTURE1);
648          glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData);
649          if(material.flags.tile)
650          {
651             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
652             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
653          }
654          else
655          {
656             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
657             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
658          }
659
660          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, material.bumpMap.mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
661          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
662          glActiveTexture(GL_TEXTURE0);
663          ((DefaultShaderBits)state).normalsMapping = true;
664       }
665       else
666          ((DefaultShaderBits)state).normalsMapping = false;
667
668       if(material && material.envMap && (material.refractiveIndex || material.refractiveIndexContainer || material.reflectivity || material.reflectMap))
669       {
670          CubeMap cube = material.envMap;
671          glActiveTexture(GL_TEXTURE3);
672          glBindTexture(GL_TEXTURE_CUBE_MAP, (GLuint)(uintptr)cube.driverData);
673          glActiveTexture(GL_TEXTURE0);
674          ((DefaultShaderBits)state).environmentMapping = true;
675
676          if(material.refractiveIndex || material.refractiveIndexContainer)
677          {
678             refractionETA =
679                (material.refractiveIndexContainer ? material.refractiveIndexContainer : 1.0) /
680                (material.refractiveIndex ? material.refractiveIndex : 1.0);
681
682             ((DefaultShaderBits)state).refraction = true;
683          }
684
685          if(material.reflectivity || material.reflectMap)
686          {
687             reflectivity = material.reflectivity;
688             if(!reflectivity && material.reflectMap) reflectivity = 1.0;
689
690             if(material.reflectMap)
691             {
692                glActiveTexture(GL_TEXTURE4);
693                glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.reflectMap.driverData);
694                if(material.flags.tile)
695                {
696                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
697                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
698                }
699                else
700                {
701                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
702                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
703                }
704
705                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, material.reflectMap.mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
706                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
707                glActiveTexture(GL_TEXTURE0);
708
709                ((DefaultShaderBits)state).reflectionMap = true;
710             }
711             else
712                ((DefaultShaderBits)state).reflectionMap = false;
713             ((DefaultShaderBits)state).reflection = true;
714          }
715       }
716       else
717       {
718          ((DefaultShaderBits)state).environmentMapping = false;
719          ((DefaultShaderBits)state).refraction = false;
720          ((DefaultShaderBits)state).reflection = false;
721          ((DefaultShaderBits)state).reflectionMap = false;
722       }
723
724       if(material && material.specularMap)
725       {
726          glActiveTexture(GL_TEXTURE2);
727          glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.specularMap.driverData);
728          if(material.flags.tile)
729          {
730             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
731             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
732          }
733          else
734          {
735             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
736             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
737          }
738
739          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, material.specularMap.mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
740          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
741          glActiveTexture(GL_TEXTURE0);
742          ((DefaultShaderBits)state).specularMapping = true;
743       }
744       else
745          ((DefaultShaderBits)state).specularMapping = false;
746
747       uniformsModified = true;
748 #endif
749    }
750
751    void setLight(Display display, uint id, Light light)
752    {
753       int lShift = 3*id;
754       bool lightOn = light && !light.flags.off;
755       LightMode mode = (LightMode)((((DefaultShaderBits)state).lightBits & (0x7 << lShift)) >> lShift);
756
757       if(lightOn && !((DefaultShaderBits)state).lighting)
758          ((DefaultShaderBits)state).lighting = true;
759
760       if(lightOn || (lightOn != (mode != off)))
761          uniformsModified = true;
762
763       if(lightOn)
764       {
765          Object lightObject = light.lightObject;
766          float multiplier = light.multiplier;
767          Matrix m = matrixStack[0][matrixIndex[0]];
768          Vector3D l;
769          m.Scale(::nearPlane, ::nearPlane, ::nearPlane);
770
771          if(!multiplier) multiplier = 1.0f;
772
773          lDiffuse[id][0] = light.diffuse.r * multiplier;
774          lDiffuse[id][1] = light.diffuse.g * multiplier;
775          lDiffuse[id][2] = light.diffuse.b * multiplier;
776
777          lAmbient[id][0] = light.ambient.r * multiplier;
778          lAmbient[id][1] = light.ambient.g * multiplier;
779          lAmbient[id][2] = light.ambient.b * multiplier;
780
781          lSpecular[id][0] = light.specular.r * multiplier;
782          lSpecular[id][1] = light.specular.g * multiplier;
783          lSpecular[id][2] = light.specular.b * multiplier;
784
785          if(lightObject)
786          {
787             // Positional Lights (Including Spot Lights and Omni with flags.spot not set)
788             Matrix * mat = &lightObject.matrix;
789             Vector3D positionVector { mat->m[3][0], mat->m[3][1], mat->m[3][2] };
790             if(display.display3D.camera)
791                positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
792
793             l.MultMatrix(positionVector, m);
794             lPosition[id][0] = (float)l.x, lPosition[id][1] = (float)-l.y, lPosition[id][2] = (float)l.z;
795
796             // Display Light Position
797             /*
798             GLSetupLighting(false);
799             glDisable(GL_DEPTH_TEST);
800             GLColor3f(
801                light.diffuse.r * multiplier,
802                light.diffuse.g * multiplier,
803                light.diffuse.b * multiplier);
804             glPointSize(10);
805             GLBegin(GL_POINTS);
806             GLVertex3dv((double *)&positionVector);
807             GLEnd();
808             glEnable(GL_DEPTH_TEST);
809             GLSetupLighting(true);
810             */
811
812             // Display Target
813             /*
814             if(light.target)
815             {
816                Vector3D positionVector;
817                if(lightObject.flags.root || !lightObject.parent)
818                {
819                   positionVector = light.target.transform.position;
820                   positionVector.Subtract(positionVector, display.camera.cPosition);
821                }
822                else
823                {
824                   positionVector.MultMatrix(light.target.transform.position,
825                      lightObject.light.target.parent.matrix);
826                   positionVector.Subtract(positionVector, display.camera.cPosition);
827                }
828                GLSetupLighting(false);
829                glDisable(GL_DEPTH_TEST);
830                GLColor3f(1,1,0);
831                glPointSize(10);
832                GLBegin(GL_POINTS);
833                GLVertex3dv((double *)&positionVector);
834                GLEnd();
835                glEnable(GL_DEPTH_TEST);
836                GLSetupLighting(false);
837             }
838             */
839
840             if(light.flags.attenuation)
841             {
842                lAtt[id][0] = light.Kc;
843                lAtt[id][1] = light.Kl;
844                lAtt[id][2] = light.Kq;
845             }
846
847             if((light.flags.spot && light.fallOff < 360) || (lightObject && (light.direction.x || light.direction.y || light.direction.z)))
848             {
849                #define MAXLIGHT  0.9
850                // Figure out exponent out of the hot spot
851                float exponent = light.flags.spot ? (float)(log(MAXLIGHT) / log(cos(light.hotSpot / 2))) : 1;
852                Degrees cutOff = light.flags.spot ? light.fallOff/2 : 90;
853                Vector3D l, n;
854                l.MultMatrix(light.direction, m);
855                n.Normalize(l);
856                n.Scale(n, -1);
857
858                lSpotDir[id][0] = (float)n.x, lSpotDir[id][1] = (float)-n.y, lSpotDir[id][2] = (float)n.z;
859                lCutOffCos[id] = (float)cos(Degrees { cutOff });
860                lSpotExp[id] = exponent;
861
862                mode = light.flags.attenuation ? posSpotAtt : posSpot;
863             }
864             else
865                mode = light.flags.attenuation ? posAtt : pos;
866          }
867          else
868          {
869             // Directional Light
870             Vector3D vector { 0,0,-1 };
871             Vector3D direction, v;
872             Matrix mat;
873             mat.RotationQuaternion(light.orientation);
874             direction.MultMatrix(vector, mat);
875             v.Normalize(direction);
876             l.MultMatrix(v, m);
877
878             lPosition[id][0] = (float)l.x, lPosition[id][1] = (float)-l.y, lPosition[id][2] = (float)l.z;
879             mode = dir;
880          }
881       }
882       else
883          mode = off;
884       lightBits = (lightBits & ~(0x7 << lShift)) | (mode << lShift);
885       ((DefaultShaderBits)state).lightBits = lightBits;
886    }
887    #endif
888
889    DefaultShader ::shader() { return defaultShader; }
890 }
891
892 DefaultShader defaultShader { };