e87a0389fbf1637a58d7b44c54b74836e313c832
[sdk] / ecere / src / gfx / drivers / gl3 / shading.ec
1 import "Display"
2 import "matrixStack"
3 import "glab"
4
5 #ifndef _GLES
6  #define SHADERS
7 #endif
8
9 #if defined(SHADERS)
10
11 #if defined(__ANDROID__) || defined(__ODROID__)
12    #include <GLES/gl.h>
13
14    #define GL_INT    0x1404
15    #define GL_DOUBLE 0x140A
16 #elif defined(__EMSCRIPTEN__)
17    #include <GLES2/gl2.h>
18 #else
19 #  if defined(SHADERS)
20 #     include "gl_core_3_3.h"
21 #  else
22 #     include "gl_compat_4_4.h"
23 #  endif
24 #endif
25
26 int shadingProgram;
27
28 // Uniforms
29 int uPrjMatrix;
30 int uMVMatrix;
31 int uTextureMatrix;
32 int uColor;
33 int uTexturingOn;
34 int uLightingOn;
35 int uFogOn;
36 int uFogDensity;
37 int uFogColor;
38 int uGlobalAmbient;
39 int uLightsOn[8];
40 int uLightsPos[8];
41 int uLightsDiffuse[8];
42 int uLightsAmbient[8];
43 int uLightsSpecular[8];
44 int uPerVertexColor;
45 int uMatDiffuse;
46 int uMatAmbient;
47 int uMatSpecular;
48 int uMatEmissive;
49 int uMatPower;
50 int uMatOpacity;
51 int uMatTwoSided;
52
53 void shader_LoadMatrixf(MatrixMode mode, float * m)
54 {
55    if(mode == texture)
56       glUniformMatrix4fv(uTextureMatrix, 1, GL_FALSE, m);
57    else if(mode == projection)
58       glUniformMatrix4fv(uPrjMatrix, 1, GL_FALSE, m);
59    else
60       glUniformMatrix4fv(uMVMatrix, 1, GL_FALSE, m);
61 }
62
63 void shader_setGlobalAmbient(float r, float g, float b, float a)
64 {
65    glUniform3f(uGlobalAmbient, r, g, b);
66 }
67
68 void shader_color(float r, float g, float b, float a)
69 {
70    glUniform4f(uColor, r, g, b, a);
71 }
72
73 void shader_lighting(bool on)
74 {
75    glUniform1i(uLightingOn, on);
76 }
77
78 void shader_fog(bool on)
79 {
80    glUniform1i(uFogOn, on);
81 }
82
83 void shader_fogDensity(float density)
84 {
85    glUniform1f(uFogDensity, density);
86 }
87
88 void shader_fogColor(float r, float g, float b)
89 {
90    glUniform3f(uFogColor, r, g, b);
91 }
92
93 void shader_texturing(bool on)
94 {
95    glUniform1i(uTexturingOn, on);
96 }
97
98 #if !defined(ECERE_NO3D)
99 public void shader_setMaterial(Material material, bool perVertexColor)
100 {
101    glUniform1i(uPerVertexColor, perVertexColor);
102    glUniform1i(uMatTwoSided, !material.flags.singleSideLight);
103    glUniform3f(uMatDiffuse, material.diffuse.r, material.diffuse.g, material.diffuse.b);
104    glUniform3f(uMatAmbient, material.ambient.r, material.ambient.g, material.ambient.b);
105    glUniform3f(uMatSpecular, material.specular.r, material.specular.g, material.specular.b);
106    glUniform3f(uMatEmissive, material.emissive.r, material.emissive.g, material.emissive.b);
107    glUniform1f(uMatPower, material.power);
108    glUniform1f(uMatOpacity, material.opacity);
109 }
110 #endif
111
112 public void shader_setSimpleMaterial(ColorAlpha color)
113 {
114    float opacity = color.a / 255.0f;
115    float r = color.color.r / 255.0f;
116    float g = color.color.g / 255.0f;
117    float b = color.color.b / 255.0f;
118    glUniform1i(uPerVertexColor, 0);
119    glUniform1i(uMatTwoSided, 0);
120    glUniform3f(uMatDiffuse, r, g, b);
121    glUniform3f(uMatAmbient, r, g, b);
122    glUniform3f(uMatSpecular, r, g, b);
123    glUniform3f(uMatEmissive, 0, 0, 0);
124    glUniform1f(uMatPower, 0);
125    glUniform1f(uMatOpacity, opacity);
126 }
127
128 public void shader_setPerVertexColor(bool perVertexColor)
129 {
130    glUniform1i(uPerVertexColor, perVertexColor);
131 }
132
133 #if !defined(ECERE_NO3D)
134 void shader_setLight(Display display, uint id, Light light)
135 {
136    if(light != null)
137    {
138       Object lightObject = light.lightObject;
139       float multiplier = light.multiplier;
140
141       glUniform1i(uLightsOn[id], 1);
142
143       if(!multiplier) multiplier = 1.0f;
144
145       glUniform3f(uLightsDiffuse[id],
146          light.diffuse.r * multiplier,
147          light.diffuse.g * multiplier,
148          light.diffuse.b * multiplier);
149
150       glUniform3f(uLightsAmbient[id],
151          light.ambient.r * multiplier,
152          light.ambient.g * multiplier,
153          light.ambient.b * multiplier);
154
155       glUniform3f(uLightsSpecular[id],
156          light.specular.r * multiplier,
157          light.specular.g * multiplier,
158          light.specular.b * multiplier);
159
160       if(lightObject)
161       {
162          /*
163          Vector3D positionVector;
164          if(light.flags.spot)
165          {
166             if(lightObject.flags.root || !lightObject.parent)
167             {
168                positionVector = lightObject.transform.position;
169                positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
170             }
171             else
172             {
173                positionVector.MultMatrix(lightObject.transform.position, lightObject.parent.matrix);
174                if(display.display3D.camera)
175                   positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
176             }
177             position[3] = 1;
178          }
179          else
180          {
181             if(!light.direction.x && !light.direction.y && !light.direction.z)
182             {
183                Vector3Df vector { 0,0,-1 };
184                Matrix mat;
185                mat.RotationQuaternion(light.orientation);
186                positionVector.MultMatrixf(vector, mat);
187             }
188             else
189             {
190                positionVector = light.direction;
191                position[3] = 1;
192             }
193          }
194
195          position[0] = (float)positionVector.x;
196          position[1] = (float)positionVector.y;
197          position[2] = (float)positionVector.z;
198
199          glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
200
201          if(light.flags.attenuation)
202          {
203             glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc);
204             glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl);
205             glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq);
206          }
207
208          if(light.flags.spot)
209          {
210             float exponent = 0;
211             #define MAXLIGHT  0.9
212             float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 };
213             // Figure out exponent out of the hot spot
214             exponent = (float)(log(MAXLIGHT) / log(cos((light.hotSpot / 2))));
215
216             glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction);
217             glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)(light.fallOff / 2));
218             glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent);
219          }
220          */
221       }
222       else
223       {
224          Vector3Df l;
225          Vector3Df vector { 0,0,-1 };
226          Vector3Df direction;
227          Matrix mat;
228          Matrix m = matrixStack[0][matrixIndex[0]];
229          m.Scale(nearPlane, nearPlane, nearPlane);
230
231          mat.RotationQuaternion(light.orientation);
232          direction.MultMatrix(vector, mat);
233
234          vector.MultMatrix(direction, m);
235          l.Normalize(vector);
236
237          glUniform4f(uLightsPos[id], l.x, l.y, l.z, 0);
238       }
239    }
240    else
241       glUniform1i(uLightsOn[id], 0);
242 }
243 #endif
244
245 bool loadShaders(const String vertexShaderFile, const String fragmentShaderFile)
246 {
247    bool result = false;
248    File vf = FileOpen(vertexShaderFile, read);
249    File ff = FileOpen(fragmentShaderFile, read);
250    // printf("loading shaders %s and %s (%p and %p)\n", vertexShaderFile, fragmentShaderFile, vf, ff);
251    if(vf && ff)
252    {
253       static char compileLog[65536];
254       #define BUFFER_SIZE  4096
255       int bufferLen = BUFFER_SIZE;
256       char * buffer = new byte[BUFFER_SIZE];
257       int vsLen = 0, fsLen = 0;
258       char * vsSource = null;
259       char * psSource = null;
260       if(vf)
261       {
262          while(!vf.eof)
263          {
264             int count = vf.Read(buffer + vsLen, 1, BUFFER_SIZE);
265             vsLen += count;
266             if(count == BUFFER_SIZE && bufferLen < vsLen + BUFFER_SIZE)
267             {
268                bufferLen = vsLen + BUFFER_SIZE;
269                buffer = renew buffer byte[bufferLen];
270             }
271          }
272          vsSource = new byte[vsLen+1];
273          memcpy(vsSource, buffer, vsLen);
274          vsSource[vsLen] = 0;
275          delete vf;
276       }
277       if(ff)
278       {
279          while(!ff.eof)
280          {
281             int count = ff.Read(buffer + fsLen, 1, BUFFER_SIZE);
282             fsLen += count;
283             if(count == BUFFER_SIZE && bufferLen < fsLen + BUFFER_SIZE)
284             {
285                bufferLen = fsLen + BUFFER_SIZE;
286                buffer = renew buffer byte[bufferLen];
287             }
288          }
289          psSource = new byte[fsLen+1];
290          memcpy(psSource, buffer, fsLen);
291          psSource[fsLen] = 0;
292          delete ff;
293       }
294       delete buffer;
295
296       printf("We've got OpenGL Version %s\n\n", (char *)glGetString(GL_VERSION));
297       printf("We've got Shading Language Version %s\n\n", (char *)glGetString(GL_SHADING_LANGUAGE_VERSION));
298
299       {
300          int program = glCreateProgram();
301          int vShader = glCreateShader(GL_VERTEX_SHADER);
302          int fShader = glCreateShader(GL_FRAGMENT_SHADER);
303          const char * vptr[1] = { vsSource };
304          const char * fptr[1] = { psSource };
305          int i;
306
307          glShaderSource(vShader, 1, vptr, &vsLen);
308          glShaderSource(fShader, 1, fptr, &fsLen);
309          delete vsSource;
310          delete psSource;
311
312          glCompileShader(vShader);
313          glGetShaderInfoLog(vShader, sizeof(compileLog), null, compileLog);
314          puts("Vertex Shader Compile Log:");
315          puts("--------------------------");
316          puts(compileLog[0] ? compileLog : "Success.");
317
318          glCompileShader(fShader);
319          glGetShaderInfoLog(fShader, sizeof(compileLog), null, compileLog);
320          puts("");
321          puts("");
322          puts("Fragment Shader Compile Log:");
323          puts("--------------------------");
324          puts(compileLog[0] ? compileLog : "Success.");
325
326          glAttachShader(program, vShader);
327          glAttachShader(program, fShader);
328
329          glBindAttribLocation(program, GLBufferContents::vertex, "vertex");
330          glBindAttribLocation(program, GLBufferContents::texCoord, "texCoord");
331          glBindAttribLocation(program, GLBufferContents::color, "color");
332          glBindAttribLocation(program, GLBufferContents::normal, "normal");
333          // glBindFragDataLocation(program, 0, "fragColor");
334
335          glLinkProgram(program);
336          glValidateProgram(program);
337
338          glGetProgramInfoLog(program, sizeof(compileLog), null, compileLog);
339          puts("");
340          puts("");
341          puts("Shader Program Log:");
342          puts("--------------------------");
343          puts(compileLog[0] ? compileLog : "Success.");
344
345          uPrjMatrix     = glGetUniformLocation(program, "projection_matrix");
346          uMVMatrix      = glGetUniformLocation(program, "modelview_matrix");
347          uTextureMatrix = glGetUniformLocation(program, "texture_matrix");
348          uColor         = glGetUniformLocation(program, "current_color");
349          uTexturingOn   = glGetUniformLocation(program, "texturingOn");
350          uLightingOn    = glGetUniformLocation(program, "lightingOn");
351          uFogOn         = glGetUniformLocation(program, "fogOn");
352          uFogDensity    = glGetUniformLocation(program, "fogDensity");
353          uFogColor      = glGetUniformLocation(program, "fogColor");
354          uGlobalAmbient = glGetUniformLocation(program, "globalAmbient");
355          uPerVertexColor  = glGetUniformLocation(program, "perVertexColor");
356          uMatDiffuse       = glGetUniformLocation(program, "matDiffuse");
357          uMatAmbient       = glGetUniformLocation(program, "matAmbient");
358          uMatSpecular      = glGetUniformLocation(program, "matSpecular");
359          uMatEmissive      = glGetUniformLocation(program, "matEmissive");
360          uMatPower         = glGetUniformLocation(program, "matPower");
361          uMatOpacity       = glGetUniformLocation(program, "matOpacity");
362          uMatTwoSided      = glGetUniformLocation(program, "matTwoSided");
363
364          for(i = 0; i < 8; i++)
365          {
366             char name[100];
367
368             sprintf(name, "lightsOn[%d]", i);
369             uLightsOn [i] = glGetUniformLocation(program, name);
370
371             sprintf(name, "lightsPos[%d]", i);
372             uLightsPos[i] = glGetUniformLocation(program, name);
373
374             sprintf(name, "lightsDiffuse[%d]", i);
375             uLightsDiffuse[i] = glGetUniformLocation(program, name);
376
377             sprintf(name, "lightsAmbient[%d]", i);
378             uLightsAmbient[i] = glGetUniformLocation(program, name);
379
380             sprintf(name, "lightsSpecular[%d]", i);
381             uLightsSpecular[i] = glGetUniformLocation(program, name);
382          }
383
384          shadingProgram = program;
385
386          glUseProgram(shadingProgram);
387
388          // Initialize uniforms to defaults
389          glmsMatrixMode(texture);
390          glmsLoadIdentity();
391          glmsMatrixMode(projection);
392          glmsLoadIdentity();
393          glmsMatrixMode(modelView);
394          glmsLoadIdentity();
395          shader_color(1.0, 1.0, 1.0, 1.0);
396
397          result = true;
398       }
399    }
400    delete vf;
401    delete ff;
402
403    return result;
404 }
405
406 #endif