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