#include "graphics/glwrap.hpp" #include "irr_driver.hpp" #include #include #include "config/user_config.hpp" #ifdef _IRR_WINDOWS_API_ #define IRR_OGL_LOAD_EXTENSION(X) wglGetProcAddress(reinterpret_cast(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(tex)->getOpenGLTextureName(); } GLuint getDepthTexture(irr::video::ITexture *tex) { assert(tex->isRenderTarget()); return static_cast(tex)->DepthBufferTexture; } std::set 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(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(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& destRect, const core::rect& sourceRect, float &width, float &height, float ¢er_pos_x, float ¢er_pos_y, float &tex_width, float &tex_height, float &tex_center_pos_x, float &tex_center_pos_y ) { core::dimension2d 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& 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(ss.Width); const f32 invH = 1.f / static_cast(ss.Height); const core::rect 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& destRect, const core::rect& sourceRect, const core::rect* 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& 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(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& destRect, const core::rect& sourceRect, const core::rect* 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& 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& position, const core::rect* clip) { if (!irr_driver->isGLSL()) { irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip); return; } core::dimension2d 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& 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); } }