1 // ---------------------------------------------------------------------------
2 //
3 // @file TwOpenGLCore.cpp
4 // @author Philippe Decaudin
5 // @license This file is part of the AntTweakBar library.
6 // For conditions of distribution and use, see License.txt
7 //
8 // ---------------------------------------------------------------------------
9
10 /*
11 #pragma warning GL3 //// used for development
12 #define GL3_PROTOTYPES 1 ////
13 #include <GL3/gl3.h> ////
14 #define ANT_OGL_HEADER_INCLUDED ////
15 */
16
17 #if defined ANT_OSX
18 # include <OpenGL/gl3.h>
19 # define ANT_OGL_HEADER_INCLUDED
20 #endif
21 #include "TwPrecomp.h"
22 #include "LoadOGLCore.h"
23 #include "TwOpenGLCore.h"
24 #include "TwMgr.h"
25
26 using namespace std;
27
28 extern const char *g_ErrCantLoadOGL;
29 extern const char *g_ErrCantUnloadOGL;
30
31 // ---------------------------------------------------------------------------
32
33 #ifdef _DEBUG
CheckGLCoreError(const char * file,int line,const char * func)34 static void CheckGLCoreError(const char *file, int line, const char *func)
35 {
36 int err=0;
37 char msg[256];
38 while( (err=_glGetError())!=0 )
39 {
40 sprintf(msg, "%s(%d) : [%s] GL_CORE_ERROR=0x%x\n", file, line, func, err);
41 #ifdef ANT_WINDOWS
42 OutputDebugString(msg);
43 #endif
44 fprintf(stderr, msg);
45 }
46 }
47 # ifdef __FUNCTION__
48 # define CHECK_GL_ERROR CheckGLCoreError(__FILE__, __LINE__, __FUNCTION__)
49 # else
50 # define CHECK_GL_ERROR CheckGLCoreError(__FILE__, __LINE__, "")
51 # endif
52 #else
53 # define CHECK_GL_ERROR ((void)(0))
54 #endif
55
56 // ---------------------------------------------------------------------------
57
BindFont(const CTexFont * _Font)58 static GLuint BindFont(const CTexFont *_Font)
59 {
60 GLuint TexID = 0;
61 _glGenTextures(1, &TexID);
62 _glBindTexture(GL_TEXTURE_2D, TexID);
63 _glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
64 _glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
65 _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
66 _glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
67 _glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
68 _glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
69 _glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
70 _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
71 _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
72 _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
73 _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
74 _glBindTexture(GL_TEXTURE_2D, 0);
75
76 return TexID;
77 }
78
UnbindFont(GLuint _FontTexID)79 static void UnbindFont(GLuint _FontTexID)
80 {
81 if( _FontTexID>0 )
82 _glDeleteTextures(1, &_FontTexID);
83 }
84
85 // ---------------------------------------------------------------------------
86
CompileShader(GLuint shader)87 static GLuint CompileShader(GLuint shader)
88 {
89 _glCompileShader(shader); CHECK_GL_ERROR;
90
91 GLint status;
92 _glGetShaderiv(shader, GL_COMPILE_STATUS, &status); CHECK_GL_ERROR;
93 if (status == GL_FALSE)
94 {
95 GLint infoLogLength;
96 _glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); CHECK_GL_ERROR;
97
98 GLchar strInfoLog[256];
99 _glGetShaderInfoLog(shader, sizeof(strInfoLog), NULL, strInfoLog); CHECK_GL_ERROR;
100 #ifdef ANT_WINDOWS
101 OutputDebugString("Compile failure: ");
102 OutputDebugString(strInfoLog);
103 OutputDebugString("\n");
104 #endif
105 fprintf(stderr, "Compile failure: %s\n", strInfoLog);
106 shader = 0;
107 }
108
109 return shader;
110 }
111
LinkProgram(GLuint program)112 static GLuint LinkProgram(GLuint program)
113 {
114 _glLinkProgram(program); CHECK_GL_ERROR;
115
116 GLint status;
117 _glGetProgramiv(program, GL_LINK_STATUS, &status); CHECK_GL_ERROR;
118 if (status == GL_FALSE)
119 {
120 GLint infoLogLength;
121 _glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); CHECK_GL_ERROR;
122
123 GLchar strInfoLog[256];
124 _glGetProgramInfoLog(program, sizeof(strInfoLog), NULL, strInfoLog); CHECK_GL_ERROR;
125 #ifdef ANT_WINDOWS
126 OutputDebugString("Linker failure: ");
127 OutputDebugString(strInfoLog);
128 OutputDebugString("\n");
129 #endif
130 fprintf(stderr, "Linker failure: %s\n", strInfoLog);
131 program = 0;
132 }
133
134 return program;
135 }
136
137 // ---------------------------------------------------------------------------
138
ResizeTriBuffers(size_t _NewSize)139 void CTwGraphOpenGLCore::ResizeTriBuffers(size_t _NewSize)
140 {
141 m_TriBufferSize = _NewSize;
142
143 _glBindVertexArray(m_TriVArray);
144
145 _glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
146 _glBufferData(GL_ARRAY_BUFFER, m_TriBufferSize*sizeof(Vec2), 0, GL_DYNAMIC_DRAW);
147
148 _glBindBuffer(GL_ARRAY_BUFFER, m_TriUVs);
149 _glBufferData(GL_ARRAY_BUFFER, m_TriBufferSize*sizeof(Vec2), 0, GL_DYNAMIC_DRAW);
150
151 _glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
152 _glBufferData(GL_ARRAY_BUFFER, m_TriBufferSize*sizeof(color32), 0, GL_DYNAMIC_DRAW);
153
154 CHECK_GL_ERROR;
155 }
156
157 // ---------------------------------------------------------------------------
158
Init()159 int CTwGraphOpenGLCore::Init()
160 {
161 m_Drawing = false;
162 m_FontTexID = 0;
163 m_FontTex = NULL;
164
165 if( LoadOpenGLCore()==0 )
166 {
167 g_TwMgr->SetLastError(g_ErrCantLoadOGL);
168 return 0;
169 }
170
171 // Create line/rect shaders
172 const GLchar *lineRectVS[] = {
173 "#version 150 core\n"
174 "in vec3 vertex;"
175 "in vec4 color;"
176 "out vec4 fcolor;"
177 "void main() { gl_Position = vec4(vertex, 1); fcolor = color; }"
178 };
179 m_LineRectVS = _glCreateShader(GL_VERTEX_SHADER);
180 _glShaderSource(m_LineRectVS, 1, lineRectVS, NULL);
181 CompileShader(m_LineRectVS);
182
183 const GLchar *lineRectFS[] = {
184 "#version 150 core\n"
185 "precision highp float;"
186 "in vec4 fcolor;"
187 "out vec4 outColor;"
188 "void main() { outColor = fcolor; }"
189 };
190 m_LineRectFS = _glCreateShader(GL_FRAGMENT_SHADER);
191 _glShaderSource(m_LineRectFS, 1, lineRectFS, NULL);
192 CompileShader(m_LineRectFS);
193
194 m_LineRectProgram = _glCreateProgram();
195 _glAttachShader(m_LineRectProgram, m_LineRectVS);
196 _glAttachShader(m_LineRectProgram, m_LineRectFS);
197 _glBindAttribLocation(m_LineRectProgram, 0, "vertex");
198 _glBindAttribLocation(m_LineRectProgram, 1, "color");
199 LinkProgram(m_LineRectProgram);
200
201 // Create line/rect vertex buffer
202 const GLfloat lineRectInitVertices[] = { 0,0,0, 0,0,0, 0,0,0, 0,0,0 };
203 const color32 lineRectInitColors[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
204 _glGenVertexArrays(1, &m_LineRectVArray);
205 _glBindVertexArray(m_LineRectVArray);
206 _glGenBuffers(1, &m_LineRectVertices);
207 _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectVertices);
208 _glBufferData(GL_ARRAY_BUFFER, sizeof(lineRectInitVertices), lineRectInitVertices, GL_DYNAMIC_DRAW);
209 _glGenBuffers(1, &m_LineRectColors);
210 _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectColors);
211 _glBufferData(GL_ARRAY_BUFFER, sizeof(lineRectInitColors), lineRectInitColors, GL_DYNAMIC_DRAW);
212
213 // Create triangles shaders
214 const GLchar *triVS[] = {
215 "#version 150 core\n"
216 "uniform vec2 offset;"
217 "uniform vec2 wndSize;"
218 "in vec2 vertex;"
219 "in vec4 color;"
220 "out vec4 fcolor;"
221 "void main() { gl_Position = vec4(2.0*(vertex.x+offset.x-0.5)/wndSize.x - 1.0, 1.0 - 2.0*(vertex.y+offset.y-0.5)/wndSize.y, 0, 1); fcolor = color; }"
222 };
223 m_TriVS = _glCreateShader(GL_VERTEX_SHADER);
224 _glShaderSource(m_TriVS, 1, triVS, NULL);
225 CompileShader(m_TriVS);
226
227 const GLchar *triUniVS[] = {
228 "#version 150 core\n"
229 "uniform vec2 offset;"
230 "uniform vec2 wndSize;"
231 "uniform vec4 color;"
232 "in vec2 vertex;"
233 "out vec4 fcolor;"
234 "void main() { gl_Position = vec4(2.0*(vertex.x+offset.x-0.5)/wndSize.x - 1.0, 1.0 - 2.0*(vertex.y+offset.y-0.5)/wndSize.y, 0, 1); fcolor = color; }"
235 };
236 m_TriUniVS = _glCreateShader(GL_VERTEX_SHADER);
237 _glShaderSource(m_TriUniVS, 1, triUniVS, NULL);
238 CompileShader(m_TriUniVS);
239
240 m_TriFS = m_TriUniFS = m_LineRectFS;
241
242 m_TriProgram = _glCreateProgram();
243 _glAttachShader(m_TriProgram, m_TriVS);
244 _glAttachShader(m_TriProgram, m_TriFS);
245 _glBindAttribLocation(m_TriProgram, 0, "vertex");
246 _glBindAttribLocation(m_TriProgram, 1, "color");
247 LinkProgram(m_TriProgram);
248 m_TriLocationOffset = _glGetUniformLocation(m_TriProgram, "offset");
249 m_TriLocationWndSize = _glGetUniformLocation(m_TriProgram, "wndSize");
250
251 m_TriUniProgram = _glCreateProgram();
252 _glAttachShader(m_TriUniProgram, m_TriUniVS);
253 _glAttachShader(m_TriUniProgram, m_TriUniFS);
254 _glBindAttribLocation(m_TriUniProgram, 0, "vertex");
255 _glBindAttribLocation(m_TriUniProgram, 1, "color");
256 LinkProgram(m_TriUniProgram);
257 m_TriUniLocationOffset = _glGetUniformLocation(m_TriUniProgram, "offset");
258 m_TriUniLocationWndSize = _glGetUniformLocation(m_TriUniProgram, "wndSize");
259 m_TriUniLocationColor = _glGetUniformLocation(m_TriUniProgram, "color");
260
261 const GLchar *triTexFS[] = {
262 "#version 150 core\n"
263 "precision highp float;"
264 "uniform sampler2D tex;"
265 "in vec2 fuv;"
266 "in vec4 fcolor;"
267 "out vec4 outColor;"
268 // texture2D is deprecated and replaced by texture with GLSL 3.30 but it seems
269 // that on Mac Lion backward compatibility is not ensured.
270 #if defined(ANT_OSX) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070)
271 "void main() { outColor.rgb = fcolor.bgr; outColor.a = fcolor.a * texture(tex, fuv).r; }"
272 #else
273 "void main() { outColor.rgb = fcolor.bgr; outColor.a = fcolor.a * texture2D(tex, fuv).r; }"
274 #endif
275 };
276 m_TriTexFS = _glCreateShader(GL_FRAGMENT_SHADER);
277 _glShaderSource(m_TriTexFS, 1, triTexFS, NULL);
278 CompileShader(m_TriTexFS);
279
280 const GLchar *triTexVS[] = {
281 "#version 150 core\n"
282 "uniform vec2 offset;"
283 "uniform vec2 wndSize;"
284 "in vec2 vertex;"
285 "in vec2 uv;"
286 "in vec4 color;"
287 "out vec2 fuv;"
288 "out vec4 fcolor;"
289 "void main() { gl_Position = vec4(2.0*(vertex.x+offset.x-0.5)/wndSize.x - 1.0, 1.0 - 2.0*(vertex.y+offset.y-0.5)/wndSize.y, 0, 1); fuv = uv; fcolor = color; }"
290 };
291 m_TriTexVS = _glCreateShader(GL_VERTEX_SHADER);
292 _glShaderSource(m_TriTexVS, 1, triTexVS, NULL);
293 CompileShader(m_TriTexVS);
294
295 const GLchar *triTexUniVS[] = {
296 "#version 150 core\n"
297 "uniform vec2 offset;"
298 "uniform vec2 wndSize;"
299 "uniform vec4 color;"
300 "in vec2 vertex;"
301 "in vec2 uv;"
302 "out vec4 fcolor;"
303 "out vec2 fuv;"
304 "void main() { gl_Position = vec4(2.0*(vertex.x+offset.x-0.5)/wndSize.x - 1.0, 1.0 - 2.0*(vertex.y+offset.y-0.5)/wndSize.y, 0, 1); fuv = uv; fcolor = color; }"
305 };
306 m_TriTexUniVS = _glCreateShader(GL_VERTEX_SHADER);
307 _glShaderSource(m_TriTexUniVS, 1, triTexUniVS, NULL);
308 CompileShader(m_TriTexUniVS);
309
310 m_TriTexUniFS = m_TriTexFS;
311
312 m_TriTexProgram = _glCreateProgram();
313 _glAttachShader(m_TriTexProgram, m_TriTexVS);
314 _glAttachShader(m_TriTexProgram, m_TriTexFS);
315 _glBindAttribLocation(m_TriTexProgram, 0, "vertex");
316 _glBindAttribLocation(m_TriTexProgram, 1, "uv");
317 _glBindAttribLocation(m_TriTexProgram, 2, "color");
318 LinkProgram(m_TriTexProgram);
319 m_TriTexLocationOffset = _glGetUniformLocation(m_TriTexProgram, "offset");
320 m_TriTexLocationWndSize = _glGetUniformLocation(m_TriTexProgram, "wndSize");
321 m_TriTexLocationTexture = _glGetUniformLocation(m_TriTexProgram, "tex");
322
323 m_TriTexUniProgram = _glCreateProgram();
324 _glAttachShader(m_TriTexUniProgram, m_TriTexUniVS);
325 _glAttachShader(m_TriTexUniProgram, m_TriTexUniFS);
326 _glBindAttribLocation(m_TriTexUniProgram, 0, "vertex");
327 _glBindAttribLocation(m_TriTexUniProgram, 1, "uv");
328 _glBindAttribLocation(m_TriTexUniProgram, 2, "color");
329 LinkProgram(m_TriTexUniProgram);
330 m_TriTexUniLocationOffset = _glGetUniformLocation(m_TriTexUniProgram, "offset");
331 m_TriTexUniLocationWndSize = _glGetUniformLocation(m_TriTexUniProgram, "wndSize");
332 m_TriTexUniLocationColor = _glGetUniformLocation(m_TriTexUniProgram, "color");
333 m_TriTexUniLocationTexture = _glGetUniformLocation(m_TriTexUniProgram, "tex");
334
335 // Create tri vertex buffer
336 _glGenVertexArrays(1, &m_TriVArray);
337 _glGenBuffers(1, &m_TriVertices);
338 _glGenBuffers(1, &m_TriUVs);
339 _glGenBuffers(1, &m_TriColors);
340 ResizeTriBuffers(16384); // set initial size
341
342 CHECK_GL_ERROR;
343 return 1;
344 }
345
346 // ---------------------------------------------------------------------------
347
Shut()348 int CTwGraphOpenGLCore::Shut()
349 {
350 assert(m_Drawing==false);
351
352 UnbindFont(m_FontTexID);
353
354 CHECK_GL_ERROR;
355
356 _glDeleteProgram(m_LineRectProgram); m_LineRectProgram = 0;
357 _glDeleteShader(m_LineRectVS); m_LineRectVS = 0;
358 _glDeleteShader(m_LineRectFS); m_LineRectFS = 0;
359
360 _glDeleteProgram(m_TriProgram); m_TriProgram = 0;
361 _glDeleteShader(m_TriVS); m_TriVS = 0;
362
363 _glDeleteProgram(m_TriUniProgram); m_TriUniProgram = 0;
364 _glDeleteShader(m_TriUniVS); m_TriUniVS = 0;
365
366 _glDeleteProgram(m_TriTexProgram); m_TriTexProgram = 0;
367 _glDeleteShader(m_TriTexVS); m_TriTexVS = 0;
368 _glDeleteShader(m_TriTexFS); m_TriTexFS = 0;
369
370 _glDeleteProgram(m_TriTexUniProgram); m_TriTexUniProgram = 0;
371 _glDeleteShader(m_TriTexUniVS); m_TriTexUniVS = 0;
372
373 _glDeleteBuffers(1, &m_LineRectVertices); m_LineRectVertices = 0;
374 _glDeleteBuffers(1, &m_LineRectColors); m_LineRectColors = 0;
375 _glDeleteVertexArrays(1, &m_LineRectVArray); m_LineRectVArray = 0;
376
377 _glDeleteBuffers(1, &m_TriVertices); m_TriVertices = 0;
378 _glDeleteBuffers(1, &m_TriColors); m_TriColors = 0;
379 _glDeleteBuffers(1, &m_TriUVs); m_TriUVs = 0;
380 _glDeleteVertexArrays(1, &m_TriVArray); m_TriVArray = 0;
381
382 CHECK_GL_ERROR;
383
384 int Res = 1;
385 if( UnloadOpenGLCore()==0 )
386 {
387 g_TwMgr->SetLastError(g_ErrCantUnloadOGL);
388 Res = 0;
389 }
390
391 return Res;
392 }
393
394 // ---------------------------------------------------------------------------
395
BeginDraw(int _WndWidth,int _WndHeight)396 void CTwGraphOpenGLCore::BeginDraw(int _WndWidth, int _WndHeight)
397 {
398 CHECK_GL_ERROR;
399 assert(m_Drawing==false && _WndWidth>0 && _WndHeight>0);
400 m_Drawing = true;
401 m_WndWidth = _WndWidth;
402 m_WndHeight = _WndHeight;
403 m_OffsetX = 0;
404 m_OffsetY = 0;
405
406 _glGetIntegerv(GL_VIEWPORT, m_PrevViewport); CHECK_GL_ERROR;
407 if( _WndWidth>0 && _WndHeight>0 )
408 {
409 GLint Vp[4];
410 Vp[0] = 0;
411 Vp[1] = 0;
412 Vp[2] = _WndWidth-1;
413 Vp[3] = _WndHeight-1;
414 _glViewport(Vp[0], Vp[1], Vp[2], Vp[3]);
415 }
416
417 m_PrevVArray = 0;
418 _glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&m_PrevVArray); CHECK_GL_ERROR;
419 _glBindVertexArray(0); CHECK_GL_ERROR;
420
421 m_PrevLineWidth = 1;
422 _glGetFloatv(GL_LINE_WIDTH, &m_PrevLineWidth); CHECK_GL_ERROR;
423 _glLineWidth(1); CHECK_GL_ERROR;
424
425 m_PrevLineSmooth = _glIsEnabled(GL_LINE_SMOOTH);
426 _glDisable(GL_LINE_SMOOTH); CHECK_GL_ERROR;
427
428 m_PrevCullFace = _glIsEnabled(GL_CULL_FACE);
429 _glDisable(GL_CULL_FACE); CHECK_GL_ERROR;
430
431 m_PrevDepthTest = _glIsEnabled(GL_DEPTH_TEST);
432 _glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR;
433
434 m_PrevBlend = _glIsEnabled(GL_BLEND);
435 _glEnable(GL_BLEND); CHECK_GL_ERROR;
436
437 m_PrevScissorTest = _glIsEnabled(GL_SCISSOR_TEST);
438 _glDisable(GL_SCISSOR_TEST); CHECK_GL_ERROR;
439
440 _glGetIntegerv(GL_SCISSOR_BOX, m_PrevScissorBox); CHECK_GL_ERROR;
441
442 _glGetIntegerv(GL_BLEND_SRC, &m_PrevSrcBlend); CHECK_GL_ERROR;
443 _glGetIntegerv(GL_BLEND_DST, &m_PrevDstBlend); CHECK_GL_ERROR;
444 _glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CHECK_GL_ERROR;
445
446 m_PrevTexture = 0;
447 _glGetIntegerv(GL_TEXTURE_BINDING_2D, &m_PrevTexture); CHECK_GL_ERROR;
448 _glBindTexture(GL_TEXTURE_2D, 0); CHECK_GL_ERROR;
449
450 m_PrevProgramObject = 0;
451 _glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&m_PrevProgramObject); CHECK_GL_ERROR;
452 _glBindVertexArray(0); CHECK_GL_ERROR;
453 _glUseProgram(0); CHECK_GL_ERROR;
454
455 m_PrevActiveTexture = 0;
456 _glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&m_PrevActiveTexture); CHECK_GL_ERROR;
457 _glActiveTexture(GL_TEXTURE0);
458
459 CHECK_GL_ERROR;
460 }
461
462 // ---------------------------------------------------------------------------
463
EndDraw()464 void CTwGraphOpenGLCore::EndDraw()
465 {
466 assert(m_Drawing==true);
467 m_Drawing = false;
468
469 _glLineWidth(m_PrevLineWidth); CHECK_GL_ERROR;
470
471 if( m_PrevLineSmooth )
472 {
473 _glEnable(GL_LINE_SMOOTH); CHECK_GL_ERROR;
474 }
475 else
476 {
477 _glDisable(GL_LINE_SMOOTH); CHECK_GL_ERROR;
478 }
479
480 if( m_PrevCullFace )
481 {
482 _glEnable(GL_CULL_FACE); CHECK_GL_ERROR;
483 }
484 else
485 {
486 _glDisable(GL_CULL_FACE); CHECK_GL_ERROR;
487 }
488
489 if( m_PrevDepthTest )
490 {
491 _glEnable(GL_DEPTH_TEST); CHECK_GL_ERROR;
492 }
493 else
494 {
495 _glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR;
496 }
497
498 if( m_PrevBlend )
499 {
500 _glEnable(GL_BLEND); CHECK_GL_ERROR;
501 }
502 else
503 {
504 _glDisable(GL_BLEND); CHECK_GL_ERROR;
505 }
506
507 if( m_PrevScissorTest )
508 {
509 _glEnable(GL_SCISSOR_TEST); CHECK_GL_ERROR;
510 }
511 else
512 {
513 _glDisable(GL_SCISSOR_TEST); CHECK_GL_ERROR;
514 }
515
516 _glScissor(m_PrevScissorBox[0], m_PrevScissorBox[1], m_PrevScissorBox[2], m_PrevScissorBox[3]); CHECK_GL_ERROR;
517
518 _glBlendFunc(m_PrevSrcBlend, m_PrevDstBlend); CHECK_GL_ERROR;
519
520 _glBindTexture(GL_TEXTURE_2D, m_PrevTexture); CHECK_GL_ERROR;
521
522 _glUseProgram(m_PrevProgramObject); CHECK_GL_ERROR;
523
524 _glBindVertexArray(m_PrevVArray); CHECK_GL_ERROR;
525
526 _glViewport(m_PrevViewport[0], m_PrevViewport[1], m_PrevViewport[2], m_PrevViewport[3]); CHECK_GL_ERROR;
527
528 CHECK_GL_ERROR;
529 }
530
531 // ---------------------------------------------------------------------------
532
IsDrawing()533 bool CTwGraphOpenGLCore::IsDrawing()
534 {
535 return m_Drawing;
536 }
537
538 // ---------------------------------------------------------------------------
539
Restore()540 void CTwGraphOpenGLCore::Restore()
541 {
542 UnbindFont(m_FontTexID);
543 m_FontTexID = 0;
544 m_FontTex = NULL;
545 }
546
547 // ---------------------------------------------------------------------------
548
ToNormScreenX(float x,int wndWidth)549 static inline float ToNormScreenX(float x, int wndWidth)
550 {
551 return 2.0f*((float)x-0.5f)/wndWidth - 1.0f;
552 }
553
ToNormScreenY(float y,int wndHeight)554 static inline float ToNormScreenY(float y, int wndHeight)
555 {
556 return 1.0f - 2.0f*((float)y-0.5f)/wndHeight;
557 }
558
559 // ---------------------------------------------------------------------------
560
DrawLine(int _X0,int _Y0,int _X1,int _Y1,color32 _Color0,color32 _Color1,bool _AntiAliased)561 void CTwGraphOpenGLCore::DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased)
562 {
563 CHECK_GL_ERROR;
564 assert(m_Drawing==true);
565
566 //const GLfloat dx = +0.0f;
567 const GLfloat dx = 0;
568 //GLfloat dy = -0.2f;
569 const GLfloat dy = -0.5f;
570 if( _AntiAliased )
571 _glEnable(GL_LINE_SMOOTH);
572 else
573 _glDisable(GL_LINE_SMOOTH);
574
575 _glBindVertexArray(m_LineRectVArray);
576
577 GLfloat x0 = ToNormScreenX(_X0+dx + m_OffsetX, m_WndWidth);
578 GLfloat y0 = ToNormScreenY(_Y0+dy + m_OffsetY, m_WndHeight);
579 GLfloat x1 = ToNormScreenX(_X1+dx + m_OffsetX, m_WndWidth);
580 GLfloat y1 = ToNormScreenY(_Y1+dy + m_OffsetY, m_WndHeight);
581 GLfloat vertices[] = { x0,y0,0, x1,y1,0 };
582 _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectVertices);
583 _glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
584 _glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 0, NULL);
585 _glEnableVertexAttribArray(0);
586
587 color32 colors[] = { _Color0, _Color1 };
588 _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectColors);
589 _glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(colors), colors);
590 _glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
591 _glEnableVertexAttribArray(1);
592
593 _glUseProgram(m_LineRectProgram);
594 _glDrawArrays(GL_LINES, 0, 2);
595
596 if( _AntiAliased )
597 _glDisable(GL_LINE_SMOOTH);
598
599 CHECK_GL_ERROR;
600 }
601
602 // ---------------------------------------------------------------------------
603
DrawRect(int _X0,int _Y0,int _X1,int _Y1,color32 _Color00,color32 _Color10,color32 _Color01,color32 _Color11)604 void CTwGraphOpenGLCore::DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11)
605 {
606 CHECK_GL_ERROR;
607 assert(m_Drawing==true);
608
609 // border adjustment
610 if(_X0<_X1)
611 ++_X1;
612 else if(_X0>_X1)
613 ++_X0;
614 if(_Y0<_Y1)
615 --_Y0;
616 else if(_Y0>_Y1)
617 --_Y1;
618
619 _glBindVertexArray(m_LineRectVArray);
620
621 GLfloat x0 = ToNormScreenX((float)_X0 + m_OffsetX, m_WndWidth);
622 GLfloat y0 = ToNormScreenY((float)_Y0 + m_OffsetY, m_WndHeight);
623 GLfloat x1 = ToNormScreenX((float)_X1 + m_OffsetX, m_WndWidth);
624 GLfloat y1 = ToNormScreenY((float)_Y1 + m_OffsetY, m_WndHeight);
625 GLfloat vertices[] = { x0,y0,0, x1,y0,0, x0,y1,0, x1,y1,0 };
626 _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectVertices);
627 _glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
628 _glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 0, NULL);
629 _glEnableVertexAttribArray(0);
630
631 GLuint colors[] = { _Color00, _Color10, _Color01, _Color11 };
632 _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectColors);
633 _glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(colors), colors);
634 _glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
635 _glEnableVertexAttribArray(1);
636
637 _glUseProgram(m_LineRectProgram);
638 _glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
639
640 CHECK_GL_ERROR;
641 }
642
643 // ---------------------------------------------------------------------------
644
NewTextObj()645 void *CTwGraphOpenGLCore::NewTextObj()
646 {
647 return new CTextObj;
648 }
649
650 // ---------------------------------------------------------------------------
651
DeleteTextObj(void * _TextObj)652 void CTwGraphOpenGLCore::DeleteTextObj(void *_TextObj)
653 {
654 assert(_TextObj!=NULL);
655 delete static_cast<CTextObj *>(_TextObj);
656 }
657
658 // ---------------------------------------------------------------------------
659
BuildText(void * _TextObj,const std::string * _TextLines,color32 * _LineColors,color32 * _LineBgColors,int _NbLines,const CTexFont * _Font,int _Sep,int _BgWidth)660 void CTwGraphOpenGLCore::BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth)
661 {
662 assert(m_Drawing==true);
663 assert(_TextObj!=NULL);
664 assert(_Font!=NULL);
665
666 if( _Font != m_FontTex )
667 {
668 UnbindFont(m_FontTexID);
669 m_FontTexID = BindFont(_Font);
670 m_FontTex = _Font;
671 }
672 CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);
673 TextObj->m_TextVerts.resize(0);
674 TextObj->m_TextUVs.resize(0);
675 TextObj->m_BgVerts.resize(0);
676 TextObj->m_Colors.resize(0);
677 TextObj->m_BgColors.resize(0);
678
679 int x, x1, y, y1, i, Len;
680 unsigned char ch;
681 const unsigned char *Text;
682 color32 LineColor = COLOR32_RED;
683 for( int Line=0; Line<_NbLines; ++Line )
684 {
685 x = 0;
686 y = Line * (_Font->m_CharHeight+_Sep);
687 y1 = y+_Font->m_CharHeight;
688 Len = (int)_TextLines[Line].length();
689 Text = (const unsigned char *)(_TextLines[Line].c_str());
690 if( _LineColors!=NULL )
691 LineColor = (_LineColors[Line]&0xff00ff00) | GLubyte(_LineColors[Line]>>16) | (GLubyte(_LineColors[Line])<<16);
692
693 for( i=0; i<Len; ++i )
694 {
695 ch = Text[i];
696 x1 = x + _Font->m_CharWidth[ch];
697
698 TextObj->m_TextVerts.push_back(Vec2(x , y ));
699 TextObj->m_TextVerts.push_back(Vec2(x1, y ));
700 TextObj->m_TextVerts.push_back(Vec2(x , y1));
701 TextObj->m_TextVerts.push_back(Vec2(x1, y ));
702 TextObj->m_TextVerts.push_back(Vec2(x1, y1));
703 TextObj->m_TextVerts.push_back(Vec2(x , y1));
704
705 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV0[ch]));
706 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
707 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));
708 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
709 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV1[ch]));
710 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));
711
712 if( _LineColors!=NULL )
713 {
714 TextObj->m_Colors.push_back(LineColor);
715 TextObj->m_Colors.push_back(LineColor);
716 TextObj->m_Colors.push_back(LineColor);
717 TextObj->m_Colors.push_back(LineColor);
718 TextObj->m_Colors.push_back(LineColor);
719 TextObj->m_Colors.push_back(LineColor);
720 }
721
722 x = x1;
723 }
724 if( _BgWidth>0 )
725 {
726 TextObj->m_BgVerts.push_back(Vec2(-1 , y ));
727 TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
728 TextObj->m_BgVerts.push_back(Vec2(-1 , y1));
729 TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
730 TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y1));
731 TextObj->m_BgVerts.push_back(Vec2(-1 , y1));
732
733 if( _LineBgColors!=NULL )
734 {
735 color32 LineBgColor = (_LineBgColors[Line]&0xff00ff00) | GLubyte(_LineBgColors[Line]>>16) | (GLubyte(_LineBgColors[Line])<<16);
736 TextObj->m_BgColors.push_back(LineBgColor);
737 TextObj->m_BgColors.push_back(LineBgColor);
738 TextObj->m_BgColors.push_back(LineBgColor);
739 TextObj->m_BgColors.push_back(LineBgColor);
740 TextObj->m_BgColors.push_back(LineBgColor);
741 TextObj->m_BgColors.push_back(LineBgColor);
742 }
743 }
744 }
745 }
746
747 // ---------------------------------------------------------------------------
748
DrawText(void * _TextObj,int _X,int _Y,color32 _Color,color32 _BgColor)749 void CTwGraphOpenGLCore::DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor)
750 {
751 CHECK_GL_ERROR;
752 assert(m_Drawing==true);
753 assert(_TextObj!=NULL);
754 CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);
755
756 if( TextObj->m_TextVerts.size()<4 && TextObj->m_BgVerts.size()<4 )
757 return; // nothing to draw
758
759 // draw character background triangles
760 if( (_BgColor!=0 || TextObj->m_BgColors.size()==TextObj->m_BgVerts.size()) && TextObj->m_BgVerts.size()>=4 )
761 {
762 size_t numBgVerts = TextObj->m_BgVerts.size();
763 if( numBgVerts > m_TriBufferSize )
764 ResizeTriBuffers(numBgVerts + 2048);
765
766 _glBindVertexArray(m_TriVArray);
767
768 _glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
769 _glBufferSubData(GL_ARRAY_BUFFER, 0, numBgVerts*sizeof(Vec2), &(TextObj->m_BgVerts[0]));
770 _glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL);
771 _glEnableVertexAttribArray(0);
772 _glDisableVertexAttribArray(1);
773 _glDisableVertexAttribArray(2);
774
775 if( TextObj->m_BgColors.size()==TextObj->m_BgVerts.size() && _BgColor==0 )
776 {
777 _glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
778 _glBufferSubData(GL_ARRAY_BUFFER, 0, numBgVerts*sizeof(color32), &(TextObj->m_BgColors[0]));
779 _glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
780 _glEnableVertexAttribArray(1);
781
782 _glUseProgram(m_TriProgram);
783 _glUniform2f(m_TriLocationOffset, (float)_X, (float)_Y);
784 _glUniform2f(m_TriLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
785 }
786 else
787 {
788 _glUseProgram(m_TriUniProgram);
789 _glUniform4f(m_TriUniLocationColor, GLfloat((_BgColor>>16)&0xff)/256.0f, GLfloat((_BgColor>>8)&0xff)/256.0f, GLfloat(_BgColor&0xff)/256.0f, GLfloat((_BgColor>>24)&0xff)/256.0f);
790 _glUniform2f(m_TriUniLocationOffset, (float)_X, (float)_Y);
791 _glUniform2f(m_TriUniLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
792 }
793
794 _glDrawArrays(GL_TRIANGLES, 0, (GLsizei)TextObj->m_BgVerts.size());
795 }
796
797 // draw character triangles
798 if( TextObj->m_TextVerts.size()>=4 )
799 {
800 _glActiveTexture(GL_TEXTURE0);
801 _glBindTexture(GL_TEXTURE_2D, m_FontTexID);
802 size_t numTextVerts = TextObj->m_TextVerts.size();
803 if( numTextVerts > m_TriBufferSize )
804 ResizeTriBuffers(numTextVerts + 2048);
805
806 _glBindVertexArray(m_TriVArray);
807 _glDisableVertexAttribArray(2);
808
809 _glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
810 _glBufferSubData(GL_ARRAY_BUFFER, 0, numTextVerts*sizeof(Vec2), &(TextObj->m_TextVerts[0]));
811 _glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL);
812 _glEnableVertexAttribArray(0);
813
814 _glBindBuffer(GL_ARRAY_BUFFER, m_TriUVs);
815 _glBufferSubData(GL_ARRAY_BUFFER, 0, numTextVerts*sizeof(Vec2), &(TextObj->m_TextUVs[0]));
816 _glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
817 _glEnableVertexAttribArray(1);
818
819 if( TextObj->m_Colors.size()==TextObj->m_TextVerts.size() && _Color==0 )
820 {
821 _glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
822 _glBufferSubData(GL_ARRAY_BUFFER, 0, numTextVerts*sizeof(color32), &(TextObj->m_Colors[0]));
823 _glVertexAttribPointer(2, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
824 _glEnableVertexAttribArray(2);
825
826 _glUseProgram(m_TriTexProgram);
827 _glUniform2f(m_TriTexLocationOffset, (float)_X, (float)_Y);
828 _glUniform2f(m_TriTexLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
829 _glUniform1i(m_TriTexLocationTexture, 0);
830 }
831 else
832 {
833 _glUseProgram(m_TriTexUniProgram);
834 _glUniform4f(m_TriTexUniLocationColor, GLfloat((_Color>>16)&0xff)/256.0f, GLfloat((_Color>>8)&0xff)/256.0f, GLfloat(_Color&0xff)/256.0f, GLfloat((_Color>>24)&0xff)/256.0f);
835 _glUniform2f(m_TriTexUniLocationOffset, (float)_X, (float)_Y);
836 _glUniform2f(m_TriTexUniLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
837 _glUniform1i(m_TriTexUniLocationTexture, 0);
838 }
839
840 _glDrawArrays(GL_TRIANGLES, 0, (GLsizei)TextObj->m_TextVerts.size());
841 }
842
843 CHECK_GL_ERROR;
844 }
845
846 // ---------------------------------------------------------------------------
847
ChangeViewport(int _X0,int _Y0,int _Width,int _Height,int _OffsetX,int _OffsetY)848 void CTwGraphOpenGLCore::ChangeViewport(int _X0, int _Y0, int _Width, int _Height, int _OffsetX, int _OffsetY)
849 {
850 // glViewport impacts the NDC; use glScissor instead
851 m_OffsetX = _X0 + _OffsetX;
852 m_OffsetY = _Y0 + _OffsetY;
853 SetScissor(_X0, _Y0, _Width, _Height);
854 }
855
856 // ---------------------------------------------------------------------------
857
RestoreViewport()858 void CTwGraphOpenGLCore::RestoreViewport()
859 {
860 m_OffsetX = m_OffsetY = 0;
861 SetScissor(0, 0, 0, 0);
862 }
863
864 // ---------------------------------------------------------------------------
865
SetScissor(int _X0,int _Y0,int _Width,int _Height)866 void CTwGraphOpenGLCore::SetScissor(int _X0, int _Y0, int _Width, int _Height)
867 {
868 if( _Width>0 && _Height>0 )
869 {
870 _glScissor(_X0-1, m_WndHeight-_Y0-_Height, _Width-1, _Height);
871 _glEnable(GL_SCISSOR_TEST);
872 }
873 else
874 _glDisable(GL_SCISSOR_TEST);
875 }
876
877 // ---------------------------------------------------------------------------
878
DrawTriangles(int _NumTriangles,int * _Vertices,color32 * _Colors,Cull _CullMode)879 void CTwGraphOpenGLCore::DrawTriangles(int _NumTriangles, int *_Vertices, color32 *_Colors, Cull _CullMode)
880 {
881 assert(m_Drawing==true);
882
883 const GLfloat dx = +0.0f;
884 const GLfloat dy = +0.0f;
885
886 // Backup states
887 GLint prevCullFaceMode, prevFrontFace;
888 _glGetIntegerv(GL_CULL_FACE_MODE, &prevCullFaceMode);
889 _glGetIntegerv(GL_FRONT_FACE, &prevFrontFace);
890 GLboolean prevCullEnable = _glIsEnabled(GL_CULL_FACE);
891 _glCullFace(GL_BACK);
892 _glEnable(GL_CULL_FACE);
893 if( _CullMode==CULL_CW )
894 _glFrontFace(GL_CCW);
895 else if( _CullMode==CULL_CCW )
896 _glFrontFace(GL_CW);
897 else
898 _glDisable(GL_CULL_FACE);
899
900 _glUseProgram(m_TriProgram);
901 _glBindVertexArray(m_TriVArray);
902 _glUniform2f(m_TriLocationOffset, (float)m_OffsetX+dx, (float)m_OffsetY+dy);
903 _glUniform2f(m_TriLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
904 _glDisableVertexAttribArray(2);
905
906 size_t numVerts = 3*_NumTriangles;
907 if( numVerts > m_TriBufferSize )
908 ResizeTriBuffers(numVerts + 2048);
909
910 _glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
911 _glBufferSubData(GL_ARRAY_BUFFER, 0, numVerts*2*sizeof(int), _Vertices);
912 _glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, NULL);
913 _glEnableVertexAttribArray(0);
914
915 _glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
916 _glBufferSubData(GL_ARRAY_BUFFER, 0, numVerts*sizeof(color32), _Colors);
917 _glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
918 _glEnableVertexAttribArray(1);
919
920 _glDrawArrays(GL_TRIANGLES, 0, (GLsizei)numVerts);
921
922 // Reset states
923 _glCullFace(prevCullFaceMode);
924 _glFrontFace(prevFrontFace);
925 if( prevCullEnable )
926 _glEnable(GL_CULL_FACE);
927 else
928 _glDisable(GL_CULL_FACE);
929
930 CHECK_GL_ERROR;
931 }
932
933 // ---------------------------------------------------------------------------
934