Files
bullet3/Extras/CDTestFramework/AntTweakBar/src/TwOpenGLCore.cpp
erwin.coumans 4442a826ed add commandline arguments to serialize demo for xml export and Bullet import file name
update AntTweakBar version in CDTestFramework
add btCompoundShape support in BulletXmlWorldImporter (this importer is still premature/work-in-progress)
2012-09-26 19:47:18 +00:00

928 lines
32 KiB
C++

// ---------------------------------------------------------------------------
//
// @file TwOpenGLCore.cpp
// @author Philippe Decaudin - http://www.antisphere.com
// @license This file is part of the AntTweakBar library.
// For conditions of distribution and use, see License.txt
//
// ---------------------------------------------------------------------------
/*
#pragma warning GL3 //// used for development
#define GL3_PROTOTYPES 1 ////
#include <GL3/gl3.h> ////
#define ANT_OGL_HEADER_INCLUDED ////
*/
#if defined ANT_OSX
# include <OpenGL/gl3.h>
# define ANT_OGL_HEADER_INCLUDED
#endif
#include "TwPrecomp.h"
#include "LoadOGLCore.h"
#include "TwOpenGLCore.h"
#include "TwMgr.h"
using namespace std;
extern const char *g_ErrCantLoadOGL;
extern const char *g_ErrCantUnloadOGL;
// ---------------------------------------------------------------------------
#ifdef _DEBUG
static void CheckGLCoreError(const char *file, int line, const char *func)
{
int err=0;
char msg[256];
while( (err=_glGetError())!=0 )
{
sprintf(msg, "%s(%d) : [%s] GL_CORE_ERROR=0x%x\n", file, line, func, err);
#ifdef ANT_WINDOWS
OutputDebugString(msg);
#endif
fprintf(stderr, msg);
}
}
# ifdef __FUNCTION__
# define CHECK_GL_ERROR CheckGLCoreError(__FILE__, __LINE__, __FUNCTION__)
# else
# define CHECK_GL_ERROR CheckGLCoreError(__FILE__, __LINE__, "")
# endif
#else
# define CHECK_GL_ERROR ((void)(0))
#endif
// ---------------------------------------------------------------------------
static GLuint BindFont(const CTexFont *_Font)
{
GLuint TexID = 0;
_glGenTextures(1, &TexID);
_glBindTexture(GL_TEXTURE_2D, TexID);
_glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
_glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
_glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
_glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
_glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
_glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
_glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
_glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
_glBindTexture(GL_TEXTURE_2D, 0);
return TexID;
}
static void UnbindFont(GLuint _FontTexID)
{
if( _FontTexID>0 )
_glDeleteTextures(1, &_FontTexID);
}
// ---------------------------------------------------------------------------
static GLuint CompileShader(GLuint shader)
{
_glCompileShader(shader); CHECK_GL_ERROR;
GLint status;
_glGetShaderiv(shader, GL_COMPILE_STATUS, &status); CHECK_GL_ERROR;
if (status == GL_FALSE)
{
GLint infoLogLength;
_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); CHECK_GL_ERROR;
GLchar strInfoLog[256];
_glGetShaderInfoLog(shader, sizeof(strInfoLog), NULL, strInfoLog); CHECK_GL_ERROR;
#ifdef ANT_WINDOWS
OutputDebugString("Compile failure: ");
OutputDebugString(strInfoLog);
OutputDebugString("\n");
#endif
fprintf(stderr, "Compile failure: %s\n", strInfoLog);
shader = 0;
}
return shader;
}
static GLuint LinkProgram(GLuint program)
{
_glLinkProgram(program); CHECK_GL_ERROR;
GLint status;
_glGetProgramiv(program, GL_LINK_STATUS, &status); CHECK_GL_ERROR;
if (status == GL_FALSE)
{
GLint infoLogLength;
_glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); CHECK_GL_ERROR;
GLchar strInfoLog[256];
_glGetProgramInfoLog(program, sizeof(strInfoLog), NULL, strInfoLog); CHECK_GL_ERROR;
#ifdef ANT_WINDOWS
OutputDebugString("Linker failure: ");
OutputDebugString(strInfoLog);
OutputDebugString("\n");
#endif
fprintf(stderr, "Linker failure: %s\n", strInfoLog);
program = 0;
}
return program;
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::ResizeTriBuffers(size_t _NewSize)
{
m_TriBufferSize = _NewSize;
_glBindVertexArray(m_TriVArray);
_glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
_glBufferData(GL_ARRAY_BUFFER, m_TriBufferSize*sizeof(Vec2), 0, GL_DYNAMIC_DRAW);
_glBindBuffer(GL_ARRAY_BUFFER, m_TriUVs);
_glBufferData(GL_ARRAY_BUFFER, m_TriBufferSize*sizeof(Vec2), 0, GL_DYNAMIC_DRAW);
_glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
_glBufferData(GL_ARRAY_BUFFER, m_TriBufferSize*sizeof(color32), 0, GL_DYNAMIC_DRAW);
CHECK_GL_ERROR;
}
// ---------------------------------------------------------------------------
int CTwGraphOpenGLCore::Init()
{
m_Drawing = false;
m_FontTexID = 0;
m_FontTex = NULL;
if( LoadOpenGLCore()==0 )
{
g_TwMgr->SetLastError(g_ErrCantLoadOGL);
return 0;
}
// Create line/rect shaders
const GLchar *lineRectVS[] = {
"#version 150 core\n"
"in vec3 vertex;"
"in vec4 color;"
"out vec4 fcolor;"
"void main() { gl_Position = vec4(vertex, 1); fcolor = color; }"
};
m_LineRectVS = _glCreateShader(GL_VERTEX_SHADER);
_glShaderSource(m_LineRectVS, 1, lineRectVS, NULL);
CompileShader(m_LineRectVS);
const GLchar *lineRectFS[] = {
"#version 150 core\n"
"precision highp float;"
"in vec4 fcolor;"
"out vec4 outColor;"
"void main() { outColor = fcolor; }"
};
m_LineRectFS = _glCreateShader(GL_FRAGMENT_SHADER);
_glShaderSource(m_LineRectFS, 1, lineRectFS, NULL);
CompileShader(m_LineRectFS);
m_LineRectProgram = _glCreateProgram();
_glAttachShader(m_LineRectProgram, m_LineRectVS);
_glAttachShader(m_LineRectProgram, m_LineRectFS);
_glBindAttribLocation(m_LineRectProgram, 0, "vertex");
_glBindAttribLocation(m_LineRectProgram, 1, "color");
LinkProgram(m_LineRectProgram);
// Create line/rect vertex buffer
const GLfloat lineRectInitVertices[] = { 0,0,0, 0,0,0, 0,0,0, 0,0,0 };
const color32 lineRectInitColors[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
_glGenVertexArrays(1, &m_LineRectVArray);
_glBindVertexArray(m_LineRectVArray);
_glGenBuffers(1, &m_LineRectVertices);
_glBindBuffer(GL_ARRAY_BUFFER, m_LineRectVertices);
_glBufferData(GL_ARRAY_BUFFER, sizeof(lineRectInitVertices), lineRectInitVertices, GL_DYNAMIC_DRAW);
_glGenBuffers(1, &m_LineRectColors);
_glBindBuffer(GL_ARRAY_BUFFER, m_LineRectColors);
_glBufferData(GL_ARRAY_BUFFER, sizeof(lineRectInitColors), lineRectInitColors, GL_DYNAMIC_DRAW);
// Create triangles shaders
const GLchar *triVS[] = {
"#version 150 core\n"
"uniform vec2 offset;"
"uniform vec2 wndSize;"
"in vec2 vertex;"
"in vec4 color;"
"out vec4 fcolor;"
"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; }"
};
m_TriVS = _glCreateShader(GL_VERTEX_SHADER);
_glShaderSource(m_TriVS, 1, triVS, NULL);
CompileShader(m_TriVS);
const GLchar *triUniVS[] = {
"#version 150 core\n"
"uniform vec2 offset;"
"uniform vec2 wndSize;"
"uniform vec4 color;"
"in vec2 vertex;"
"out vec4 fcolor;"
"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; }"
};
m_TriUniVS = _glCreateShader(GL_VERTEX_SHADER);
_glShaderSource(m_TriUniVS, 1, triUniVS, NULL);
CompileShader(m_TriUniVS);
m_TriFS = m_TriUniFS = m_LineRectFS;
m_TriProgram = _glCreateProgram();
_glAttachShader(m_TriProgram, m_TriVS);
_glAttachShader(m_TriProgram, m_TriFS);
_glBindAttribLocation(m_TriProgram, 0, "vertex");
_glBindAttribLocation(m_TriProgram, 1, "color");
LinkProgram(m_TriProgram);
m_TriLocationOffset = _glGetUniformLocation(m_TriProgram, "offset");
m_TriLocationWndSize = _glGetUniformLocation(m_TriProgram, "wndSize");
m_TriUniProgram = _glCreateProgram();
_glAttachShader(m_TriUniProgram, m_TriUniVS);
_glAttachShader(m_TriUniProgram, m_TriUniFS);
_glBindAttribLocation(m_TriUniProgram, 0, "vertex");
_glBindAttribLocation(m_TriUniProgram, 1, "color");
LinkProgram(m_TriUniProgram);
m_TriUniLocationOffset = _glGetUniformLocation(m_TriUniProgram, "offset");
m_TriUniLocationWndSize = _glGetUniformLocation(m_TriUniProgram, "wndSize");
m_TriUniLocationColor = _glGetUniformLocation(m_TriUniProgram, "color");
const GLchar *triTexFS[] = {
"#version 150 core\n"
"precision highp float;"
"uniform sampler2D tex;"
"in vec2 fuv;"
"in vec4 fcolor;"
"out vec4 outColor;"
"void main() { outColor.rgb = fcolor.bgr; outColor.a = fcolor.a * texture2D(tex, fuv).r; }"
};
m_TriTexFS = _glCreateShader(GL_FRAGMENT_SHADER);
_glShaderSource(m_TriTexFS, 1, triTexFS, NULL);
CompileShader(m_TriTexFS);
const GLchar *triTexVS[] = {
"#version 150 core\n"
"uniform vec2 offset;"
"uniform vec2 wndSize;"
"in vec2 vertex;"
"in vec2 uv;"
"in vec4 color;"
"out vec2 fuv;"
"out vec4 fcolor;"
"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; }"
};
m_TriTexVS = _glCreateShader(GL_VERTEX_SHADER);
_glShaderSource(m_TriTexVS, 1, triTexVS, NULL);
CompileShader(m_TriTexVS);
const GLchar *triTexUniVS[] = {
"#version 150 core\n"
"uniform vec2 offset;"
"uniform vec2 wndSize;"
"uniform vec4 color;"
"in vec2 vertex;"
"in vec2 uv;"
"out vec4 fcolor;"
"out vec2 fuv;"
"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; }"
};
m_TriTexUniVS = _glCreateShader(GL_VERTEX_SHADER);
_glShaderSource(m_TriTexUniVS, 1, triTexUniVS, NULL);
CompileShader(m_TriTexUniVS);
m_TriTexUniFS = m_TriTexFS;
m_TriTexProgram = _glCreateProgram();
_glAttachShader(m_TriTexProgram, m_TriTexVS);
_glAttachShader(m_TriTexProgram, m_TriTexFS);
_glBindAttribLocation(m_TriTexProgram, 0, "vertex");
_glBindAttribLocation(m_TriTexProgram, 1, "uv");
_glBindAttribLocation(m_TriTexProgram, 2, "color");
LinkProgram(m_TriTexProgram);
m_TriTexLocationOffset = _glGetUniformLocation(m_TriTexProgram, "offset");
m_TriTexLocationWndSize = _glGetUniformLocation(m_TriTexProgram, "wndSize");
m_TriTexLocationTexture = _glGetUniformLocation(m_TriTexProgram, "tex");
m_TriTexUniProgram = _glCreateProgram();
_glAttachShader(m_TriTexUniProgram, m_TriTexUniVS);
_glAttachShader(m_TriTexUniProgram, m_TriTexUniFS);
_glBindAttribLocation(m_TriTexUniProgram, 0, "vertex");
_glBindAttribLocation(m_TriTexUniProgram, 1, "uv");
_glBindAttribLocation(m_TriTexUniProgram, 2, "color");
LinkProgram(m_TriTexUniProgram);
m_TriTexUniLocationOffset = _glGetUniformLocation(m_TriTexUniProgram, "offset");
m_TriTexUniLocationWndSize = _glGetUniformLocation(m_TriTexUniProgram, "wndSize");
m_TriTexUniLocationColor = _glGetUniformLocation(m_TriTexUniProgram, "color");
m_TriTexUniLocationTexture = _glGetUniformLocation(m_TriTexUniProgram, "tex");
// Create tri vertex buffer
_glGenVertexArrays(1, &m_TriVArray);
_glGenBuffers(1, &m_TriVertices);
_glGenBuffers(1, &m_TriUVs);
_glGenBuffers(1, &m_TriColors);
ResizeTriBuffers(16384); // set initial size
CHECK_GL_ERROR;
return 1;
}
// ---------------------------------------------------------------------------
int CTwGraphOpenGLCore::Shut()
{
assert(m_Drawing==false);
UnbindFont(m_FontTexID);
CHECK_GL_ERROR;
_glDeleteProgram(m_LineRectProgram); m_LineRectProgram = 0;
_glDeleteShader(m_LineRectVS); m_LineRectVS = 0;
_glDeleteShader(m_LineRectFS); m_LineRectFS = 0;
_glDeleteProgram(m_TriProgram); m_TriProgram = 0;
_glDeleteShader(m_TriVS); m_TriVS = 0;
_glDeleteProgram(m_TriUniProgram); m_TriUniProgram = 0;
_glDeleteShader(m_TriUniVS); m_TriUniVS = 0;
_glDeleteProgram(m_TriTexProgram); m_TriTexProgram = 0;
_glDeleteShader(m_TriTexVS); m_TriTexVS = 0;
_glDeleteShader(m_TriTexFS); m_TriTexFS = 0;
_glDeleteProgram(m_TriTexUniProgram); m_TriTexUniProgram = 0;
_glDeleteShader(m_TriTexUniVS); m_TriTexUniVS = 0;
_glDeleteBuffers(1, &m_LineRectVertices); m_LineRectVertices = 0;
_glDeleteBuffers(1, &m_LineRectColors); m_LineRectColors = 0;
_glDeleteVertexArrays(1, &m_LineRectVArray); m_LineRectVArray = 0;
_glDeleteBuffers(1, &m_TriVertices); m_TriVertices = 0;
_glDeleteBuffers(1, &m_TriColors); m_TriColors = 0;
_glDeleteBuffers(1, &m_TriUVs); m_TriUVs = 0;
_glDeleteVertexArrays(1, &m_TriVArray); m_TriVArray = 0;
CHECK_GL_ERROR;
int Res = 1;
if( UnloadOpenGLCore()==0 )
{
g_TwMgr->SetLastError(g_ErrCantUnloadOGL);
Res = 0;
}
return Res;
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::BeginDraw(int _WndWidth, int _WndHeight)
{
CHECK_GL_ERROR;
assert(m_Drawing==false && _WndWidth>0 && _WndHeight>0);
m_Drawing = true;
m_WndWidth = _WndWidth;
m_WndHeight = _WndHeight;
m_OffsetX = 0;
m_OffsetY = 0;
_glGetIntegerv(GL_VIEWPORT, m_PrevViewport); CHECK_GL_ERROR;
if( _WndWidth>0 && _WndHeight>0 )
{
GLint Vp[4];
Vp[0] = 0;
Vp[1] = 0;
Vp[2] = _WndWidth-1;
Vp[3] = _WndHeight-1;
_glViewport(Vp[0], Vp[1], Vp[2], Vp[3]);
}
m_PrevVArray = 0;
_glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&m_PrevVArray); CHECK_GL_ERROR;
_glBindVertexArray(0); CHECK_GL_ERROR;
m_PrevLineWidth = 1;
_glGetFloatv(GL_LINE_WIDTH, &m_PrevLineWidth); CHECK_GL_ERROR;
_glLineWidth(1); CHECK_GL_ERROR;
m_PrevLineSmooth = _glIsEnabled(GL_LINE_SMOOTH);
_glDisable(GL_LINE_SMOOTH); CHECK_GL_ERROR;
m_PrevCullFace = _glIsEnabled(GL_CULL_FACE);
_glDisable(GL_CULL_FACE); CHECK_GL_ERROR;
m_PrevDepthTest = _glIsEnabled(GL_DEPTH_TEST);
_glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR;
m_PrevBlend = _glIsEnabled(GL_BLEND);
_glEnable(GL_BLEND); CHECK_GL_ERROR;
m_PrevScissorTest = _glIsEnabled(GL_SCISSOR_TEST);
_glDisable(GL_SCISSOR_TEST); CHECK_GL_ERROR;
_glGetIntegerv(GL_SCISSOR_BOX, m_PrevScissorBox); CHECK_GL_ERROR;
_glGetIntegerv(GL_BLEND_SRC, &m_PrevSrcBlend); CHECK_GL_ERROR;
_glGetIntegerv(GL_BLEND_DST, &m_PrevDstBlend); CHECK_GL_ERROR;
_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CHECK_GL_ERROR;
m_PrevTexture = 0;
_glGetIntegerv(GL_TEXTURE_BINDING_2D, &m_PrevTexture); CHECK_GL_ERROR;
_glBindTexture(GL_TEXTURE_2D, 0); CHECK_GL_ERROR;
m_PrevProgramObject = 0;
_glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&m_PrevProgramObject); CHECK_GL_ERROR;
_glBindVertexArray(0); CHECK_GL_ERROR;
_glUseProgram(0); CHECK_GL_ERROR;
m_PrevActiveTexture = 0;
_glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&m_PrevActiveTexture); CHECK_GL_ERROR;
_glActiveTexture(GL_TEXTURE0);
CHECK_GL_ERROR;
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::EndDraw()
{
assert(m_Drawing==true);
m_Drawing = false;
_glLineWidth(m_PrevLineWidth); CHECK_GL_ERROR;
if( m_PrevLineSmooth )
{
_glEnable(GL_LINE_SMOOTH); CHECK_GL_ERROR;
}
else
{
_glDisable(GL_LINE_SMOOTH); CHECK_GL_ERROR;
}
if( m_PrevCullFace )
{
_glEnable(GL_CULL_FACE); CHECK_GL_ERROR;
}
else
{
_glDisable(GL_CULL_FACE); CHECK_GL_ERROR;
}
if( m_PrevDepthTest )
{
_glEnable(GL_DEPTH_TEST); CHECK_GL_ERROR;
}
else
{
_glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR;
}
if( m_PrevBlend )
{
_glEnable(GL_BLEND); CHECK_GL_ERROR;
}
else
{
_glDisable(GL_BLEND); CHECK_GL_ERROR;
}
if( m_PrevScissorTest )
{
_glEnable(GL_SCISSOR_TEST); CHECK_GL_ERROR;
}
else
{
_glDisable(GL_SCISSOR_TEST); CHECK_GL_ERROR;
}
_glScissor(m_PrevScissorBox[0], m_PrevScissorBox[1], m_PrevScissorBox[2], m_PrevScissorBox[3]); CHECK_GL_ERROR;
_glBlendFunc(m_PrevSrcBlend, m_PrevDstBlend); CHECK_GL_ERROR;
_glBindTexture(GL_TEXTURE_2D, m_PrevTexture); CHECK_GL_ERROR;
_glUseProgram(m_PrevProgramObject); CHECK_GL_ERROR;
_glBindVertexArray(m_PrevVArray); CHECK_GL_ERROR;
_glViewport(m_PrevViewport[0], m_PrevViewport[1], m_PrevViewport[2], m_PrevViewport[3]); CHECK_GL_ERROR;
CHECK_GL_ERROR;
}
// ---------------------------------------------------------------------------
bool CTwGraphOpenGLCore::IsDrawing()
{
return m_Drawing;
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::Restore()
{
UnbindFont(m_FontTexID);
m_FontTexID = 0;
m_FontTex = NULL;
}
// ---------------------------------------------------------------------------
static inline float ToNormScreenX(float x, int wndWidth)
{
return 2.0f*((float)x-0.5f)/wndWidth - 1.0f;
}
static inline float ToNormScreenY(float y, int wndHeight)
{
return 1.0f - 2.0f*((float)y-0.5f)/wndHeight;
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased)
{
CHECK_GL_ERROR;
assert(m_Drawing==true);
//const GLfloat dx = +0.0f;
const GLfloat dx = 0;
//GLfloat dy = -0.2f;
const GLfloat dy = -0.5f;
if( _AntiAliased )
_glEnable(GL_LINE_SMOOTH);
else
_glDisable(GL_LINE_SMOOTH);
_glBindVertexArray(m_LineRectVArray);
GLfloat x0 = ToNormScreenX(_X0+dx + m_OffsetX, m_WndWidth);
GLfloat y0 = ToNormScreenY(_Y0+dy + m_OffsetY, m_WndHeight);
GLfloat x1 = ToNormScreenX(_X1+dx + m_OffsetX, m_WndWidth);
GLfloat y1 = ToNormScreenY(_Y1+dy + m_OffsetY, m_WndHeight);
GLfloat vertices[] = { x0,y0,0, x1,y1,0 };
_glBindBuffer(GL_ARRAY_BUFFER, m_LineRectVertices);
_glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
_glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(0);
color32 colors[] = { _Color0, _Color1 };
_glBindBuffer(GL_ARRAY_BUFFER, m_LineRectColors);
_glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(colors), colors);
_glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(1);
_glUseProgram(m_LineRectProgram);
_glDrawArrays(GL_LINES, 0, 2);
if( _AntiAliased )
_glDisable(GL_LINE_SMOOTH);
CHECK_GL_ERROR;
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11)
{
CHECK_GL_ERROR;
assert(m_Drawing==true);
// border adjustment
if(_X0<_X1)
++_X1;
else if(_X0>_X1)
++_X0;
if(_Y0<_Y1)
--_Y0;
else if(_Y0>_Y1)
--_Y1;
_glBindVertexArray(m_LineRectVArray);
GLfloat x0 = ToNormScreenX((float)_X0 + m_OffsetX, m_WndWidth);
GLfloat y0 = ToNormScreenY((float)_Y0 + m_OffsetY, m_WndHeight);
GLfloat x1 = ToNormScreenX((float)_X1 + m_OffsetX, m_WndWidth);
GLfloat y1 = ToNormScreenY((float)_Y1 + m_OffsetY, m_WndHeight);
GLfloat vertices[] = { x0,y0,0, x1,y0,0, x0,y1,0, x1,y1,0 };
_glBindBuffer(GL_ARRAY_BUFFER, m_LineRectVertices);
_glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
_glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(0);
GLuint colors[] = { _Color00, _Color10, _Color01, _Color11 };
_glBindBuffer(GL_ARRAY_BUFFER, m_LineRectColors);
_glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(colors), colors);
_glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(1);
_glUseProgram(m_LineRectProgram);
_glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
CHECK_GL_ERROR;
}
// ---------------------------------------------------------------------------
void *CTwGraphOpenGLCore::NewTextObj()
{
return new CTextObj;
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::DeleteTextObj(void *_TextObj)
{
assert(_TextObj!=NULL);
delete static_cast<CTextObj *>(_TextObj);
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth)
{
assert(m_Drawing==true);
assert(_TextObj!=NULL);
assert(_Font!=NULL);
if( _Font != m_FontTex )
{
UnbindFont(m_FontTexID);
m_FontTexID = BindFont(_Font);
m_FontTex = _Font;
}
CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);
TextObj->m_TextVerts.resize(0);
TextObj->m_TextUVs.resize(0);
TextObj->m_BgVerts.resize(0);
TextObj->m_Colors.resize(0);
TextObj->m_BgColors.resize(0);
int x, x1, y, y1, i, Len;
unsigned char ch;
const unsigned char *Text;
color32 LineColor = COLOR32_RED;
for( int Line=0; Line<_NbLines; ++Line )
{
x = 0;
y = Line * (_Font->m_CharHeight+_Sep);
y1 = y+_Font->m_CharHeight;
Len = (int)_TextLines[Line].length();
Text = (const unsigned char *)(_TextLines[Line].c_str());
if( _LineColors!=NULL )
LineColor = (_LineColors[Line]&0xff00ff00) | GLubyte(_LineColors[Line]>>16) | (GLubyte(_LineColors[Line])<<16);
for( i=0; i<Len; ++i )
{
ch = Text[i];
x1 = x + _Font->m_CharWidth[ch];
TextObj->m_TextVerts.push_back(Vec2(x , y ));
TextObj->m_TextVerts.push_back(Vec2(x1, y ));
TextObj->m_TextVerts.push_back(Vec2(x , y1));
TextObj->m_TextVerts.push_back(Vec2(x1, y ));
TextObj->m_TextVerts.push_back(Vec2(x1, y1));
TextObj->m_TextVerts.push_back(Vec2(x , y1));
TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV0[ch]));
TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));
TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV1[ch]));
TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));
if( _LineColors!=NULL )
{
TextObj->m_Colors.push_back(LineColor);
TextObj->m_Colors.push_back(LineColor);
TextObj->m_Colors.push_back(LineColor);
TextObj->m_Colors.push_back(LineColor);
TextObj->m_Colors.push_back(LineColor);
TextObj->m_Colors.push_back(LineColor);
}
x = x1;
}
if( _BgWidth>0 )
{
TextObj->m_BgVerts.push_back(Vec2(-1 , y ));
TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
TextObj->m_BgVerts.push_back(Vec2(-1 , y1));
TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y1));
TextObj->m_BgVerts.push_back(Vec2(-1 , y1));
if( _LineBgColors!=NULL )
{
color32 LineBgColor = (_LineBgColors[Line]&0xff00ff00) | GLubyte(_LineBgColors[Line]>>16) | (GLubyte(_LineBgColors[Line])<<16);
TextObj->m_BgColors.push_back(LineBgColor);
TextObj->m_BgColors.push_back(LineBgColor);
TextObj->m_BgColors.push_back(LineBgColor);
TextObj->m_BgColors.push_back(LineBgColor);
TextObj->m_BgColors.push_back(LineBgColor);
TextObj->m_BgColors.push_back(LineBgColor);
}
}
}
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor)
{
CHECK_GL_ERROR;
assert(m_Drawing==true);
assert(_TextObj!=NULL);
CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);
if( TextObj->m_TextVerts.size()<4 && TextObj->m_BgVerts.size()<4 )
return; // nothing to draw
// draw character background triangles
if( (_BgColor!=0 || TextObj->m_BgColors.size()==TextObj->m_BgVerts.size()) && TextObj->m_BgVerts.size()>=4 )
{
size_t numBgVerts = TextObj->m_BgVerts.size();
if( numBgVerts > m_TriBufferSize )
ResizeTriBuffers(numBgVerts + 2048);
_glBindVertexArray(m_TriVArray);
_glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
_glBufferSubData(GL_ARRAY_BUFFER, 0, numBgVerts*sizeof(Vec2), &(TextObj->m_BgVerts[0]));
_glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(0);
_glDisableVertexAttribArray(1);
_glDisableVertexAttribArray(2);
if( TextObj->m_BgColors.size()==TextObj->m_BgVerts.size() && _BgColor==0 )
{
_glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
_glBufferSubData(GL_ARRAY_BUFFER, 0, numBgVerts*sizeof(color32), &(TextObj->m_BgColors[0]));
_glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(1);
_glUseProgram(m_TriProgram);
_glUniform2f(m_TriLocationOffset, (float)_X, (float)_Y);
_glUniform2f(m_TriLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
}
else
{
_glUseProgram(m_TriUniProgram);
_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);
_glUniform2f(m_TriUniLocationOffset, (float)_X, (float)_Y);
_glUniform2f(m_TriUniLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
}
_glDrawArrays(GL_TRIANGLES, 0, (GLsizei)TextObj->m_BgVerts.size());
}
// draw character triangles
if( TextObj->m_TextVerts.size()>=4 )
{
_glActiveTexture(GL_TEXTURE0);
_glBindTexture(GL_TEXTURE_2D, m_FontTexID);
size_t numTextVerts = TextObj->m_TextVerts.size();
if( numTextVerts > m_TriBufferSize )
ResizeTriBuffers(numTextVerts + 2048);
_glBindVertexArray(m_TriVArray);
_glDisableVertexAttribArray(2);
_glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
_glBufferSubData(GL_ARRAY_BUFFER, 0, numTextVerts*sizeof(Vec2), &(TextObj->m_TextVerts[0]));
_glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(0);
_glBindBuffer(GL_ARRAY_BUFFER, m_TriUVs);
_glBufferSubData(GL_ARRAY_BUFFER, 0, numTextVerts*sizeof(Vec2), &(TextObj->m_TextUVs[0]));
_glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
_glEnableVertexAttribArray(1);
if( TextObj->m_Colors.size()==TextObj->m_TextVerts.size() && _Color==0 )
{
_glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
_glBufferSubData(GL_ARRAY_BUFFER, 0, numTextVerts*sizeof(color32), &(TextObj->m_Colors[0]));
_glVertexAttribPointer(2, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(2);
_glUseProgram(m_TriTexProgram);
_glUniform2f(m_TriTexLocationOffset, (float)_X, (float)_Y);
_glUniform2f(m_TriTexLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
_glUniform1i(m_TriTexLocationTexture, 0);
}
else
{
_glUseProgram(m_TriTexUniProgram);
_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);
_glUniform2f(m_TriTexUniLocationOffset, (float)_X, (float)_Y);
_glUniform2f(m_TriTexUniLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
_glUniform1i(m_TriTexUniLocationTexture, 0);
}
_glDrawArrays(GL_TRIANGLES, 0, (GLsizei)TextObj->m_TextVerts.size());
}
CHECK_GL_ERROR;
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::ChangeViewport(int _X0, int _Y0, int _Width, int _Height, int _OffsetX, int _OffsetY)
{
// glViewport impacts the NDC; use glScissor instead
m_OffsetX = _X0 + _OffsetX;
m_OffsetY = _Y0 + _OffsetY;
SetScissor(_X0, _Y0, _Width, _Height);
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::RestoreViewport()
{
m_OffsetX = m_OffsetY = 0;
SetScissor(0, 0, 0, 0);
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::SetScissor(int _X0, int _Y0, int _Width, int _Height)
{
if( _Width>0 && _Height>0 )
{
_glScissor(_X0-1, m_WndHeight-_Y0-_Height, _Width-1, _Height);
_glEnable(GL_SCISSOR_TEST);
}
else
_glDisable(GL_SCISSOR_TEST);
}
// ---------------------------------------------------------------------------
void CTwGraphOpenGLCore::DrawTriangles(int _NumTriangles, int *_Vertices, color32 *_Colors, Cull _CullMode)
{
assert(m_Drawing==true);
const GLfloat dx = +0.0f;
const GLfloat dy = +0.0f;
// Backup states
GLint prevCullFaceMode, prevFrontFace;
_glGetIntegerv(GL_CULL_FACE_MODE, &prevCullFaceMode);
_glGetIntegerv(GL_FRONT_FACE, &prevFrontFace);
GLboolean prevCullEnable = _glIsEnabled(GL_CULL_FACE);
_glCullFace(GL_BACK);
_glEnable(GL_CULL_FACE);
if( _CullMode==CULL_CW )
_glFrontFace(GL_CCW);
else if( _CullMode==CULL_CCW )
_glFrontFace(GL_CW);
else
_glDisable(GL_CULL_FACE);
_glUseProgram(m_TriProgram);
_glBindVertexArray(m_TriVArray);
_glUniform2f(m_TriLocationOffset, (float)m_OffsetX+dx, (float)m_OffsetY+dy);
_glUniform2f(m_TriLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
_glDisableVertexAttribArray(2);
size_t numVerts = 3*_NumTriangles;
if( numVerts > m_TriBufferSize )
ResizeTriBuffers(numVerts + 2048);
_glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
_glBufferSubData(GL_ARRAY_BUFFER, 0, numVerts*2*sizeof(int), _Vertices);
_glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, NULL);
_glEnableVertexAttribArray(0);
_glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
_glBufferSubData(GL_ARRAY_BUFFER, 0, numVerts*sizeof(color32), _Colors);
_glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
_glEnableVertexAttribArray(1);
_glDrawArrays(GL_TRIANGLES, 0, (GLsizei)numVerts);
// Reset states
_glCullFace(prevCullFaceMode);
_glFrontFace(prevFrontFace);
if( prevCullEnable )
_glEnable(GL_CULL_FACE);
else
_glDisable(GL_CULL_FACE);
CHECK_GL_ERROR;
}
// ---------------------------------------------------------------------------