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