ecere/gfx/OpenGL: (OpenGL ES) Support for glColor4f() with lighting enabled
[sdk] / ecere / src / gfx / drivers / gl3 / immediate.ec
1 // OpenGL Immediate Mode Transition Kit
2
3 #ifndef _GLES
4  #define SHADERS
5 #endif
6
7 #if defined(__ANDROID__) || defined(__ODROID__)
8    #include <GLES/gl.h>
9 #elif defined(__EMSCRIPTEN__)
10    #include <GLES2/gl2.h>
11 #else
12 #  if defined(SHADERS)
13 #     include "gl_core_3_3.h"
14 #  else
15 #     include "gl_compat_4_4.h"
16 #  endif
17 #endif
18
19 import "glab"
20 import "shading"
21
22 #ifdef SHADERS
23
24 #undef glEnableClientState
25 #undef glDisableClientState
26 #undef GL_VERTEX_ARRAY
27 #undef GL_NORMAL_ARRAY
28 #undef GL_TEXTURE_COORD_ARRAY
29 #undef GL_COLOR_ARRAY
30 #undef glVertexPointer
31 #undef glTexCoordPointer
32
33 #define glEnableClientState      glEnableVertexAttribArray
34 #define glDisableClientState     glDisableVertexAttribArray
35 #define GL_VERTEX_ARRAY          GLBufferContents::vertex
36 #define GL_NORMAL_ARRAY          GLBufferContents::normal
37 #define GL_TEXTURE_COORD_ARRAY   GLBufferContents::texCoord
38 #define GL_COLOR_ARRAY           GLBufferContents::color
39
40 #define glVertexPointer(n, t, s, p)    glVertexAttribPointer(GLBufferContents::vertex,   n, t, GL_FALSE, s, p)
41 #define glTexCoordPointer(n, t, s, p)  glVertexAttribPointer(GLBufferContents::texCoord, n, t, GL_FALSE, s, p)
42
43 #endif
44
45 public enum GLIMTKMode
46 {
47    unset          =     -1,
48    points         = 0x0000,
49    lines          = 0x0001,
50    lineLoop       = 0x0002,
51    lineStrip      = 0x0003,
52    triangles      = 0x0004,
53    triangleStrip  = 0x0005,
54    triangleFan    = 0x0006,
55    quads          = 0x0007,
56    quadStrip      = 0x0008,
57    polygon        = 0x0009
58 };
59
60 static int beginCount;
61 static int vertexCount;
62 static int normalCount;
63 static float *vertexPointer;
64 static float *normalPointer;
65 static GLIMTKMode beginMode = unset;
66 static uint beginBufferSize, normalBufferSize;
67 static int numVertexCoords = 2;
68 static bool vertexColorValues = false;
69 static int vertexStride = 4;
70 static int vertexOffset = 2;
71
72 public void glimtkRecti(int a, int b, int c, int d)
73 {
74    glimtkBegin(quads);
75    glimtkVertex2i(a, b);
76    glimtkVertex2i(a, d);
77    glimtkVertex2i(c, d);
78    glimtkVertex2i(c, b);
79    glimtkEnd();
80 }
81
82 public void glimtkBegin(GLIMTKMode mode)
83 {
84    beginMode = mode;
85    beginCount = 0;
86    vertexCount = 0;
87    vertexColorValues = false;
88    vertexOffset = 2;
89    vertexStride = 4;
90    numVertexCoords = 2;
91
92    if(!vertexPointer)
93    {
94       normalBufferSize = beginBufferSize = 1024;  // default number of vertices
95       vertexPointer = new float[beginBufferSize * vertexStride];
96       normalPointer = new float[normalBufferSize * 3];
97    }
98 }
99
100 public void glimtkTexCoord2f(float x, float y)
101 {
102    int count = vertexCount;
103
104    if(vertexCount + numVertexCoords > beginBufferSize)
105    {
106       beginBufferSize = beginBufferSize + beginBufferSize/2;
107       vertexPointer = renew vertexPointer float[beginBufferSize * vertexStride];
108    }
109
110    vertexPointer[count*vertexStride  ] = x;
111    vertexPointer[count*vertexStride+1] = y;
112    count++;
113
114    if(beginMode == quads && ((beginCount % 4) == 3))
115    {
116       vertexPointer[count*vertexStride  ] = vertexPointer[(count-4)*vertexStride];
117       vertexPointer[count*vertexStride+1] = vertexPointer[(count-4)*vertexStride+1];
118       count++;
119       vertexPointer[count*vertexStride  ] = vertexPointer[(count-3)*vertexStride];
120       vertexPointer[count*vertexStride+1] = vertexPointer[(count-3)*vertexStride+1];
121       count++;
122    }
123 }
124 public void glimtkTexCoord2i(int x, int y)       { glimtkTexCoord2f((float)x, (float)y); }
125 public void glimtkTexCoord2d(double x, double y) { glimtkTexCoord2f((float)x, (float)y); }
126 public void glimtkTexCoord2fv(float * a)         { glimtkTexCoord2f(a[0], a[1]); }
127
128 public void glimtkVertex2f(float x, float y)
129 {
130    numVertexCoords = 2;
131    vertexStride = vertexOffset + numVertexCoords;
132
133    if(vertexCount + 4 > beginBufferSize)
134    {
135       beginBufferSize = beginBufferSize + beginBufferSize/2;
136       vertexPointer = renew vertexPointer float[beginBufferSize * vertexStride];
137    }
138
139    vertexPointer[vertexCount*vertexStride+vertexOffset] = x;
140    vertexPointer[vertexCount*vertexStride+vertexOffset + 1] = y;
141    vertexCount++;
142
143    if(beginMode == quads && ((beginCount % 4) == 3))
144    {
145       vertexPointer[vertexCount*vertexStride+vertexOffset] = vertexPointer[(vertexCount-4)*vertexStride+vertexOffset];
146       vertexPointer[vertexCount*vertexStride+vertexOffset + 1] = vertexPointer[(vertexCount-4)*vertexStride+vertexOffset + 1];
147       vertexCount++;
148       vertexPointer[vertexCount*vertexStride+vertexOffset] = vertexPointer[(vertexCount-3)*vertexStride+vertexOffset];
149       vertexPointer[vertexCount*vertexStride+vertexOffset + 1] = vertexPointer[(vertexCount-3)*vertexStride+vertexOffset + 1];
150       vertexCount++;
151    }
152    beginCount++;
153 }
154 public void glimtkVertex2i(int x, int y)         { glimtkVertex2f((float)x, (float)y); }
155 public void glimtkVertex2d(double x, double y)   { glimtkVertex2f((float)x, (float)y); }
156
157 GLAB streamVecAB, streamNorAB;
158
159 public void glimtkEnd(void)
160 {
161    GLIMTKMode mode = beginMode;
162    if(mode == quads)        mode = triangles;
163    else if(mode == polygon) mode = triangleFan;
164
165    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
166
167    if(vboAvailable)
168    {
169       streamVecAB.upload(vertexStride * sizeof(float) * vertexCount, vertexPointer);
170       streamVecAB.use(texCoord, 2, GL_FLOAT, vertexStride * sizeof(float), 0);
171    }
172    else
173       noAB.use(texCoord, 2, GL_FLOAT, vertexStride * sizeof(float), vertexPointer);
174
175    if(vertexColorValues)
176    {
177       glEnableClientState(GL_COLOR_ARRAY);
178       if(vboAvailable)
179          streamVecAB.use(color, 4, GL_FLOAT, vertexStride * sizeof(float), (void *)(2 * sizeof(float)));
180       else
181          noAB.use(color, 4, GL_FLOAT, vertexStride * sizeof(float), vertexPointer + 2);
182
183 #ifdef SHADERS
184       shader_setPerVertexColor(true);
185 #endif
186    }
187
188    if(vboAvailable)
189       streamVecAB.use(vertex, numVertexCoords, GL_FLOAT, vertexStride * sizeof(float), (void *)(vertexOffset * sizeof(float)));
190    else
191       noAB.use(vertex, numVertexCoords, GL_FLOAT, vertexStride * sizeof(float), vertexPointer + vertexOffset);
192
193    if(normalCount && normalCount == vertexCount)
194    {
195       glEnableClientState(GL_NORMAL_ARRAY);
196       if(vboAvailable)
197       {
198          streamNorAB.upload(3*sizeof(float) * vertexCount, normalPointer);
199          streamNorAB.use(normal, 3, GL_FLOAT, 3*sizeof(float), 0);
200       }
201       else
202          noAB.use(normal, 3, GL_FLOAT, 3*sizeof(float),normalPointer);
203    }
204
205    glDrawArrays(mode, 0, vertexCount);
206
207    if(normalCount)
208       glDisableClientState(GL_NORMAL_ARRAY);
209    if(vertexColorValues)
210    {
211       glDisableClientState(GL_COLOR_ARRAY);
212
213 #ifdef SHADERS
214       shader_setPerVertexColor(false);
215 #endif
216
217    }
218    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
219
220    normalCount = 0;
221    vertexColorValues = false;
222    numVertexCoords = 2;
223    beginMode = unset;
224 }
225
226 // Vertex Pointer
227 static float *floatVPBuffer = null;
228 static short *shortVPBuffer = null;
229 static unsigned int shortVPSize = 0, floatVPSize = 0;
230
231 // Buffer Data
232 static unsigned short *shortBDBuffer = null;
233 static unsigned int shortBDSize = 0;
234
235 public void glimtkVertexPointeri(int numCoords, int stride, int *pointer, int numVertices)
236 {
237    if(pointer)
238    {
239       int i;
240       if(numVertices*numCoords > shortVPSize)
241       {
242          shortVPSize = numVertices*numCoords;
243          shortVPBuffer = renew shortVPBuffer short[shortVPSize];
244       }
245       for(i = 0; i < numVertices*numCoords; i++)
246          shortVPBuffer[i] = (short)pointer[i];
247
248       glVertexPointer(numCoords, GL_SHORT, stride, shortVPBuffer);
249    }
250    else
251       glVertexPointer(numCoords, GL_SHORT, stride, 0);
252 }
253
254 public void glimtkVertexPointerd(int numCoords, int stride, double *pointer, int numVertices)
255 {
256    if(pointer)
257    {
258       int i;
259       if(numVertices*numCoords > floatVPSize)
260       {
261          floatVPSize = numVertices*numCoords;
262          floatVPBuffer = renew floatVPBuffer float[floatVPSize];
263       }
264       for(i = 0; i < numVertices*numCoords; i++)
265          floatVPBuffer[i] = (float)pointer[i];
266       glVertexPointer(numCoords, GL_FLOAT, stride, floatVPBuffer);
267    }
268    else
269       glVertexPointer(numCoords, GL_FLOAT, stride, 0);
270 }
271
272 public void glimtkTexReuseIntVP(int numCoords)
273 {
274    glTexCoordPointer(numCoords, GL_SHORT, 0, floatVPBuffer);
275 }
276
277 public void glimtkTexReuseDoubleVP(int numCoords)
278 {
279    glTexCoordPointer(numCoords, GL_FLOAT, 0, floatVPBuffer);
280 }
281
282 public void glimtkColor4f(float r, float g, float b, float a)
283 {
284    if(beginMode != unset)
285    {
286       int count = vertexCount;
287
288       vertexColorValues = true;
289       vertexOffset = 6;
290       vertexStride = vertexOffset + numVertexCoords;
291
292       if(vertexCount + vertexStride > beginBufferSize)
293       {
294          beginBufferSize = beginBufferSize + beginBufferSize/2;
295          vertexPointer = renew vertexPointer float[beginBufferSize * vertexStride];
296       }
297
298       vertexPointer[count*vertexStride + 2] = r;
299       vertexPointer[count*vertexStride + 3] = g;
300       vertexPointer[count*vertexStride + 4] = b;
301       vertexPointer[count*vertexStride + 5] = a;
302       count++;
303
304       if(beginMode == quads && ((beginCount % 4) == 3))
305       {
306          vertexPointer[count*vertexStride + 2] = vertexPointer[(count-4) * vertexStride + 2];
307          vertexPointer[count*vertexStride + 3] = vertexPointer[(count-4) * vertexStride + 3];
308          vertexPointer[count*vertexStride + 4] = vertexPointer[(count-4) * vertexStride + 4];
309          vertexPointer[count*vertexStride + 5] = vertexPointer[(count-4) * vertexStride + 5];
310          count++;
311          vertexPointer[count*vertexStride + 2] = vertexPointer[(count-3) * vertexStride + 2];
312          vertexPointer[count*vertexStride + 3] = vertexPointer[(count-3) * vertexStride + 3];
313          vertexPointer[count*vertexStride + 4] = vertexPointer[(count-3) * vertexStride + 4];
314          vertexPointer[count*vertexStride + 5] = vertexPointer[(count-3) * vertexStride + 5];
315          count++;
316       }
317    }
318    else
319    {
320 #ifdef SHADERS
321       shader_color(r, g, b, a);
322 #else
323       glColor4f(r, g, b, a);
324       if(lightingEnabled)
325       {
326          float color[4] = { r, g, b, a };
327          glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
328          glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
329       }
330 #endif
331    }
332 }
333
334 public void glimtkColor3f( float r, float g, float b )
335 {
336    glimtkColor4f(r, g, b, 1.0f);
337 }
338
339 public void glimtkColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
340 {
341    glimtkColor4f(r/255.0f, g/255.0f, b/255.0f, a/255.0f);
342 }
343
344 public void glimtkColor4fv(float * a)
345 {
346    glimtkColor4f(a[0], a[1], a[2], a[3]);
347 }
348
349 public void glimtkBufferDatad(int target, int size, void * data, int usage)
350 {
351    int numElems = size/sizeof(double);
352    double * dblPtr = (double *)data;
353    int i;
354    if (numElems > floatVPSize)
355    {
356       floatVPSize = numElems;
357       floatVPBuffer = renew floatVPBuffer float[floatVPSize];
358    }
359    for (i=0; i< numElems; i++)
360       floatVPBuffer[i] = (float)dblPtr[i];
361
362    glBufferData(target, numElems*sizeof(float), floatVPBuffer, usage);
363 }
364
365 public void glimtkBufferDatai(int target, int size, void * data, int usage)
366 {
367    int numElems = size/sizeof(unsigned int);
368    unsigned int * pointer = (unsigned int *)data;
369    int i;
370    if (numElems > shortBDSize)
371    {
372       shortBDSize = numElems;
373       shortBDBuffer = renew shortBDBuffer uint16[shortBDSize];
374    }
375    for (i=0; i< numElems; i++)
376       shortBDBuffer[i] = (unsigned short)pointer[i];
377
378    glBufferData(target, numElems*sizeof(unsigned short), shortBDBuffer, usage);
379 }
380
381 public void glimtkVertex3f( float x, float y, float z )
382 {
383    numVertexCoords = 3;
384    vertexStride = vertexOffset + numVertexCoords;
385
386    if(vertexCount + vertexStride > beginBufferSize)
387    {
388       beginBufferSize = beginBufferSize + beginBufferSize/2;
389       vertexPointer = renew vertexPointer float[beginBufferSize * vertexStride];
390    }
391
392    vertexPointer[vertexCount*vertexStride+vertexOffset] = x;
393    vertexPointer[vertexCount*vertexStride+vertexOffset+1] = y;
394    vertexPointer[vertexCount*vertexStride+vertexOffset+2] = z;
395    vertexCount++;
396
397    if(beginMode == quads && ((beginCount % 4) == 3))
398    {
399       vertexPointer[vertexCount*vertexStride+vertexOffset] = vertexPointer[(vertexCount-4)*vertexStride+vertexOffset];
400       vertexPointer[vertexCount*vertexStride+vertexOffset+1] = vertexPointer[(vertexCount-4)*vertexStride+vertexOffset+1];
401       vertexPointer[vertexCount*vertexStride+vertexOffset+2] = vertexPointer[(vertexCount-4)*vertexStride+vertexOffset+2];
402       vertexCount++;
403       vertexPointer[vertexCount*vertexStride+vertexOffset] = vertexPointer[(vertexCount-3)*vertexStride+vertexOffset];
404       vertexPointer[vertexCount*vertexStride+vertexOffset+1] = vertexPointer[(vertexCount-3)*vertexStride+vertexOffset+1];
405       vertexPointer[vertexCount*vertexStride+vertexOffset+2] = vertexPointer[(vertexCount-3)*vertexStride+vertexOffset+2];
406       vertexCount++;
407    }
408    beginCount++;
409 }
410
411 public void glimtkVertex3d( double x, double y, double z )  { glimtkVertex3f((float)x, (float)y, (float)z); }
412 public void glimtkVertex3fv( float* coords )                { glimtkVertex3f(coords[0], coords[1], coords[2]); }
413 public void glimtkVertex3dv( double* coords )               { glimtkVertex3f((float)coords[0], (float)coords[1], (float)coords[2]); }
414
415 public void glimtkNormal3f(float x, float y, float z)
416 {
417    normalCount = vertexCount;
418    if(vertexCount + 4 > normalBufferSize)
419    {
420       normalBufferSize = normalBufferSize + normalBufferSize/2;
421       normalPointer = renew normalPointer float[normalBufferSize * 2];
422    }
423
424    normalPointer[normalCount*3+0] = x;
425    normalPointer[normalCount*3+1] = y;
426    normalPointer[normalCount*3+2] = z;
427    normalCount++;
428
429    if(beginMode == quads && ((beginCount % 4) == 3))
430    {
431       normalPointer[normalCount*3+0] = normalPointer[(normalCount-4)*3+0];
432       normalPointer[normalCount*3+1] = normalPointer[(normalCount-4)*3+1];
433       normalPointer[normalCount*3+2] = normalPointer[(normalCount-4)*3+2];
434       normalCount++;
435       normalPointer[normalCount*3+0] = normalPointer[(normalCount-3)*3+0];
436       normalPointer[normalCount*3+1] = normalPointer[(normalCount-3)*3+1];
437       normalPointer[normalCount*3+2] = normalPointer[(normalCount-3)*3+2];
438       normalCount++;
439    }
440 }
441 public void glimtkNormal3fd(double x, double y, double z)         { glimtkNormal3f((float)x, (float)y, (float)z); }
442 public void glimtkNormal3fv(float * coords)                       { glimtkNormal3f(coords[0], coords[1], coords[2]); }
443
444 public void glimtkTerminate()
445 {
446    delete vertexPointer;
447    delete normalPointer;
448    beginBufferSize = 0;
449
450    delete floatVPBuffer;
451    shortVPSize = 0;
452
453    delete shortVPBuffer;
454    floatVPSize = 0;
455
456    delete shortBDBuffer;
457    shortBDSize = 0;
458 }