1 // Hyperbolic Rogue -- low-level OpenGL routines
2 // Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
3
4 /** \file glhr.cpp
5 * \brief low-level OpenGL routines
6 *
7 * If CAP_SHADER is 0, OpenGL 1.0 is used.
8 * If CAP_SHADER is 1, we are using GLSL shaders.
9 */
10
11 #include "hyper.h"
12 namespace hr {
13
14 EX bool detailed_shader = false;
15
16 EX namespace glhr {
pointtogl(const hyperpoint & t)17 EX glvertex pointtogl(const hyperpoint& t) {
18 glvertex h;
19 h[0] = t[0]; h[1] = t[1]; h[2] = t[2];
20 if(SHDIM == 4) h[3] = (MDIM == 4) ? t[3] : 1;
21 return h;
22 }
23
gltopoint(const glvertex & t)24 EX hyperpoint gltopoint(const glvertex& t) {
25 hyperpoint h;
26 h[0] = t[0]; h[1] = t[1]; h[2] = t[2];
27 if(SHDIM == 4 && MAXMDIM == 4) h[3] = t[3];
28 return h;
29 }
30
31 #if CAP_SHADER
32 EX bool noshaders = false;
33 #endif
34 #if !CAP_SHADER
35 EX bool noshaders = true;
36 #endif
37
38 #if HDR
makevertex(GLfloat x,GLfloat y,GLfloat z)39 inline glvertex makevertex(GLfloat x, GLfloat y, GLfloat z) {
40 #if SHDIM == 3
41 return make_array(x, y, z);
42 #else
43 return make_array<GLfloat>(x, y, z, 1);
44 #endif
45 }
46 #endif
47
48 EX }
49
50 #if CAP_GL
51 #ifndef DEBUG_GL
52 #define DEBUG_GL 0
53 #endif
54
55 // Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
56
glError(const char * GLcall,const char * file,const int line)57 EX void glError(const char* GLcall, const char* file, const int line) {
58 GLenum errCode = glGetError();
59 if(errCode!=GL_NO_ERROR) {
60 println(hlog, format("OPENGL ERROR #%i: in file %s on line %i :: %s",errCode,file, line, GLcall));
61 }
62 }
63
64 #if HDR
65 struct glwrap {
66 const char* msg;
67 int line;
68 void act(const char *when);
glwraphr::glwrap69 glwrap(const char *m, int l) : msg(m), line(l) { act("before"); }
~glwraphr::glwrap70 ~glwrap() { act("after"); }
71 };
72 #define GLWRAP glwrap w##__line(__FILE__, __LINE__)
73 #endif
74
act(const char * when)75 void glwrap::act(const char *when) {
76 GLenum errCode = glGetError();
77 if(errCode!=GL_NO_ERROR) {
78 println(hlog, format("GL error %i %s: %s:%i", errCode, when, msg, line));
79 }
80 }
81
82 #if HDR
83 #if CAP_SHADER && CAP_NOSHADER
84 #define WITHSHADER(x, y) if(glhr::noshaders) y else x
85 #else
86 #if CAP_NOSHADER
87 #define WITHSHADER(x, y) if(1) y
88 #else
89 #define WITHSHADER(x, y) if(1) x
90 #endif
91 #endif
92 #endif
93
94 EX namespace glhr {
95
to_glsl(ld x)96 EX string to_glsl(ld x) {
97 char buf[64];
98 snprintf(buf, 64, "float(%.10e)", x);
99 return buf;
100 }
101
102 #if HDR
103 struct glmatrix {
104 GLfloat a[4][4];
operator []hr::glhr::glmatrix105 GLfloat* operator[] (int i) { return a[i]; }
operator []hr::glhr::glmatrix106 const GLfloat* operator[] (int i) const { return a[i]; }
as_arrayhr::glhr::glmatrix107 GLfloat* as_array() { return a[0]; }
as_arrayhr::glhr::glmatrix108 const GLfloat* as_array() const { return a[0]; }
as_stdarrayhr::glhr::glmatrix109 array<float, 16>& as_stdarray() { return *(array<float, 16>*)this; }
as_stdarrayhr::glhr::glmatrix110 const array<float, 16>& as_stdarray() const { return *(array<float, 16>*)this; }
111 };
112
113 struct colored_vertex {
114 glvertex coords;
115 glvec4 color;
colored_vertexhr::glhr::colored_vertex116 colored_vertex() {}
colored_vertexhr::glhr::colored_vertex117 colored_vertex(GLfloat x, GLfloat y, GLfloat r, GLfloat g, GLfloat b) {
118 coords[0] = x;
119 coords[1] = y;
120 coords[2] = 0;
121 coords[3] = 1;
122 color[0] = r;
123 color[1] = g;
124 color[2] = b;
125 color[3] = 1;
126 }
colored_vertexhr::glhr::colored_vertex127 colored_vertex(hyperpoint h, color_t col) {
128 coords = pointtogl(h);
129 for(int i=0; i<4; i++)
130 color[i] = part(col, 3-i) / 255.0;
131 }
132 };
133
134 struct textured_vertex {
135 glvertex coords;
136 /* texture uses the 'z' for shading with POLY_SHADE_TEXTURE */
137 glvec3 texture;
138 };
139
140 struct ct_vertex {
141 glvertex coords;
142 glvec4 color;
143 glvec2 texture;
ct_vertexhr::glhr::ct_vertex144 ct_vertex() {}
ct_vertexhr::glhr::ct_vertex145 ct_vertex(const hyperpoint& h, ld x1, ld y1, ld col) {
146 coords = pointtogl(h);
147 texture[0] = x1;
148 texture[1] = y1;
149 color[0] = color[1] = color[2] = col;
150 color[3] = 1;
151 }
152 };
153
154 #endif
155
156 bool glew = false;
157
158 bool current_depthtest, current_depthwrite;
159 ld fogbase;
160
161 #if HDR
162 typedef const void *constvoidptr;
163 #endif
164
165 EX constvoidptr current_vertices, buffered_vertices;
166 EX ld current_linewidth;
167
168 GLuint buf_current, buf_buffered;
169
display(const glmatrix & m)170 void display(const glmatrix& m) {
171 for(int i=0; i<4; i++) {
172 for(int j=0; j<4; j++)
173 printf("%10.5f", m[i][j]);
174 printf("\n");
175 }
176 printf("\n");
177 }
178
operator *(glmatrix m1,glmatrix m2)179 EX glmatrix operator * (glmatrix m1, glmatrix m2) {
180 glmatrix res;
181 for(int i=0; i<4; i++)
182 for(int j=0; j<4; j++) {
183 res[i][j] = 0;
184 for(int k=0; k<4; k++)
185 res[i][j] += m1[i][k] * m2[k][j];
186 }
187 return res;
188 }
189
190 EX glmatrix id = {{{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1}}};
191
scale(ld x,ld y,ld z)192 EX glmatrix scale(ld x, ld y, ld z) {
193 glmatrix tmp;
194 for(int i=0; i<4; i++)
195 for(int j=0; j<4; j++)
196 tmp[i][j] = (i==j);
197 tmp[0][0] = x;
198 tmp[1][1] = y;
199 tmp[2][2] = z;
200 return tmp;
201 }
202
tmtogl(const transmatrix & T)203 EX glmatrix tmtogl(const transmatrix& T) {
204 glmatrix tmp;
205 for(int i=0; i<4; i++)
206 for(int j=0; j<4; j++)
207 tmp[i][j] = T[i][j];
208 return tmp;
209 }
210
tmtogl_transpose(const transmatrix & T)211 EX glmatrix tmtogl_transpose(const transmatrix& T) {
212 glmatrix tmp;
213 for(int i=0; i<4; i++)
214 for(int j=0; j<4; j++)
215 tmp[i][j] = T[j][i];
216 return tmp;
217 }
218
tmtogl_transpose3(const transmatrix & T)219 EX glmatrix tmtogl_transpose3(const transmatrix& T) {
220 glmatrix tmp;
221 for(int i=0; i<4; i++)
222 for(int j=0; j<4; j++)
223 tmp[i][j] = T[j][i];
224 if(MDIM == 3)
225 for(int i=0; i<4; i++)
226 for(int j=0; j<4; j++)
227 if(i == 3 || j == 3) tmp[j][i] = 0;
228 return tmp;
229 }
230
ortho(ld x,ld y,ld z)231 EX glmatrix ortho(ld x, ld y, ld z) {
232 return scale(1/x, 1/y, 1/z);
233 }
234
as_glmatrix(GLfloat o[16])235 EX glmatrix& as_glmatrix(GLfloat o[16]) {
236 glmatrix& tmp = (glmatrix&) (o[0]);
237 return tmp;
238 }
239
240 #if HDR
241 constexpr ld vnear_default = 1e-3;
242 constexpr ld vfar_default = 1e9;
243 #endif
244
frustum(ld x,ld y,ld vnear IS (vnear_default),ld vfar IS (vfar_default))245 EX glmatrix frustum(ld x, ld y, ld vnear IS(vnear_default), ld vfar IS(vfar_default)) {
246 GLfloat frustum[16] = {
247 GLfloat(1 / x), 0, 0, 0,
248 0, GLfloat(1 / y), 0, 0,
249 0, 0, GLfloat(-(vnear+vfar)/(vfar-vnear)), -1,
250 0, 0, GLfloat(-2*vnear*vfar/(vfar-vnear)), 0};
251 return as_glmatrix(frustum);
252 }
253
translate(ld x,ld y,ld z)254 EX glmatrix translate(ld x, ld y, ld z) {
255 glmatrix tmp;
256 for(int i=0; i<4; i++)
257 for(int j=0; j<4; j++)
258 tmp[i][j] = (i==j);
259 tmp[3][0] = x;
260 tmp[3][1] = y;
261 tmp[3][2] = z;
262 return tmp;
263 }
264
265 // ** legacy **
266
267 // /* shaders */
268
269 glmatrix projection;
270
new_projection()271 EX void new_projection() {
272 WITHSHADER({
273 projection = id;
274 }, {
275 glMatrixMode(GL_MODELVIEW);
276 glLoadIdentity();
277 glMatrixMode(GL_PROJECTION);
278 glLoadIdentity();
279 return;
280 })
281 }
282
projection_multiply(const glmatrix & m)283 EX void projection_multiply(const glmatrix& m) {
284 WITHSHADER({
285 projection = m * projection;
286 }, {
287 glMatrixMode(GL_PROJECTION);
288 glMultMatrixf(m.as_array());
289 })
290 }
291
292 EX void init();
293
294 #if HDR
295 struct GLprogram {
296 GLuint _program;
297 GLuint vertShader, fragShader;
298
299 GLint uFog, uFogColor, uColor, tTexture, tInvExpTable, tAirMap, uMV, uProjection, uAlpha, uFogBase, uPP;
300 GLint uPRECX, uPRECY, uPRECZ, uIndexSL, uIterations, uLevelLines, uSV, uRadarTransform;
301 GLint uRotSin, uRotCos, uRotNil;
302 GLint uDepthScaling, uCamera, uDepth;
303
304 flagtype shader_flags;
305
306 string _vsh, _fsh;
307
308 GLprogram(string vsh, string fsh);
309
310 ~GLprogram();
311 };
312 #endif
313
314 EX shared_ptr<GLprogram> current_glprogram = nullptr;
315
316 EX bool debug_gl;
317
compileShader(int type,const string & s)318 EX int compileShader(int type, const string& s) {
319 GLint status;
320
321 if(debug_gl) {
322 println(hlog, "===\n");
323 int lineno = 1;
324 string cline = "";
325 for(char c: s+"\n") {
326 if(c == '\n') println(hlog, format("%4d : ", lineno), cline), lineno++, cline = "";
327 else cline += c;
328 }
329 println(hlog, "===");
330 }
331
332 GLint shader = glCreateShader(type);
333 const char *ss = s.c_str();
334 glShaderSource(shader, 1, &ss, NULL);
335 glCompileShader(shader);
336
337 GLint logLength;
338 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
339 if (logLength > 0) {
340 std::vector<char> log(logLength);
341 glGetShaderInfoLog(shader, logLength, &logLength, log.data());
342 string s = log.data();
343 if(logLength > 0)
344 println(hlog, "compiler log (", logLength, "): \n", s);
345 if(debug_gl) {
346 println(hlog, "failed to compile shader -- exit called");
347 exit(1);
348 }
349 }
350
351 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
352 if (status == 0) {
353 glDeleteShader(shader);
354 printf("failed to compile shader\n");
355 println(hlog, s);
356 shader = 0;
357 }
358
359 return shader;
360 }
361
GLprogram(string vsh,string fsh)362 GLprogram::GLprogram(string vsh, string fsh) {
363 if(noshaders || !vid.usingGL) {
364 uFog = -1;
365 uProjection = -1;
366 uPP = -1;
367 uMV = -1;
368 uPRECX = -1;
369 uIterations = -1;
370 uAlpha = -1;
371 uLevelLines = -1;
372 uFogColor = -1;
373 uDepthScaling = uCamera = uDepth = -1;
374
375 uColor = tTexture = tInvExpTable = tAirMap = -1;
376 uFogBase = -1;
377 uPRECX = uPRECY = uPRECZ = uIndexSL = -1;
378 uSV = uRadarTransform = -1;
379
380 uRotCos = -1;
381 uRotSin = -1;
382 uRotNil = -1;
383 return;
384 }
385
386 _vsh = vsh; _fsh = fsh;
387 _program = glCreateProgram();
388
389 add_fixed_functions(vsh);
390 add_fixed_functions(fsh);
391
392 // printf("creating program %d\n", _program);
393 vertShader = compileShader(GL_VERTEX_SHADER, vsh.c_str());
394 fragShader = compileShader(GL_FRAGMENT_SHADER, fsh.c_str());
395
396 // Attach vertex shader to program.
397 glAttachShader(_program, vertShader);
398
399 // Attach fragment shader to program.
400 glAttachShader(_program, fragShader);
401
402 glBindAttribLocation(_program, aPosition, "aPosition");
403 glBindAttribLocation(_program, aTexture, "aTexture");
404 glBindAttribLocation(_program, aColor, "aColor");
405
406 GLint status;
407 glLinkProgram(_program);
408
409 GLint logLength;
410 glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &logLength);
411 if (logLength > 0) {
412 std::vector<char> log(logLength);
413 glGetProgramInfoLog(_program, logLength, &logLength, log.data());
414 if(logLength > 0)
415 printf("linking log (%d): %s\n", logLength, log.data());
416 }
417
418 glGetProgramiv(_program, GL_LINK_STATUS, &status);
419 if (status == 0) {
420 printf("failed to link shader\n");
421 exit(1);
422 }
423
424 uMV = glGetUniformLocation(_program, "uMV");
425 uProjection = glGetUniformLocation(_program, "uP");
426 uPP = glGetUniformLocation(_program, "uPP");
427 uFog = glGetUniformLocation(_program, "uFog");
428 uFogColor = glGetUniformLocation(_program, "uFogColor");
429 uFogBase = glGetUniformLocation(_program, "uFogBase");
430 uAlpha = glGetUniformLocation(_program, "uAlpha");
431 uColor = glGetUniformLocation(_program, "uColor");
432 tTexture = glGetUniformLocation(_program, "tTexture");
433 tInvExpTable = glGetUniformLocation(_program, "tInvExpTable");
434 tAirMap = glGetUniformLocation(_program, "tAirMap");
435
436 uDepth = glGetUniformLocation(_program, "uDepth");
437 uDepthScaling = glGetUniformLocation(_program, "uDepthScaling");
438 uCamera = glGetUniformLocation(_program, "uCamera");
439
440 uPRECX = glGetUniformLocation(_program, "PRECX");
441 uPRECY = glGetUniformLocation(_program, "PRECY");
442 uPRECZ = glGetUniformLocation(_program, "PRECZ");
443 uIndexSL = glGetUniformLocation(_program, "uIndexSL");
444 uSV = glGetUniformLocation(_program, "uSV");
445 uIterations = glGetUniformLocation(_program, "uIterations");
446 uLevelLines = glGetUniformLocation(_program, "uLevelLines");
447 uRadarTransform = glGetUniformLocation(_program, "uRadarTransform");
448
449 uRotCos = glGetUniformLocation(_program, "uRotCos");
450 uRotSin = glGetUniformLocation(_program, "uRotSin");
451 uRotNil = glGetUniformLocation(_program, "uRotNil");
452 }
453
~GLprogram()454 GLprogram::~GLprogram() {
455 glDeleteProgram(_program);
456 if(vertShader) glDeleteShader(vertShader), vertShader = 0;
457 if(fragShader) glDeleteShader(fragShader), fragShader = 0;
458 }
459
set_index_sl(ld x)460 EX void set_index_sl(ld x) {
461 glUniform1f(glhr::current_glprogram->uIndexSL, x);
462 }
463
set_sv(ld x)464 EX void set_sv(ld x) {
465 glUniform1f(glhr::current_glprogram->uSV, x);
466 }
467
set_sl_iterations(int steps)468 EX void set_sl_iterations(int steps) {
469 glUniform1i(glhr::current_glprogram->uIterations, steps);
470 }
471
set_solv_prec(int x,int y,int z)472 EX void set_solv_prec(int x, int y, int z) {
473 glUniform1i(glhr::current_glprogram->tInvExpTable, INVERSE_EXP_BINDING);
474 glUniform1f(glhr::current_glprogram->uPRECX, x);
475 glUniform1f(glhr::current_glprogram->uPRECY, y);
476 glUniform1f(glhr::current_glprogram->uPRECZ, z);
477 }
478
479 EX glmatrix current_matrix, current_modelview, current_projection;
480
operator ==(const glmatrix & m1,const glmatrix & m2)481 bool operator == (const glmatrix& m1, const glmatrix& m2) {
482 for(int i=0; i<4; i++)
483 for(int j=0; j<4; j++)
484 if(m1[i][j] != m2[i][j]) return false;
485 return true;
486 }
487
operator !=(const glmatrix & m1,const glmatrix & m2)488 bool operator != (const glmatrix& m1, const glmatrix& m2) {
489 return !(m1 == m2);
490 }
491
492 EX glmatrix eyeshift;
493 EX bool using_eyeshift;
494
set_modelview(const glmatrix & modelview)495 EX void set_modelview(const glmatrix& modelview) {
496 #if CAP_NOSHADER
497 if(noshaders) {
498 glMatrixMode(GL_MODELVIEW);
499 glLoadMatrixf(modelview.as_array());
500 return;
501 }
502 #endif
503 auto& cur = current_glprogram;
504 if(!cur) return;
505
506 if(detailed_shader) println(hlog, "\n*** ENABLING MODELVIEW:\n", modelview.as_stdarray());
507 if(detailed_shader) println(hlog, "\n*** ENABLING PROJECTION:\n", projection.as_stdarray());
508
509 if(using_eyeshift) {
510 glmatrix mvp = modelview * eyeshift;
511 #if MINIMIZE_GL_CALLS
512 if(mvp == current_matrix) return;
513 current_matrix = mvp;
514 #endif
515 glUniformMatrix4fv(cur->uMV, 1, 0, mvp.as_array());
516 }
517 else if(modelview != current_modelview) {
518 current_modelview = modelview;
519 glUniformMatrix4fv(cur->uMV, 1, 0, modelview.as_array());
520 }
521 if(projection != current_projection) {
522 current_projection = projection;
523 glUniformMatrix4fv(cur->uProjection, 1, 0, projection.as_array());
524 }
525 }
526
id_modelview()527 EX void id_modelview() {
528 #if CAP_NOSHADER
529 if(noshaders) {
530 glMatrixMode(GL_MODELVIEW);
531 glLoadIdentity();
532 return;
533 }
534 #endif
535 set_modelview(id);
536 }
537
538 EX array<GLfloat, 4> acolor(color_t color, ld scale IS(1)) {
539 array<GLfloat, 4> cols;
540 for(int i=0; i<4; i++)
541 cols[i] = part(color, 3-i) / 255.0 * scale;
542 return cols;
543 }
544
545
546 EX void color2(color_t color, ld scale IS(1)) {
547 auto cols = acolor(color, scale);
548
549 WITHSHADER({
550 if(!current_glprogram) return;
551 glUniform4f(current_glprogram->uColor, cols[0], cols[1], cols[2], cols[3]);
552 }, {
553 glColor4f(cols[0], cols[1], cols[2], cols[3]);
554 }
555 )
556 }
557
colorClear(color_t color)558 EX void colorClear(color_t color) {
559 glClearColor(part(color, 3) / 255.0, part(color, 2) / 255.0, part(color, 1) / 255.0, part(color, 0) / 255.0);
560 }
561
full_enable(shared_ptr<GLprogram> p)562 EX void full_enable(shared_ptr<GLprogram> p) {
563 auto& cur = current_glprogram;
564 flagtype oldflags = cur ? cur->shader_flags : 0;
565 if(p == cur) return;
566 if(!vid.usingGL) return;
567 cur = p;
568 GLERR("pre_switch_mode");
569 WITHSHADER({
570 if(detailed_shader) println(hlog, "\n*** ENABLING VERTEX SHADER:\n", cur->_vsh, "\n\nENABLING FRAGMENT SHADER:\n", cur->_fsh, "\n");
571 glUseProgram(cur->_program);
572 GLERR("after_enable");
573 }, {
574 });
575 reset_projection();
576 flagtype newflags = cur->shader_flags;
577 tie(oldflags, newflags) = make_pair(oldflags & ~newflags, newflags & ~oldflags);
578
579 if(newflags & GF_TEXTURE) {
580 GLERR("xsm");
581 WITHSHADER({
582 glEnableVertexAttribArray(aTexture);
583 GLERR("xsm");
584 }, {
585 glEnable(GL_TEXTURE_2D);
586 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
587 GLERR("xsm");
588 })
589 }
590 if(oldflags & GF_TEXTURE) {
591 GLERR("xsm");
592 WITHSHADER({
593 glDisableVertexAttribArray(aTexture);
594 GLERR("xsm");
595 }, {
596 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
597 glDisable(GL_TEXTURE_2D);
598 GLERR("xsm");
599 })
600 }
601 if(newflags & GF_VARCOLOR) {
602 WITHSHADER({
603 GLERR("xsm");
604 glEnableVertexAttribArray(aColor);
605 }, {
606 GLERR("xsm");
607 glEnableClientState(GL_COLOR_ARRAY);
608 GLERR("xsm");
609 })
610 }
611 if(oldflags & GF_VARCOLOR) {
612 WITHSHADER({
613 glDisableVertexAttribArray(aColor);
614 GLERR("xsm");
615 }, {
616 glDisableClientState(GL_COLOR_ARRAY);
617 GLERR("xsm");
618 })
619 }
620 if(newflags & GF_LIGHTFOG) {
621 #ifdef GLES_ONLY
622 #define glFogi glFogx
623 #endif
624 WITHSHADER({}, {
625 /*GLfloat light_ambient[] = { 3.5, 3.5, 3.5, 1.0 };
626 GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
627 GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 };
628
629 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
630 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
631 glLightfv(GL_LIGHT0, GL_POSITION, light_position);
632
633 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
634 GLERR("lighting");
635
636 glEnable(GL_LIGHTING);
637 glEnable(GL_LIGHT0); */
638
639 glEnable(GL_FOG);
640 glFogi(GL_FOG_MODE, GL_LINEAR);
641 glFogf(GL_FOG_START, 0);
642 })
643 }
644 if(oldflags & GF_LIGHTFOG) {
645 WITHSHADER({}, {glDisable(GL_FOG);})
646 }
647 WITHSHADER({
648 glUniform1f(cur->uFogBase, 1); fogbase = 1;
649 }, {})
650 GLERR("after_switch_mode");
651 current_vertices = NULL;
652 WITHSHADER({
653 current_matrix[0][0] = -1e8; // invalid
654 current_modelview[0][0] = -1e8;
655 current_projection[0][0] = -1e8;
656 }, {})
657 id_modelview();
658 current_linewidth = -1;
659 /* if(current_depthwrite) glDepthMask(GL_TRUE);
660 else glDepthMask(GL_FALSE);
661 if(current_depthtest) glEnable(GL_DEPTH_TEST);
662 else glDisable(GL_DEPTH_TEST); */
663 }
664
fog_max(ld fogmax,color_t fogcolor)665 EX void fog_max(ld fogmax, color_t fogcolor) {
666 WITHSHADER({
667 if(current_glprogram->uFog != -1)
668 glUniform1f(current_glprogram->uFog, 1 / fogmax);
669
670 if(current_glprogram->uFogColor != -1) {
671 GLfloat cols[4];
672 for(int i=0; i<4; i++) cols[i] = part(fogcolor, 3-i) / 255.0;
673 glUniform4f(current_glprogram->uFogColor, cols[0], cols[1], cols[2], cols[3]);
674 }
675 }, {
676 glFogf(GL_FOG_END, fogmax);
677 })
678 }
679
set_fogbase(ld _fogbase)680 EX void set_fogbase(ld _fogbase) {
681 WITHSHADER({
682 if(fogbase != _fogbase) {
683 fogbase = _fogbase;
684 glUniform1f(current_glprogram->uFogBase, fogbase);
685 }
686 }, {})
687 }
688
set_ualpha(ld alpha)689 EX void set_ualpha(ld alpha) {
690 WITHSHADER({
691 glUniform1f(current_glprogram->uAlpha, alpha);
692 }, {})
693 }
694
init()695 void init() {
696
697 #if CAP_GLEW
698 if(!glew) {
699 glew = true;
700 printf("Initializing GLEW\n");
701 GLenum err = glewInit();
702 if (GLEW_OK != err) {
703 addMessage("Failed to initialize GLEW");
704 printf("Failed to initialize GLEW\n");
705 return;
706 }
707 printf("CreateProgram = %p\n", reinterpret_cast<void*>(__glewCreateProgram));
708 if(!__glewCreateProgram) noshaders = true;
709 }
710 #endif
711
712 projection = id;
713
714 WITHSHADER(glEnableVertexAttribArray(aPosition);, glEnableClientState(GL_VERTEX_ARRAY);)
715 GLERR("aPosition");
716 // #endif
717
718 glDisableVertexAttribArray(aTexture);
719 glDisableVertexAttribArray(aColor);
720
721 #if CAP_VERTEXBUFFER
722 glGenBuffers(1, &buf_current);
723 glGenBuffers(1, &buf_buffered);
724 current_vertices = NULL;
725 buffered_vertices = (void*) &buffered_vertices; // point to nothing
726 glBindBuffer(GL_ARRAY_BUFFER, buf_current);
727 #endif
728 }
729
730 #if CAP_VERTEXBUFFER
bindbuffer(T & v)731 template<class T> void bindbuffer(T& v) {
732 if(current_vertices == buffered_vertices || current_vertices == nullptr) {
733 glBindBuffer(GL_ARRAY_BUFFER, buf_current);
734 }
735 current_vertices = &v[0];
736 glBufferData(GL_ARRAY_BUFFER, isize(v) * sizeof(v[0]), &v[0], GL_DYNAMIC_DRAW);
737 }
738
739 #define PTR(attrib, q, field) \
740 glVertexAttribPointer(attrib, q, GL_FLOAT, GL_FALSE, sizeof(v[0]), (void*) ((char*) &v[0].field - (char*) &v[0]));
741
bindbuffer_vertex(vector<glvertex> & v)742 EX void bindbuffer_vertex(vector<glvertex>& v) {
743 bindbuffer(v);
744 }
745
746 #endif
747
748 EX void vertices(const vector<glvertex>& v, int vshift IS(0)) {
749 #if CAP_VERTEXBUFFER
750 if(&v[0] == buffered_vertices) {
751 if(&v[0] == current_vertices) return;
752 current_vertices = buffered_vertices;
753 glBindBuffer(GL_ARRAY_BUFFER, buf_buffered);
754 glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), 0);
755 return;
756 }
757 bindbuffer(v);
758 glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), 0);
759 #else
760 if(current_vertices == &v[vshift]) return;
761 current_vertices = &v[vshift];
762 WITHSHADER(
763 glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), &v[vshift]);,
764 glVertexPointer(SHDIM, GL_FLOAT, sizeof(glvertex), &v[0]);
765 )
766 #endif
767 }
768
769 EX void vertices_texture(const vector<glvertex>& v, const vector<glvertex>& t, int vshift IS(0), int tshift IS(0)) {
770 #if CAP_VERTEXBUFFER
771 int q = min(isize(v)-vshift, isize(t)-tshift);
772 vector<textured_vertex> tv(q);
773 for(int i=0; i<q; i++)
774 tv[i].coords = v[vshift+i],
775 tv[i].texture[0] = t[tshift+i][0],
776 tv[i].texture[1] = t[tshift+i][1],
777 tv[i].texture[2] = t[tshift+i][2];
778 prepare(tv);
779 #else
780 vertices(v, vshift);
781 WITHSHADER(
782 glVertexAttribPointer(aTexture, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), &t[tshift]);,
783 glTexCoordPointer(SHDIM, GL_FLOAT, 0, &t[tshift]);
784 )
785 #endif
786 }
787
788 EX void vertices_texture_color(const vector<glvertex>& v, const vector<glvertex>& t, const vector<glvertex>& c, int vshift IS(0), int tshift IS(0)) {
789 #if CAP_VERTEXBUFFER
790 int q = min(isize(v)-vshift, isize(t)-tshift);
791 vector<ct_vertex> tv(q);
792 for(int i=0; i<q; i++) {
793 tv[i].coords = v[vshift+i],
794 tv[i].texture[0] = t[tshift+i][0],
795 tv[i].texture[1] = t[tshift+i][1];
796 for(int i=0; i<SHDIM; i++)
797 tv[i].color[i] = c[tshift+i][i];
798 if(SHDIM == 3) tv[i].color[3] = 1;
799 }
800 prepare(tv);
801 #else
802 vertices(v, vshift);
803 WITHSHADER({
804 glVertexAttribPointer(aTexture, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), &t[tshift]);
805 glVertexAttribPointer(aColor, 4, GL_FLOAT, GL_FALSE, sizeof(glvertex), &c[tshift]);
806 }, {
807 glTexCoordPointer(SHDIM, GL_FLOAT, 0, &t[tshift]);
808 glColorPointer(4, GL_FLOAT, sizeof(colored_vertex), &c[0]);
809 }
810 )
811 #endif
812 }
813
prepare(vector<colored_vertex> & v)814 EX void prepare(vector<colored_vertex>& v) {
815 #if CAP_VERTEXBUFFER
816 bindbuffer(v);
817 PTR(aPosition, SHDIM, coords);
818 PTR(aColor, 4, color);
819 #else
820 if(current_vertices == &v[0]) return;
821 current_vertices = &v[0];
822 WITHSHADER({
823 glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(colored_vertex), &v[0].coords);
824 glVertexAttribPointer(aColor, 4, GL_FLOAT, GL_FALSE, sizeof(colored_vertex), &v[0].color);
825 }, {
826 glVertexPointer(SHDIM, GL_FLOAT, sizeof(colored_vertex), &v[0].coords);
827 glColorPointer(4, GL_FLOAT, sizeof(colored_vertex), &v[0].color);
828 })
829 #endif
830 }
831
prepare(vector<textured_vertex> & v)832 EX void prepare(vector<textured_vertex>& v) {
833 #if CAP_VERTEXBUFFER
834 bindbuffer(v);
835 PTR(aPosition, SHDIM, coords);
836 PTR(aTexture, 3, texture);
837 #else
838 if(current_vertices == &v[0]) return;
839 current_vertices = &v[0];
840 WITHSHADER({
841 glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(textured_vertex), &v[0].coords);
842 glVertexAttribPointer(aTexture, SHDIM, GL_FLOAT, GL_FALSE, sizeof(textured_vertex), &v[0].texture);
843 }, {
844 glVertexPointer(SHDIM, GL_FLOAT, sizeof(textured_vertex), &v[0].coords);
845 glTexCoordPointer(3, GL_FLOAT, sizeof(textured_vertex), &v[0].texture);
846 })
847 #endif
848 // color2(col);
849 }
850
prepare(vector<ct_vertex> & v)851 EX void prepare(vector<ct_vertex>& v) {
852 #if CAP_VERTEXBUFFER
853 bindbuffer(v);
854 PTR(aPosition, SHDIM, coords);
855 PTR(aColor, 4, color);
856 PTR(aTexture, 2, texture);
857 #else
858 if(current_vertices == &v[0]) return;
859 current_vertices = &v[0];
860 WITHSHADER({
861 glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(ct_vertex), &v[0].coords);
862 glVertexAttribPointer(aColor, 4, GL_FLOAT, GL_FALSE, sizeof(ct_vertex), &v[0].color);
863 glVertexAttribPointer(aTexture, 2, GL_FLOAT, GL_FALSE, sizeof(ct_vertex), &v[0].texture);
864 }, {
865 glVertexPointer(SHDIM, GL_FLOAT, sizeof(ct_vertex), &v[0].coords);
866 glTexCoordPointer(2, GL_FLOAT, sizeof(ct_vertex), &v[0].texture);
867 glColorPointer(4, GL_FLOAT, sizeof(ct_vertex), &v[0].color);
868 })
869 #endif
870 }
871
store_in_buffer(vector<glvertex> & v)872 EX void store_in_buffer(vector<glvertex>& v) {
873 #if CAP_VERTEXBUFFER
874 if(!buf_buffered) {
875 printf("no buffer yet\n");
876 return;
877 }
878 printf("storing %d in buffer: %p\n", isize(v), &v[0]);
879 current_vertices = buffered_vertices = &v[0];
880 glBindBuffer(GL_ARRAY_BUFFER, buf_buffered);
881 glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), 0);
882 glBufferData(GL_ARRAY_BUFFER, isize(v) * sizeof(glvertex), &v[0], GL_STATIC_DRAW);
883 printf("Stored.\n");
884 #endif
885 }
886
set_depthtest(bool b)887 EX void set_depthtest(bool b) {
888 if(b != current_depthtest) {
889 current_depthtest = b;
890 if(b) glEnable(GL_DEPTH_TEST);
891 else glDisable(GL_DEPTH_TEST);
892 }
893 }
894
895
set_depthwrite(bool b)896 EX void set_depthwrite(bool b) {
897 if(b != current_depthwrite) { // <- this does not work ask intended for some reason...
898 current_depthwrite = b;
899 if(b) glDepthMask(GL_TRUE);
900 else glDepthMask(GL_FALSE);
901 }
902 }
903
set_linewidth(ld lw)904 EX void set_linewidth(ld lw) {
905 if(lw != current_linewidth) {
906 current_linewidth = lw;
907 glLineWidth(lw);
908 }
909 }
910
switch_to_text(const vector<glvertex> & v,const vector<glvertex> & t)911 EX void switch_to_text(const vector<glvertex>& v, const vector<glvertex>& t) {
912 current_display->next_shader_flags = GF_TEXTURE;
913 dynamicval<eModel> pm(pmodel, mdPixel);
914 if(!svg::in) current_display->set_all(0, 0);
915 vertices_texture(v, t, 0, 0);
916 }
917
be_nontextured()918 EX void be_nontextured() { current_display->next_shader_flags = 0; }
be_textured()919 EX void be_textured() { current_display->next_shader_flags = GF_TEXTURE; }
be_color_textured()920 EX void be_color_textured() { current_display->next_shader_flags = GF_TEXTURE | GF_VARCOLOR; }
921
922 EX }
923
924 EX vector<glhr::textured_vertex> text_vertices;
925
926 EX void texture_vertices(GLfloat *f, int qty, int stride IS(2)) {
927 WITHSHADER(
928 glVertexAttribPointer(aTexture, stride, GL_FLOAT, GL_FALSE, stride * sizeof(GLfloat), f);,
929 glTexCoordPointer(stride, GL_FLOAT, 0, f);
930 )
931 }
932
oldvertices(GLfloat * f,int qty)933 EX void oldvertices(GLfloat *f, int qty) {
934 WITHSHADER(
935 glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, SHDIM * sizeof(GLfloat), f);,
936 glVertexPointer(SHDIM, GL_FLOAT, 0, f);
937 )
938 }
939
940 #endif
941 }
942
943 #define glMatrixMode DISABLED
944 #define glLoadIdentity DISABLED
945 #define glMultMatrixf DISABLED
946 #define glScalef DISABLED
947 #define glTranslatef DISABLED
948 #define glPushMatrix DISABLED
949 #define glPopMatrix DISABLED
950
951