2014-04-08 21:45:04 +02:00

642 lines
26 KiB
C++

#include "graphics/glwrap.hpp"
#include "irr_driver.hpp"
#include <fstream>
#include <string>
#include "config/user_config.hpp"
#ifdef _IRR_WINDOWS_API_
#define IRR_OGL_LOAD_EXTENSION(X) wglGetProcAddress(reinterpret_cast<const char*>(X))
PFNGLGENTRANSFORMFEEDBACKSPROC glGenTransformFeedbacks;
PFNGLBINDTRANSFORMFEEDBACKPROC glBindTransformFeedback;
PFNGLDRAWTRANSFORMFEEDBACKPROC glDrawTransformFeedback;
PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
PFNGLBINDBUFFERBASEPROC glBindBufferBase;
PFNGLGENBUFFERSPROC glGenBuffers;
PFNGLBINDBUFFERPROC glBindBuffer;
PFNGLBUFFERDATAPROC glBufferData;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
PFNGLUNIFORM1FPROC glUniform1f;
PFNGLUNIFORM3FPROC glUniform3f;
PFNGLDELETESHADERPROC glDeleteShader;
PFNGLGETSHADERIVPROC glGetShaderiv;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLACTIVETEXTUREPROC glActiveTexture;
PFNGLUNIFORM2FPROC glUniform2f;
PFNGLUNIFORM1IPROC glUniform1i;
PFNGLUNIFORM3IPROC glUniform3i;
PFNGLUNIFORM4IPROC glUniform4i;
PFNGLUNIFORM1FVPROC glUniform1fv;
PFNGLUNIFORM4FVPROC glUniform4fv;
PFNGLGETPROGRAMIVPROC glGetProgramiv;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
PFNGLBLENDEQUATIONPROC glBlendEquation;
PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
PFNGLDELETEBUFFERSPROC glDeleteBuffers;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
PFNGLTEXBUFFERPROC glTexBuffer;
PFNGLBUFFERSUBDATAPROC glBufferSubData;
PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
PFNGLTEXIMAGE3DPROC glTexImage3D;
PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex;
PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding;
#endif
static bool is_gl_init = false;
#ifdef DEBUG
#ifdef WIN32
#define ARB_DEBUG_OUTPUT
#endif
#endif
#ifdef ARB_DEBUG_OUTPUT
static void
#ifdef WIN32
CALLBACK
#endif
debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
const GLchar* msg, const void *userparam)
{
switch(source)
{
case GL_DEBUG_SOURCE_API_ARB:
Log::warn("GLWrap", "OpenGL debug callback - API");
break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
Log::warn("GLWrap", "OpenGL debug callback - WINDOW_SYSTEM");
break;
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
Log::warn("GLWrap", "OpenGL debug callback - SHADER_COMPILER");
break;
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
Log::warn("GLWrap", "OpenGL debug callback - THIRD_PARTY");
break;
case GL_DEBUG_SOURCE_APPLICATION_ARB:
Log::warn("GLWrap", "OpenGL debug callback - APPLICATION");
break;
case GL_DEBUG_SOURCE_OTHER_ARB:
Log::warn("GLWrap", "OpenGL debug callback - OTHER");
break;
}
switch(type)
{
case GL_DEBUG_TYPE_ERROR_ARB:
Log::warn("GLWrap", " Error type : ERROR");
break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
Log::warn("GLWrap", " Error type : DEPRECATED_BEHAVIOR");
break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
Log::warn("GLWrap", " Error type : UNDEFINED_BEHAVIOR");
break;
case GL_DEBUG_TYPE_PORTABILITY_ARB:
Log::warn("GLWrap", " Error type : PORTABILITY");
break;
case GL_DEBUG_TYPE_PERFORMANCE_ARB:
Log::warn("GLWrap", " Error type : PERFORMANCE");
break;
case GL_DEBUG_TYPE_OTHER_ARB:
Log::warn("GLWrap", " Error type : OTHER");
break;
}
switch(severity)
{
case GL_DEBUG_SEVERITY_HIGH_ARB:
Log::warn("GLWrap", " Severity : HIGH");
break;
case GL_DEBUG_SEVERITY_MEDIUM_ARB:
Log::warn("GLWrap", " Severity : MEDIUM");
break;
case GL_DEBUG_SEVERITY_LOW_ARB:
Log::warn("GLWrap", " Severity : LOW");
break;
}
if (msg)
Log::warn("GLWrap", " Message : %s", msg);
}
#endif
void initGL()
{
if (is_gl_init)
return;
is_gl_init = true;
#ifdef _IRR_WINDOWS_API_
glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC)IRR_OGL_LOAD_EXTENSION("glGenTransformFeedbacks");
glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC)IRR_OGL_LOAD_EXTENSION("glBindTransformFeedback");
glDrawTransformFeedback = (PFNGLDRAWTRANSFORMFEEDBACKPROC)IRR_OGL_LOAD_EXTENSION("glDrawTransformFeedback");
glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)IRR_OGL_LOAD_EXTENSION("glBeginTransformFeedback");
glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)IRR_OGL_LOAD_EXTENSION("glEndTransformFeedback");
glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)IRR_OGL_LOAD_EXTENSION("glBindBufferBase");
glGenBuffers = (PFNGLGENBUFFERSPROC)IRR_OGL_LOAD_EXTENSION("glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC)IRR_OGL_LOAD_EXTENSION("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)IRR_OGL_LOAD_EXTENSION("glBufferData");
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)IRR_OGL_LOAD_EXTENSION("glVertexAttribPointer");
glCreateShader = (PFNGLCREATESHADERPROC)IRR_OGL_LOAD_EXTENSION("glCreateShader");
glCompileShader = (PFNGLCOMPILESHADERPROC)IRR_OGL_LOAD_EXTENSION("glCompileShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)IRR_OGL_LOAD_EXTENSION("glShaderSource");
glCreateProgram = (PFNGLCREATEPROGRAMPROC)IRR_OGL_LOAD_EXTENSION("glCreateProgram");
glAttachShader = (PFNGLATTACHSHADERPROC)IRR_OGL_LOAD_EXTENSION("glAttachShader");
glLinkProgram = (PFNGLLINKPROGRAMPROC)IRR_OGL_LOAD_EXTENSION("glLinkProgram");
glUseProgram = (PFNGLUSEPROGRAMPROC)IRR_OGL_LOAD_EXTENSION("glUseProgram");
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)IRR_OGL_LOAD_EXTENSION("glEnableVertexAttribArray");
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)IRR_OGL_LOAD_EXTENSION("glGetUniformLocation");
glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)IRR_OGL_LOAD_EXTENSION("glUniformMatrix4fv");
glUniform1f = (PFNGLUNIFORM1FPROC)IRR_OGL_LOAD_EXTENSION("glUniform1f");
glUniform3f = (PFNGLUNIFORM3FPROC)IRR_OGL_LOAD_EXTENSION("glUniform3f");
glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)IRR_OGL_LOAD_EXTENSION("glDisableVertexAttribArray");
glDeleteShader = (PFNGLDELETESHADERPROC)IRR_OGL_LOAD_EXTENSION("glDeleteShader");
glGetShaderiv = (PFNGLGETSHADERIVPROC)IRR_OGL_LOAD_EXTENSION("glGetShaderiv");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)IRR_OGL_LOAD_EXTENSION("glGetShaderInfoLog");
glActiveTexture = (PFNGLACTIVETEXTUREPROC)IRR_OGL_LOAD_EXTENSION("glActiveTexture");
glUniform2f = (PFNGLUNIFORM2FPROC)IRR_OGL_LOAD_EXTENSION("glUniform2f");
glUniform4i = (PFNGLUNIFORM4IPROC)IRR_OGL_LOAD_EXTENSION("glUniform4i");
glUniform3i = (PFNGLUNIFORM3IPROC)IRR_OGL_LOAD_EXTENSION("glUniform3i");
glUniform1i = (PFNGLUNIFORM1IPROC)IRR_OGL_LOAD_EXTENSION("glUniform1i");
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)IRR_OGL_LOAD_EXTENSION("glGetProgramiv");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)IRR_OGL_LOAD_EXTENSION("glGetProgramInfoLog");
glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)IRR_OGL_LOAD_EXTENSION("glTransformFeedbackVaryings");
glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)IRR_OGL_LOAD_EXTENSION("glGetAttribLocation");
glBlendEquation = (PFNGLBLENDEQUATIONPROC)IRR_OGL_LOAD_EXTENSION("glBlendEquation");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)IRR_OGL_LOAD_EXTENSION("glVertexAttribDivisor");
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawArraysInstanced");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsInstanced");
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)IRR_OGL_LOAD_EXTENSION("glDeleteBuffers");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)IRR_OGL_LOAD_EXTENSION("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)IRR_OGL_LOAD_EXTENSION("glBindVertexArray");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)IRR_OGL_LOAD_EXTENSION("glDeleteVertexArrays");
glTexBuffer = (PFNGLTEXBUFFERPROC)IRR_OGL_LOAD_EXTENSION("glTexBuffer");
glUniform1fv = (PFNGLUNIFORM1FVPROC)IRR_OGL_LOAD_EXTENSION("glUniform1fv");
glUniform4fv = (PFNGLUNIFORM4FVPROC)IRR_OGL_LOAD_EXTENSION("glUniform4fv");
glBufferSubData = (PFNGLBUFFERSUBDATAPROC)IRR_OGL_LOAD_EXTENSION("glBufferSubData");
glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)IRR_OGL_LOAD_EXTENSION("glVertexAttribIPointer");
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)IRR_OGL_LOAD_EXTENSION("glGenFramebuffers");
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)IRR_OGL_LOAD_EXTENSION("glBindFramebuffer");
glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)IRR_OGL_LOAD_EXTENSION("glFramebufferTexture2D");
glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)IRR_OGL_LOAD_EXTENSION("glFramebufferTexture");
glTexImage3D = (PFNGLTEXIMAGE3DPROC)IRR_OGL_LOAD_EXTENSION("glTexImage3D");
glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)IRR_OGL_LOAD_EXTENSION("glGenerateMipmap");
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)IRR_OGL_LOAD_EXTENSION("glCheckFramebufferStatus");
glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)IRR_OGL_LOAD_EXTENSION("glTexImage2DMultisample");
glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)IRR_OGL_LOAD_EXTENSION("glBlitFramebuffer");
glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)IRR_OGL_LOAD_EXTENSION("glGetUniformBlockIndex");
glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)IRR_OGL_LOAD_EXTENSION("glUniformBlockBinding");
#ifdef DEBUG
glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)IRR_OGL_LOAD_EXTENSION("glDebugMessageCallbackARB");
#endif
#endif
#ifdef ARB_DEBUG_OUTPUT
if (glDebugMessageCallbackARB)
glDebugMessageCallbackARB((GLDEBUGPROCARB)debugCallback, NULL);
#endif
}
// Mostly from shader tutorial
GLuint LoadShader(const char * file, unsigned type)
{
GLuint Id = glCreateShader(type);
char versionString[20];
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
std::string Code = versionString;
std::ifstream Stream(file, std::ios::in);
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
Code += "\n" + Line;
Stream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
Log::info("GLWrap", "Compiling shader : %s", file);
char const * SourcePointer = Code.c_str();
int length = strlen(SourcePointer);
glShaderSource(Id, 1, &SourcePointer, &length);
glCompileShader(Id);
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
if (Result == GL_FALSE)
{
Log::error("GLWrap", "Error in shader %s", file);
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
return Id;
}
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
{
GLuint Program = glCreateProgram();
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(Program);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(Program, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE)
{
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
printf(ErrorMessage);
delete[] ErrorMessage;
}
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
return Program;
}
GLuint getTextureGLuint(irr::video::ITexture *tex)
{
return static_cast<irr::video::COpenGLTexture*>(tex)->getOpenGLTextureName();
}
GLuint getDepthTexture(irr::video::ITexture *tex)
{
assert(tex->isRenderTarget());
return static_cast<irr::video::COpenGLFBOTexture*>(tex)->DepthBufferTexture;
}
std::set<irr::video::ITexture *> AlreadyTransformedTexture;
void transformTexturesTosRGB(irr::video::ITexture *tex)
{
if (AlreadyTransformedTexture.find(tex) != AlreadyTransformedTexture.end())
return;
AlreadyTransformedTexture.insert(tex);
size_t w = tex->getSize().Width, h = tex->getSize().Height;
char *data = new char[w * h * 4];
memcpy(data, tex->lock(), w * h * 4);
tex->unlock();
glBindTexture(GL_TEXTURE_2D, getTextureGLuint(tex));
if (irr_driver->getGLSLVersion() < 150)
{
if (tex->hasAlpha())
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)data);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, (GLvoid *)data);
}
else
{
if (tex->hasAlpha())
glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)data);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, (GLvoid *)data);
}
glGenerateMipmap(GL_TEXTURE_2D);
delete[] data;
}
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF)
{
glActiveTexture(GL_TEXTURE0 + TextureUnit);
glBindTexture(GL_TEXTURE_2D, TextureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, allowAF ? (float)aniso : 1.0f);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
}
void blitFBO(GLuint Src, GLuint Dst, size_t width, size_t height)
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, Src);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, Dst);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
static void drawTexColoredQuad(const video::ITexture *texture, const video::SColor *col, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
unsigned colors[] = {
col[0].getRed(), col[0].getGreen(), col[0].getBlue(), col[0].getAlpha(),
col[1].getRed(), col[1].getGreen(), col[1].getBlue(), col[1].getAlpha(),
col[2].getRed(), col[2].getGreen(), col[2].getBlue(), col[2].getAlpha(),
col[3].getRed(), col[3].getGreen(), col[3].getBlue(), col[3].getAlpha(),
};
glBindBuffer(GL_ARRAY_BUFFER, UIShader::ColoredTextureRectShader::colorvbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(unsigned), colors);
glUseProgram(UIShader::ColoredTextureRectShader::Program);
glBindVertexArray(UIShader::ColoredTextureRectShader::vao);
setTexture(0, static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName(), GL_LINEAR, GL_LINEAR);
UIShader::TextureRectShader::setUniforms(center_pos_x, center_pos_y, width, height, tex_center_pos_x, tex_center_pos_y, tex_width, tex_height, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
}
void drawTexQuad(const video::ITexture *texture, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
glUseProgram(UIShader::TextureRectShader::Program);
glBindVertexArray(UIShader::TextureRectShader::vao);
setTexture(0, static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName(), GL_LINEAR, GL_LINEAR);
UIShader::TextureRectShader::setUniforms(center_pos_x, center_pos_y, width, height, tex_center_pos_x, tex_center_pos_y, tex_width, tex_height, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
}
static void
getSize(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect,
float &width, float &height,
float &center_pos_x, float &center_pos_y,
float &tex_width, float &tex_height,
float &tex_center_pos_x, float &tex_center_pos_y
)
{
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
center_pos_x = destRect.UpperLeftCorner.X + destRect.LowerRightCorner.X;
center_pos_x /= screen_w;
center_pos_x -= 1.;
center_pos_y = destRect.UpperLeftCorner.Y + destRect.LowerRightCorner.Y;
center_pos_y /= screen_h;
center_pos_y = 1. - center_pos_y;
width = destRect.LowerRightCorner.X - destRect.UpperLeftCorner.X;
width /= screen_w;
height = destRect.LowerRightCorner.Y - destRect.UpperLeftCorner.Y;
height /= screen_h;
const core::dimension2d<u32>& ss = texture->getOriginalSize();
tex_center_pos_x = sourceRect.UpperLeftCorner.X + sourceRect.LowerRightCorner.X;
tex_center_pos_x /= ss.Width * 2.;
tex_center_pos_y = sourceRect.UpperLeftCorner.Y + sourceRect.LowerRightCorner.Y;
tex_center_pos_y /= ss.Height * 2.;
tex_width = sourceRect.LowerRightCorner.X - sourceRect.UpperLeftCorner.X;
tex_width /= ss.Width * 2.;
tex_height = sourceRect.LowerRightCorner.Y - sourceRect.UpperLeftCorner.Y;
tex_height /= ss.Height * 2.;
if (texture->isRenderTarget())
{
tex_height = -tex_height;
}
const f32 invW = 1.f / static_cast<f32>(ss.Width);
const f32 invH = 1.f / static_cast<f32>(ss.Height);
const core::rect<f32> tcoords(
sourceRect.UpperLeftCorner.X * invW,
sourceRect.UpperLeftCorner.Y * invH,
sourceRect.LowerRightCorner.X * invW,
sourceRect.LowerRightCorner.Y *invH);
}
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, bool useAlphaChannelOfTexture)
{
if (!irr_driver->isGLSL()) {
video::SColor duplicatedArray[4] = {
colors, colors, colors, colors
};
draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture, destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
glUseProgram(UIShader::UniformColoredTextureRectShader::Program);
glBindVertexArray(UIShader::UniformColoredTextureRectShader::vao);
setTexture(0, static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName(), GL_LINEAR, GL_LINEAR);
UIShader::UniformColoredTextureRectShader::setUniforms(center_pos_x, center_pos_y, width, height, tex_center_pos_x, tex_center_pos_y, tex_width, tex_height,colors, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
}
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor* const colors, bool useAlphaChannelOfTexture)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DImage(texture, destRect, sourceRect, clipRect, colors, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture, destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
if (colors)
drawTexColoredQuad(texture, colors, width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
else
drawTexQuad(texture, width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
}
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position,
const core::rect<s32>* clip)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip);
return;
}
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
float center_pos_x = position.UpperLeftCorner.X + position.LowerRightCorner.X;
center_pos_x /= screen_w;
center_pos_x -= 1;
float center_pos_y = position.UpperLeftCorner.Y + position.LowerRightCorner.Y;
center_pos_y /= screen_h;
center_pos_y = 1 - center_pos_y;
float width = position.LowerRightCorner.X - position.UpperLeftCorner.X;
width /= screen_w;
float height = position.LowerRightCorner.Y - position.UpperLeftCorner.Y;
height /= screen_h;
if (color.getAlpha() < 255)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clip)
{
if (!clip->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y,
clip->getWidth(), clip->getHeight());
}
glUseProgram(UIShader::ColoredRectShader::Program);
glBindVertexArray(UIShader::ColoredRectShader::vao);
UIShader::ColoredRectShader::setUniforms(center_pos_x, center_pos_y, width, height, color);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
if (clip)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
}