1 // ---------------------------------------------------------------------------
4 // @author Philippe Decaudin - http://www.antisphere.com
5 // @license This file is part of the AntTweakBar library.
6 // Copyright © 2005, 2006 Philippe Decaudin.
7 // For conditions of distribution and use, see License.txt
11 // ---------------------------------------------------------------------------
14 #include "TwPrecomp.h"
21 const char *g_ErrCantLoadOGL = "Cannot load OpenGL library dynamically";
22 const char *g_ErrCantUnloadOGL = "Cannot unload OpenGL library";
24 GLuint g_SmallFontTexID = 0;
25 GLuint g_NormalFontTexID = 0;
26 GLuint g_LargeFontTexID = 0;
28 // ---------------------------------------------------------------------------
31 typedef void (APIENTRY * PFNGLBindBufferARB)(GLenum target, GLuint buffer);
32 typedef void (APIENTRY * PFNGLBindProgramARB)(GLenum target, GLuint program);
33 typedef GLuint (APIENTRY * PFNGLGetHandleARB)(GLenum pname);
34 typedef void (APIENTRY * PFNGLUseProgramObjectARB)(GLuint programObj);
35 PFNGLBindBufferARB _glBindBufferARB = NULL;
\r
36 PFNGLBindProgramARB _glBindProgramARB = NULL;
\r
37 PFNGLGetHandleARB _glGetHandleARB = NULL;
\r
38 PFNGLUseProgramObjectARB _glUseProgramObjectARB = NULL;
\r
39 #ifndef GL_ARRAY_BUFFER_ARB
\r
40 # define GL_ARRAY_BUFFER_ARB 0x8892
42 #ifndef GL_ELEMENT_ARRAY_BUFFER_ARB
43 # define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
45 #ifndef GL_ARRAY_BUFFER_BINDING_ARB
46 # define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
\r
48 #ifndef GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB
\r
49 # define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
51 #ifndef GL_VERTEX_PROGRAM_ARB
52 # define GL_VERTEX_PROGRAM_ARB 0x8620
54 #ifndef GL_FRAGMENT_PROGRAM_ARB
55 # define GL_FRAGMENT_PROGRAM_ARB 0x8804
57 #ifndef GL_PROGRAM_OBJECT_ARB
58 # define GL_PROGRAM_OBJECT_ARB 0x8B40
61 // ---------------------------------------------------------------------------
63 static GLuint BindFont(const CTexFont *_Font)
66 _glGenTextures(1, &TexID);
67 _glBindTexture(GL_TEXTURE_2D, TexID);
68 _glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
69 _glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
70 _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
71 _glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
72 _glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
73 _glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
74 _glPixelTransferf(GL_ALPHA_SCALE, 1);
75 _glPixelTransferf(GL_ALPHA_BIAS, 0);
76 _glPixelTransferf(GL_RED_BIAS, 1);
77 _glPixelTransferf(GL_GREEN_BIAS, 1);
78 _glPixelTransferf(GL_BLUE_BIAS, 1);
79 _glTexImage2D(GL_TEXTURE_2D, 0, 4, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
80 _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
81 _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
82 _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
83 _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
84 _glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
85 _glBindTexture(GL_TEXTURE_2D, 0);
86 _glPixelTransferf(GL_ALPHA_BIAS, 0);
87 _glPixelTransferf(GL_RED_BIAS, 0);
88 _glPixelTransferf(GL_GREEN_BIAS, 0);
89 _glPixelTransferf(GL_BLUE_BIAS, 0);
94 static void UnbindFont(GLuint _FontTexID)
97 _glDeleteTextures(1, &_FontTexID);
100 // ---------------------------------------------------------------------------
102 int CTwGraphOpenGL::Init()
104 if( LoadOpenGL()==0 )
106 g_TwMgr->SetLastError(g_ErrCantLoadOGL);
113 m_MaxClipPlanes = -1;
116 _glBindBufferARB = reinterpret_cast<PFNGLBindBufferARB>(_glGetProcAddress("glBindBufferARB"));
\r
117 _glBindProgramARB = reinterpret_cast<PFNGLBindProgramARB>(_glGetProcAddress("glBindProgramARB"));
\r
118 _glGetHandleARB = reinterpret_cast<PFNGLGetHandleARB>(_glGetProcAddress("glGetHandleARB"));
\r
119 _glUseProgramObjectARB = reinterpret_cast<PFNGLUseProgramObjectARB>(_glGetProcAddress("glUseProgramObjectARB"));
\r
124 // ---------------------------------------------------------------------------
126 int CTwGraphOpenGL::Shut()
128 assert(m_Drawing==false);
130 UnbindFont(m_FontTexID);
133 if( UnloadOpenGL()==0 )
135 g_TwMgr->SetLastError(g_ErrCantUnloadOGL);
142 // ---------------------------------------------------------------------------
144 void CTwGraphOpenGL::BeginDraw(int _WndWidth, int _WndHeight)
146 assert(m_Drawing==false && _WndWidth>0 && _WndHeight>0);
153 while( (err=_glGetError())!=0 )
155 sprintf(msg, "Before BeginDraw GL_ERROR=0x%x\n", err);
157 OutputDebugString(msg);
159 fprintf(stderr, msg);
164 _glPushAttrib(GL_ALL_ATTRIB_BITS);
165 _glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
166 _glMatrixMode(GL_TEXTURE);
169 _glMatrixMode(GL_MODELVIEW);
172 _glMatrixMode(GL_PROJECTION);
175 _glGetIntegerv(GL_VIEWPORT, Vp);
177 if( _WndWidth>0 && _WndHeight>0 )
183 _glViewport(Vp[0], Vp[1], Vp[2], Vp[3]);
186 //_glOrtho(Vp[0], Vp[0]+Vp[2]-1, Vp[1]+Vp[3]-1, Vp[1], -1, 1); // Doesn't work
187 _glOrtho(Vp[0], Vp[0]+Vp[2], Vp[1]+Vp[3], Vp[1], -1, 1);
189 if( _WndWidth>0 && _WndHeight>0 )
194 Vp[3] = _WndHeight-1;
195 _glViewport(Vp[0], Vp[1], Vp[2], Vp[3]);
198 _glOrtho(Vp[0], Vp[0]+Vp[2], Vp[1]+Vp[3], Vp[1], -1, 1);
200 _glGetFloatv(GL_LINE_WIDTH, &m_PrevLineWidth);
201 _glDisable(GL_POLYGON_STIPPLE);
203 _glDisable(GL_LINE_SMOOTH);
204 _glDisable(GL_LINE_STIPPLE);
205 _glDisable(GL_CULL_FACE);
206 _glDisable(GL_DEPTH_TEST);
207 _glDisable(GL_LIGHTING);
209 _glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
210 _glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &m_PrevTexEnv);
211 _glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
212 _glGetIntegerv(GL_POLYGON_MODE, m_PrevPolygonMode);
213 _glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
214 _glDisable(GL_ALPHA_TEST);
215 //_glEnable(GL_ALPHA_TEST);
216 //_glAlphaFunc(GL_GREATER, 0);
218 _glDisable(GL_LOGIC_OP);
219 _glDisable(GL_SCISSOR_TEST);
220 if( m_MaxClipPlanes<0 )
222 _glGetIntegerv(GL_MAX_CLIP_PLANES, &m_MaxClipPlanes);
223 if( m_MaxClipPlanes<0 || m_MaxClipPlanes>255 )
226 for( int i=0; i<m_MaxClipPlanes; ++i )
227 _glDisable(GL_CLIP_PLANE0+i);
229 _glGetIntegerv(GL_TEXTURE_BINDING_2D, &m_PrevTexture);
231 _glDisableClientState(GL_VERTEX_ARRAY);
232 _glDisableClientState(GL_NORMAL_ARRAY);
233 _glDisableClientState(GL_TEXTURE_COORD_ARRAY);
234 _glDisableClientState(GL_INDEX_ARRAY);
235 _glDisableClientState(GL_COLOR_ARRAY);
236 _glDisableClientState(GL_EDGE_FLAG_ARRAY);
238 if( _glBindBufferARB!=NULL )
240 m_PrevArrayBufferARB = m_PrevElementArrayBufferARB = 0;
241 _glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &m_PrevArrayBufferARB);
242 _glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &m_PrevElementArrayBufferARB);
243 _glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
244 _glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
246 if( _glBindProgramARB!=NULL )
248 m_PrevVertexProgramARB = _glIsEnabled(GL_VERTEX_PROGRAM_ARB);
249 m_PrevFragmentProgramARB = _glIsEnabled(GL_FRAGMENT_PROGRAM_ARB);
250 _glDisable(GL_VERTEX_PROGRAM_ARB);
251 _glDisable(GL_FRAGMENT_PROGRAM_ARB);
253 if( _glGetHandleARB!=NULL && _glUseProgramObjectARB!=NULL )
255 m_PrevProgramObjectARB = _glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
256 _glUseProgramObjectARB(0);
260 // ---------------------------------------------------------------------------
262 void CTwGraphOpenGL::EndDraw()
264 assert(m_Drawing==true);
267 _glBindTexture(GL_TEXTURE_2D, m_PrevTexture);
268 if( _glBindBufferARB!=NULL )
270 _glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_PrevArrayBufferARB);
271 _glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_PrevElementArrayBufferARB);
273 if( _glBindProgramARB!=NULL )
275 if( m_PrevVertexProgramARB )
276 _glEnable(GL_VERTEX_PROGRAM_ARB);
277 if( m_PrevFragmentProgramARB )
278 _glEnable(GL_FRAGMENT_PROGRAM_ARB);
280 if( _glGetHandleARB!=NULL && _glUseProgramObjectARB!=NULL )
281 _glUseProgramObjectARB(m_PrevProgramObjectARB);
283 _glPolygonMode(GL_FRONT, m_PrevPolygonMode[0]);
284 _glPolygonMode(GL_BACK, m_PrevPolygonMode[1]);
285 _glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m_PrevTexEnv);
286 _glLineWidth(m_PrevLineWidth);
287 _glMatrixMode(GL_PROJECTION);
289 _glMatrixMode(GL_MODELVIEW);
291 _glMatrixMode(GL_TEXTURE);
293 _glPopClientAttrib();
300 while( (err=_glGetError())!=0 )
302 sprintf(msg, "After EndDraw GL_ERROR=0x%x\n", err);
304 OutputDebugString(msg);
306 fprintf(stderr, msg);
312 // ---------------------------------------------------------------------------
314 bool CTwGraphOpenGL::IsDrawing()
319 // ---------------------------------------------------------------------------
321 void CTwGraphOpenGL::Restore()
323 UnbindFont(m_FontTexID);
329 // ---------------------------------------------------------------------------
331 void CTwGraphOpenGL::DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased)
333 assert(m_Drawing==true);
335 // border adjustment NO!!
345 const GLfloat dx = +0.0f;
346 //GLfloat dy = -0.2f;
347 const GLfloat dy = -0.5f;
349 _glEnable(GL_LINE_SMOOTH);
351 _glDisable(GL_LINE_SMOOTH);
352 _glDisable(GL_TEXTURE_2D);
353 _glMatrixMode(GL_MODELVIEW);
356 _glColor4ub(GLubyte(_Color0>>16), GLubyte(_Color0>>8), GLubyte(_Color0), GLubyte(_Color0>>24));
357 _glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y0+dy);
358 _glColor4ub(GLubyte(_Color1>>16), GLubyte(_Color1>>8), GLubyte(_Color1), GLubyte(_Color1>>24));
359 _glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y1+dy);
360 //_glVertex2i(_X0, _Y0);
361 //_glVertex2i(_X1, _Y1);
363 _glDisable(GL_LINE_SMOOTH);
366 // ---------------------------------------------------------------------------
368 void CTwGraphOpenGL::DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11)
370 assert(m_Drawing==true);
392 const GLfloat dx = +0.0f;
393 const GLfloat dy = +0.0f;
395 _glDisable(GL_TEXTURE_2D);
396 _glMatrixMode(GL_MODELVIEW);
398 //GLubyte r = GLubyte(_Color>>16);
399 //GLubyte g = GLubyte(_Color>>8);
400 //GLubyte b = GLubyte(_Color);
401 //GLubyte a = GLubyte(_Color>>24);
402 //_glColor4ub(GLubyte(_Color>>16), GLubyte(_Color>>8), GLubyte(_Color), GLubyte(_Color>>24));
403 //_glColor4ub(r, g, b, a);
405 _glColor4ub(GLubyte(_Color00>>16), GLubyte(_Color00>>8), GLubyte(_Color00), GLubyte(_Color00>>24));
406 _glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y0+dy);
407 _glColor4ub(GLubyte(_Color10>>16), GLubyte(_Color10>>8), GLubyte(_Color10), GLubyte(_Color10>>24));
408 _glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y0+dy);
409 _glColor4ub(GLubyte(_Color11>>16), GLubyte(_Color11>>8), GLubyte(_Color11), GLubyte(_Color11>>24));
410 _glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y1+dy);
411 _glColor4ub(GLubyte(_Color01>>16), GLubyte(_Color01>>8), GLubyte(_Color01), GLubyte(_Color01>>24));
412 _glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y1+dy);
416 // ---------------------------------------------------------------------------
418 void *CTwGraphOpenGL::NewTextObj()
423 // ---------------------------------------------------------------------------
425 void CTwGraphOpenGL::DeleteTextObj(void *_TextObj)
427 assert(_TextObj!=NULL);
428 delete static_cast<CTextObj *>(_TextObj);
431 // ---------------------------------------------------------------------------
433 void CTwGraphOpenGL::BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth)
435 assert(m_Drawing==true);
436 assert(_TextObj!=NULL);
439 if( _Font != m_FontTex )
441 UnbindFont(m_FontTexID);
442 m_FontTexID = BindFont(_Font);
445 CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);
446 TextObj->m_TextVerts.resize(0);
447 TextObj->m_TextUVs.resize(0);
448 TextObj->m_BgVerts.resize(0);
449 TextObj->m_Colors.resize(0);
450 TextObj->m_BgColors.resize(0);
452 int x, x1, y, y1, i, Len;
454 const unsigned char *Text;
455 color32 LineColor = COLOR32_RED;
456 for( int Line=0; Line<_NbLines; ++Line )
459 y = Line * (_Font->m_CharHeight+_Sep);
460 y1 = y+_Font->m_CharHeight;
461 Len = (int)_TextLines[Line].length();
462 Text = (const unsigned char *)(_TextLines[Line].c_str());
463 if( _LineColors!=NULL )
464 LineColor = (_LineColors[Line]&0xff00ff00) | GLubyte(_LineColors[Line]>>16) | (GLubyte(_LineColors[Line])<<16);
466 for( i=0; i<Len; ++i )
469 x1 = x + _Font->m_CharWidth[ch];
471 TextObj->m_TextVerts.push_back(Vec2(x , y ));
472 TextObj->m_TextVerts.push_back(Vec2(x1, y ));
473 TextObj->m_TextVerts.push_back(Vec2(x , y1));
474 TextObj->m_TextVerts.push_back(Vec2(x1, y ));
475 TextObj->m_TextVerts.push_back(Vec2(x1, y1));
476 TextObj->m_TextVerts.push_back(Vec2(x , y1));
478 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV0[ch]));
479 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
480 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));
481 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
482 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV1[ch]));
483 TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));
485 if( _LineColors!=NULL )
487 TextObj->m_Colors.push_back(LineColor);
488 TextObj->m_Colors.push_back(LineColor);
489 TextObj->m_Colors.push_back(LineColor);
490 TextObj->m_Colors.push_back(LineColor);
491 TextObj->m_Colors.push_back(LineColor);
492 TextObj->m_Colors.push_back(LineColor);
497 if( _BgWidth>0 && Len>0 )
499 TextObj->m_BgVerts.push_back(Vec2(-1 , y ));
500 TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
501 TextObj->m_BgVerts.push_back(Vec2(-1 , y1));
502 TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
503 TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y1));
504 TextObj->m_BgVerts.push_back(Vec2(-1 , y1));
506 if( _LineBgColors!=NULL )
508 color32 LineBgColor = (_LineBgColors[Line]&0xff00ff00) | GLubyte(_LineBgColors[Line]>>16) | (GLubyte(_LineBgColors[Line])<<16);
509 TextObj->m_BgColors.push_back(LineBgColor);
510 TextObj->m_BgColors.push_back(LineBgColor);
511 TextObj->m_BgColors.push_back(LineBgColor);
512 TextObj->m_BgColors.push_back(LineBgColor);
513 TextObj->m_BgColors.push_back(LineBgColor);
514 TextObj->m_BgColors.push_back(LineBgColor);
520 // ---------------------------------------------------------------------------
522 void CTwGraphOpenGL::DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor)
524 assert(m_Drawing==true);
525 assert(_TextObj!=NULL);
526 CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);
528 if( TextObj->m_TextVerts.size()<4 )
529 return; // no character to draw
531 _glMatrixMode(GL_MODELVIEW);
533 _glTranslatef((GLfloat)_X, (GLfloat)_Y, 0);
534 _glEnableClientState(GL_VERTEX_ARRAY);
535 if( (_BgColor!=0 || TextObj->m_BgColors.size()==TextObj->m_BgVerts.size()) && TextObj->m_BgVerts.size()>=4 )
537 _glDisable(GL_TEXTURE_2D);
538 _glVertexPointer(2, GL_FLOAT, 0, &(TextObj->m_BgVerts[0]));
539 if( TextObj->m_BgColors.size()==TextObj->m_BgVerts.size() && _BgColor==0 )
541 _glEnableClientState(GL_COLOR_ARRAY);
542 _glColorPointer(4, GL_UNSIGNED_BYTE, 0, &(TextObj->m_BgColors[0]));
546 _glDisableClientState(GL_COLOR_ARRAY);
547 _glColor4ub(GLubyte(_BgColor>>16), GLubyte(_BgColor>>8), GLubyte(_BgColor), GLubyte(_BgColor>>24));
549 _glDrawArrays(GL_TRIANGLES, 0, (int)TextObj->m_BgVerts.size());
551 _glEnable(GL_TEXTURE_2D);
552 _glBindTexture(GL_TEXTURE_2D, m_FontTexID);
553 _glEnableClientState(GL_TEXTURE_COORD_ARRAY);
554 _glVertexPointer(2, GL_FLOAT, 0, &(TextObj->m_TextVerts[0]));
555 _glTexCoordPointer(2, GL_FLOAT, 0, &(TextObj->m_TextUVs[0]));
556 if( TextObj->m_Colors.size()==TextObj->m_TextVerts.size() && _Color==0 )
558 _glEnableClientState(GL_COLOR_ARRAY);
559 _glColorPointer(4, GL_UNSIGNED_BYTE, 0, &(TextObj->m_Colors[0]));
563 _glDisableClientState(GL_COLOR_ARRAY);
564 _glColor4ub(GLubyte(_Color>>16), GLubyte(_Color>>8), GLubyte(_Color), GLubyte(_Color>>24));
567 _glDrawArrays(GL_TRIANGLES, 0, (int)TextObj->m_TextVerts.size());
569 _glDisableClientState(GL_VERTEX_ARRAY);
570 _glDisableClientState(GL_TEXTURE_COORD_ARRAY);
571 _glDisableClientState(GL_COLOR_ARRAY);
574 // ---------------------------------------------------------------------------