From 58d76e255d0ca1a5d2a00f58919d3ef245e5321c Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Wed, 18 Apr 2012 20:03:43 -0300 Subject: [PATCH] begin implementing OpenGL 1.0 engine * option to pass -opengl1 or -opengl2 as argument * note that with this commit there are a lot of graphics regressions and the master will remaing unstable for a while * shaders disabled for a while --- modules/game_shaders/map.frag | 19 ++ src/framework/CMakeLists.txt | 3 + src/framework/core/clock.cpp | 1 - src/framework/global.h | 9 +- src/framework/graphics/coordsbuffer.cpp | 40 ++- src/framework/graphics/coordsbuffer.h | 34 +-- src/framework/graphics/font.cpp | 2 +- src/framework/graphics/framebuffer.cpp | 17 +- src/framework/graphics/framebuffer.h | 1 - src/framework/graphics/glutil.h | 5 +- src/framework/graphics/graphics.cpp | 224 +++++++++++----- src/framework/graphics/graphics.h | 36 ++- src/framework/graphics/hardwarebuffer.h | 3 +- src/framework/graphics/painter.cpp | 204 +++++++-------- src/framework/graphics/painter.h | 101 +++++--- src/framework/graphics/painterogl1.cpp | 243 ++++++++++++++++++ src/framework/graphics/painterogl1.h | 73 ++++++ src/framework/graphics/painterogl2.cpp | 159 ++++++++++++ src/framework/graphics/painterogl2.h | 57 ++++ .../graphics/painterogl2_shadersources.h | 68 +++++ .../graphics/paintershadermanager.cpp | 74 ++++++ src/framework/graphics/paintershadermanager.h | 48 ++++ .../graphics/paintershaderprogram.cpp | 85 ++---- src/framework/graphics/paintershaderprogram.h | 21 +- src/framework/graphics/particle.cpp | 10 +- src/framework/graphics/shaderprogram.h | 4 +- src/framework/graphics/texture.cpp | 24 +- src/framework/graphics/texture.h | 7 +- src/framework/ui/uiframecounter.cpp | 2 +- src/framework/ui/uitextedit.cpp | 6 +- src/framework/ui/uiwidget.cpp | 16 +- src/framework/ui/uiwidgetbasestyle.cpp | 24 +- src/framework/ui/uiwidgetimage.cpp | 4 +- src/framework/ui/uiwidgettext.cpp | 4 +- src/framework/util/compiler.h | 10 + src/framework/util/types.h | 5 +- src/otclient/core/animatedtext.cpp | 2 +- src/otclient/core/creature.cpp | 48 ++-- src/otclient/core/item.cpp | 11 +- src/otclient/core/mapview.cpp | 60 ++--- src/otclient/core/spritemanager.cpp | 2 +- src/otclient/core/statictext.cpp | 2 +- src/otclient/core/thing.cpp | 4 +- src/otclient/ui/uicreature.cpp | 2 +- src/otclient/ui/uiitem.cpp | 4 +- src/otclient/ui/uimap.cpp | 5 +- 46 files changed, 1288 insertions(+), 495 deletions(-) create mode 100644 src/framework/graphics/painterogl1.cpp create mode 100644 src/framework/graphics/painterogl1.h create mode 100644 src/framework/graphics/painterogl2.cpp create mode 100644 src/framework/graphics/painterogl2.h create mode 100644 src/framework/graphics/painterogl2_shadersources.h create mode 100644 src/framework/graphics/paintershadermanager.cpp create mode 100644 src/framework/graphics/paintershadermanager.h diff --git a/modules/game_shaders/map.frag b/modules/game_shaders/map.frag index ba9d5045..b13b0695 100644 --- a/modules/game_shaders/map.frag +++ b/modules/game_shaders/map.frag @@ -5,6 +5,7 @@ uniform sampler2D tex0; // map texture varying vec2 texCoord; // map texture coords //uniform vec4 awareArea; + void main() { gl_FragColor = texture2D(tex0, texCoord); @@ -83,4 +84,22 @@ void main() } gl_FragColor = color; } +*/ +/* +void main() +{ + vec4 sum = vec4(0); + vec2 texcoord = texCoord; + int j; + int i; + + for( i= -4 ;i < 4; i++) + { + for (j = -4; j < 4; j++) + { + sum += texture2D(tex0, texcoord + vec2(j, i)*0.0025) * 0.0125; + } + } + gl_FragColor = texture2D(tex0, texCoord) + sum; +} */ \ No newline at end of file diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 11290a55..f3c47f25 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -189,6 +189,8 @@ SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/painter.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl1.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl2.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp @@ -201,6 +203,7 @@ SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/graphics/shader.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/paintershaderprogram.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/paintershadermanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/coordsbuffer.cpp # framework sound diff --git a/src/framework/core/clock.cpp b/src/framework/core/clock.cpp index f1595b8d..849b3eae 100644 --- a/src/framework/core/clock.cpp +++ b/src/framework/core/clock.cpp @@ -45,7 +45,6 @@ ticks_t Clock::asyncTicks() return std::chrono::duration_cast(timeNow - m_startupTime).count(); } - void Clock::sleep(int ms) { usleep(ms * 1000); diff --git a/src/framework/global.h b/src/framework/global.h index e91d2fe9..5193e436 100644 --- a/src/framework/global.h +++ b/src/framework/global.h @@ -23,13 +23,7 @@ #ifndef FRAMEWORK_GLOBAL_H #define FRAMEWORK_GLOBAL_H -#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -#error "sorry, you need gcc 4.6 or greater to compile" -#endif - -#if !defined(__GXX_EXPERIMENTAL_CXX0X__) -#error "sorry, you must enable C++0x to compile" -#endif +#include "util/compiler.h" // common C/C++ headers #include "pch.h" @@ -38,7 +32,6 @@ #include "const.h" // additional utilities -#include "util/compiler.h" #include "util/types.h" #include "util/tools.h" #include "math/point.h" diff --git a/src/framework/graphics/coordsbuffer.cpp b/src/framework/graphics/coordsbuffer.cpp index f75d42fa..d802c0fa 100644 --- a/src/framework/graphics/coordsbuffer.cpp +++ b/src/framework/graphics/coordsbuffer.cpp @@ -26,18 +26,18 @@ CoordsBuffer::CoordsBuffer() { m_hardwareCacheMode = HardwareBuffer::DynamicDraw; - m_hardwareVertexBuffer = nullptr; - m_hardwareTextureVertexBuffer = nullptr; + m_hardwareVertexArray = nullptr; + m_hardwareTextureCoordArray = nullptr; m_hardwareCached = false; m_hardwareCaching = false; } CoordsBuffer::~CoordsBuffer() { - if(m_hardwareVertexBuffer) - delete m_hardwareVertexBuffer; - if(m_hardwareTextureVertexBuffer) - delete m_hardwareTextureVertexBuffer; + if(m_hardwareVertexArray) + delete m_hardwareVertexArray; + if(m_hardwareTextureCoordArray) + delete m_hardwareTextureCoordArray; } void CoordsBuffer::addBoudingRect(const Rect& dest, int innerLineWidth) @@ -78,8 +78,8 @@ void CoordsBuffer::addRepeatedRects(const Rect& dest, const Rect& src) } partialDest.translate(dest.topLeft()); - m_vertexBuffer.addRect(partialDest); - m_textureVertexBuffer.addRect(partialSrc); + m_vertexArray.addRect(partialDest); + m_textureCoordArray.addRect(partialSrc); } } m_hardwareCached = false; @@ -90,10 +90,6 @@ void CoordsBuffer::enableHardwareCaching(HardwareBuffer::UsagePattern usagePatte if(!g_graphics.canUseHardwareBuffers()) return; -#ifndef OPENGL_ES2 - if(!GL_ARB_vertex_buffer_object) - return; -#endif m_hardwareCacheMode = usagePattern; m_hardwareCaching = true; m_hardwareCached = false; @@ -104,18 +100,18 @@ void CoordsBuffer::updateCaches() if(!m_hardwareCaching || m_hardwareCached) return; - if(m_vertexBuffer.vertexCount() > 0) { - if(!m_hardwareVertexBuffer && m_vertexBuffer.vertexCount() > 0) - m_hardwareVertexBuffer = new HardwareBuffer(HardwareBuffer::VertexBuffer); - m_hardwareVertexBuffer->bind(); - m_hardwareVertexBuffer->write((void*)m_vertexBuffer.vertices(), m_vertexBuffer.size() * sizeof(float), m_hardwareCacheMode); + if(m_vertexArray.vertexCount() > 0) { + if(!m_hardwareVertexArray && m_vertexArray.vertexCount() > 0) + m_hardwareVertexArray = new HardwareBuffer(HardwareBuffer::VertexBuffer); + m_hardwareVertexArray->bind(); + m_hardwareVertexArray->write((void*)m_vertexArray.vertices(), m_vertexArray.size() * sizeof(float), m_hardwareCacheMode); } - if(m_textureVertexBuffer.vertexCount() > 0) { - if(!m_hardwareTextureVertexBuffer && m_textureVertexBuffer.vertexCount() > 0) - m_hardwareTextureVertexBuffer = new HardwareBuffer(HardwareBuffer::VertexBuffer); - m_hardwareTextureVertexBuffer->bind(); - m_hardwareTextureVertexBuffer->write((void*)m_textureVertexBuffer.vertices(), m_textureVertexBuffer.size() * sizeof(float), m_hardwareCacheMode); + if(m_textureCoordArray.vertexCount() > 0) { + if(!m_hardwareTextureCoordArray && m_textureCoordArray.vertexCount() > 0) + m_hardwareTextureCoordArray = new HardwareBuffer(HardwareBuffer::VertexBuffer); + m_hardwareTextureCoordArray->bind(); + m_hardwareTextureCoordArray->write((void*)m_textureCoordArray.vertices(), m_textureCoordArray.size() * sizeof(float), m_hardwareCacheMode); } m_hardwareCached = true; diff --git a/src/framework/graphics/coordsbuffer.h b/src/framework/graphics/coordsbuffer.h index 442cac14..c65ca780 100644 --- a/src/framework/graphics/coordsbuffer.h +++ b/src/framework/graphics/coordsbuffer.h @@ -33,23 +33,23 @@ public: ~CoordsBuffer(); void clear() { - m_textureVertexBuffer.clear(); - m_vertexBuffer.clear(); + m_textureCoordArray.clear(); + m_vertexArray.clear(); m_hardwareCached = false; } void addRect(const Rect& dest) { - m_vertexBuffer.addRect(dest); + m_vertexArray.addRect(dest); m_hardwareCached = false; } void addRect(const Rect& dest, const Rect& src) { - m_vertexBuffer.addRect(dest); - m_textureVertexBuffer.addRect(src); + m_vertexArray.addRect(dest); + m_textureCoordArray.addRect(src); m_hardwareCached = false; } void addQuad(const Rect& dest, const Rect& src) { - m_vertexBuffer.addQuad(dest); - m_textureVertexBuffer.addQuad(src); + m_vertexArray.addQuad(dest); + m_textureCoordArray.addQuad(src); m_hardwareCached = false; } @@ -60,20 +60,20 @@ public: void updateCaches(); bool isHardwareCached() { return m_hardwareCached; } - float *getVertexBuffer() const { return m_vertexBuffer.vertices(); } - float *getTextureVertexBuffer() const { return m_textureVertexBuffer.vertices(); } - int getVertexCount() const { return m_vertexBuffer.vertexCount(); } - int getTextureVertexCount() const { return m_textureVertexBuffer.vertexCount(); } + float *getVertexArray() const { return m_vertexArray.vertices(); } + float *getTextureCoordArray() const { return m_textureCoordArray.vertices(); } + int getVertexCount() const { return m_vertexArray.vertexCount(); } + int getTextureCoordCount() const { return m_textureCoordArray.vertexCount(); } - HardwareBuffer *getHardwareVertexBuffer() { return m_hardwareVertexBuffer; } - HardwareBuffer *getHardwareTextureVertexBuffer() { return m_hardwareTextureVertexBuffer; } + HardwareBuffer *getHardwareVertexArray() { return m_hardwareVertexArray; } + HardwareBuffer *getHardwareTextureCoordArray() { return m_hardwareTextureCoordArray; } private: - HardwareBuffer *m_hardwareVertexBuffer; - HardwareBuffer *m_hardwareTextureVertexBuffer; + HardwareBuffer *m_hardwareVertexArray; + HardwareBuffer *m_hardwareTextureCoordArray; HardwareBuffer::UsagePattern m_hardwareCacheMode; - VertexArray m_vertexBuffer; - VertexArray m_textureVertexBuffer; + VertexArray m_vertexArray; + VertexArray m_textureCoordArray; bool m_hardwareCached; bool m_hardwareCaching; }; diff --git a/src/framework/graphics/font.cpp b/src/framework/graphics/font.cpp index 6f77eaab..55dd3cda 100644 --- a/src/framework/graphics/font.cpp +++ b/src/framework/graphics/font.cpp @@ -77,7 +77,7 @@ void Font::drawText(const std::string& text, const Rect& screenCoords, Fw::Align coordsBuffer.clear(); calculateDrawTextCoords(coordsBuffer, text, screenCoords, align); - g_painter.drawTextureCoords(coordsBuffer, m_texture); + g_painter->drawTextureCoords(coordsBuffer, m_texture); } void Font::calculateDrawTextCoords(CoordsBuffer& coordsBuffer, const std::string& text, const Rect& screenCoords, Fw::AlignmentFlag align) diff --git a/src/framework/graphics/framebuffer.cpp b/src/framework/graphics/framebuffer.cpp index c0dc86be..f3b40f6f 100644 --- a/src/framework/graphics/framebuffer.cpp +++ b/src/framework/graphics/framebuffer.cpp @@ -105,43 +105,44 @@ void FrameBuffer::clear(const Color& color, const Rect& rect) { bool clip = rect.isValid(); if(clip) - g_painter.setClipRect(Rect(0, 0, m_texture->getSize())); + g_painter->setClipRect(Rect(0, 0, m_texture->getSize())); glClearColor(color.rF(), color.gF(), color.bF(), color.aF()); glClear(GL_COLOR_BUFFER_BIT); if(clip) - g_painter.resetClipRect(); + g_painter->resetClipRect(); } void FrameBuffer::bind() { internalBind(); + Matrix3 projectionMatrix = { 2.0f/m_texture->getWidth(), 0.0f, 0.0f, 0.0f, 2.0f/m_texture->getHeight(), 0.0f, - -1.0f, -1.0f, 0.0f }; + -1.0f, -1.0f, 1.0f }; + g_painter->saveAndResetState(); + g_painter->setProjectionMatrix(projectionMatrix); - m_oldProjectionMatrix = g_painter.getProjectionMatrix(); m_oldViewportSize = g_graphics.getViewportSize(); - g_painter.setProjectionMatrix(projectionMatrix); g_graphics.setViewportSize(m_texture->getSize()); } void FrameBuffer::release() { internalRelease(); - g_painter.setProjectionMatrix(m_oldProjectionMatrix); + g_painter->restoreSavedState(); g_graphics.setViewportSize(m_oldViewportSize); } void FrameBuffer::draw(const Rect& dest, const Rect& src) { - g_painter.drawTexturedRect(dest, m_texture, src); + g_painter->drawTexturedRect(dest, m_texture, src); } void FrameBuffer::draw(const Rect& dest) { - g_painter.drawTexturedRect(dest, m_texture, Rect(0,0, getSize())); + g_painter->drawTexturedRect(dest, m_texture, Rect(0,0, getSize())); } void FrameBuffer::internalBind() diff --git a/src/framework/graphics/framebuffer.h b/src/framework/graphics/framebuffer.h index 41c0fa53..846e9c9c 100644 --- a/src/framework/graphics/framebuffer.h +++ b/src/framework/graphics/framebuffer.h @@ -50,7 +50,6 @@ private: TexturePtr m_texture; TexturePtr m_screenBackup; - Matrix3 m_oldProjectionMatrix; Size m_oldViewportSize; uint m_fbo; uint m_prevBoundFbo; diff --git a/src/framework/graphics/glutil.h b/src/framework/graphics/glutil.h index a7e97665..d2e67941 100644 --- a/src/framework/graphics/glutil.h +++ b/src/framework/graphics/glutil.h @@ -27,12 +27,9 @@ #ifndef OPENGL_ES2 #define GLEW_STATIC #include -//#include -//#include #else -#define GL_GLEXT_PROTOTYPES #include -#include +//#include #endif #endif diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index fdae31e9..2f3ba8d8 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -21,6 +21,8 @@ */ #include "fontmanager.h" +#include "painterogl1.h" +#include "painterogl2.h" #include #include @@ -33,6 +35,11 @@ void oglDebugCallback(unsigned int source, unsigned int type, unsigned int id, u logWarning("OGL: ", message); } +Graphics::Graphics() +{ + m_maxTextureSize = -1; +} + void Graphics::init() { logInfo("GPU ", glGetString(GL_RENDERER)); @@ -50,29 +57,7 @@ void Graphics::init() glDebugMessageCallbackARB(oglDebugCallback, NULL); #endif - const char *requiredExtensions[] = { - "GL_ARB_vertex_program", - "GL_ARB_vertex_shader", - "GL_ARB_fragment_shader", - "GL_ARB_texture_non_power_of_two", - "GL_ARB_multitexture" - }; - - std::stringstream ss; - bool unsupported = false; - for(auto ext : requiredExtensions) { - if(!glewIsSupported(ext)) { - ss << ext << std::endl; - unsupported = true; - } - } - - if(unsupported) - logFatal("The following OpenGL 2.0 extensions are not supported by your system graphics, please try updating your video drivers or buy a new hardware:\n", - ss.str(), - "Graphics card: ", glGetString(GL_RENDERER), - "\nOpenGL driver: ", glGetString(GL_VERSION)); - + // overwrite framebuffer API if needed if(GLEW_EXT_framebuffer_object && !GLEW_ARB_framebuffer_object) { glGenFramebuffers = glGenFramebuffersEXT; glDeleteFramebuffers = glDeleteFramebuffersEXT; @@ -82,41 +67,105 @@ void Graphics::init() glGenerateMipmap = glGenerateMipmapEXT; } - m_useFBO = m_useFBO && (GLEW_ARB_framebuffer_object || GLEW_EXT_framebuffer_object); - m_generateHardwareMipmaps = m_generateHardwareMipmaps; // glGenerateMipmap is supported when framebuffers are + // opengl 1 is always supported + g_painterOGL1 = new PainterOGL1; + // opengl 2 is only supported in newer hardware + if(GLEW_VERSION_2_0) + g_painterOGL2 = new PainterOGL2; +#else + g_painterOGL2 = new PainterOGL2; #endif - glEnable(GL_BLEND); - glClear(GL_COLOR_BUFFER_BIT); + // determine max texture size + static GLint maxTextureSize = -1; + if(maxTextureSize == -1) + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + if(m_maxTextureSize == -1 || m_maxTextureSize > maxTextureSize) + m_maxTextureSize = maxTextureSize; + + //glClear(GL_COLOR_BUFFER_BIT); + //m_prefferedPainterEngine = Painter_OpenGL1; + selectPainterEngine(m_prefferedPainterEngine); m_emptyTexture = TexturePtr(new Texture); - g_painter.init(); } void Graphics::terminate() { g_fonts.releaseFonts(); - g_painter.terminate(); + + if(g_painterOGL1) { + delete g_painterOGL1; + g_painterOGL1 = nullptr; + } + + if(g_painterOGL2) { + delete g_painterOGL2; + g_painterOGL2 = nullptr; + } + + g_painter = nullptr; + m_emptyTexture.reset(); } bool Graphics::parseOption(const std::string& option) { - if(option == "-no-fbos") + if(option == "-no-draw-arrays") + m_useDrawArrays = false; + else if(option == "-no-fbos") m_useFBO = false; - else if(option == "-no-mipmapping") - m_generateMipmaps = false; - else if(option == "-no-smoothing") + else if(option == "-no-mipmaps") + m_useMipmaps = false; + else if(option == "-no-hardware-mipmaps") + m_useHardwareMipmaps = false; + else if(option == "-no-smooth") m_useBilinearFiltering = false; - else if(option == "-no-hardware-buffering") + else if(option == "-no-hardware-buffers") m_useHardwareBuffers = false; + else if(option == "-no-non-power-of-two-textures") + m_useNonPowerOfTwoTextures = false; + else if(option == "-opengl1") + m_prefferedPainterEngine = Painter_OpenGL1; + else if(option == "-opengl2") + m_prefferedPainterEngine = Painter_OpenGL2; else return false; return true; } +bool Graphics::selectPainterEngine(PainterEngine painterEngine) +{ + // always prefer OpenGL 2 over OpenGL 1 + if(g_painterOGL2 && (painterEngine == Painter_OpenGL2 || painterEngine == Painter_Any)) + g_painter = g_painterOGL2; + // fallback to OpenGL 1 in older hardwares + else if(g_painterOGL1 && (painterEngine == Painter_OpenGL1 || painterEngine == Painter_Any)) + g_painter = g_painterOGL1; + else + logFatal("Neither OpenGL 1.0 nor OpenGL 2.0 painter engine is supported by your platform, " + "try updating your graphics drivers or your hardware and then run again."); + + // switch painters GL state + if(g_painter) + g_painter->unbind(); + g_painter->bind(); + + if(painterEngine == Painter_Any) + return true; + return getPainterEngine() == painterEngine; +} + +Graphics::PainterEngine Graphics::getPainterEngine() +{ + if(g_painter == g_painterOGL2) + return Painter_OpenGL2; + else + return Painter_OpenGL1; +} + void Graphics::resize(const Size& size) { setViewportSize(size); @@ -128,17 +177,21 @@ void Graphics::resize(const Size& size) // // This results in the Projection matrix below. // - // Projection Matrix Painter Coord GL Coord - // ------------------------------------------------ --------- --------- - // | 2.0 / width | 0.0 | -1.0 | | x | | x' | - // | 0.0 | -2.0 / height | 1.0 | * | y | = | y' | - // | 0.0 | 0.0 | 0.0 | | 1 | | 0 | - // ------------------------------------------------ --------- --------- - Matrix3 projectionMatrix = { 2.0f/size.width(), 0.0f, -1.0f, - 0.0f, -2.0f/size.height(), 1.0f, - 0.0f, 0.0f, 0.0f }; - projectionMatrix.transpose(); - g_painter.setProjectionMatrix(projectionMatrix); + // Projection Matrix + // Painter Coord ------------------------------------------------ GL Coord + // ------------- | 2.0 / width | 0.0 | 0.0 | --------------- + // | x y 1 | * | 0.0 | -2.0 / height | 0.0 | = | x' y' 1 | + // ------------- | -1.0 | 1.0 | 1.0 | --------------- + // ------------------------------------------------ + Matrix3 projectionMatrix = { 2.0f/size.width(), 0.0f, 0.0f, + 0.0f, -2.0f/size.height(), 0.0f, + -1.0f, 1.0f, 1.0f }; + + if(g_painterOGL1) + g_painterOGL1->setProjectionMatrix(projectionMatrix); + + if(g_painterOGL2) + g_painterOGL2->setProjectionMatrix(projectionMatrix); } void Graphics::beginRender() @@ -149,16 +202,6 @@ void Graphics::beginRender() void Graphics::endRender() { - // this is a simple blur effect - /* - static Timer timer; - if(timer.ticksElapsed() >= 10) { - glAccum(GL_MULT, 0.9); - glAccum(GL_ACCUM, 0.1); - timer.restart(); - } - glAccum(GL_RETURN, 1); - */ } void Graphics::setViewportSize(const Size& size) @@ -167,10 +210,71 @@ void Graphics::setViewportSize(const Size& size) m_viewportSize = size; } -int Graphics::getMaxTextureSize() +bool Graphics::canUseDrawArrays() +{ +#ifndef OPENGL_ES2 + if(!GLEW_VERSION_1_1) + return false; +#else + return false; +#endif + return m_useDrawArrays; +} + +bool Graphics::canUseShaders() { - static GLint maxTexSize = -1; - if(maxTexSize == -1) - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); - return maxTexSize; +#ifndef OPENGL_ES2 + if(GLEW_ARB_vertex_program && GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader) + return true; +#else + return true; +#endif + return false; +} + +bool Graphics::canUseFBO() +{ +#ifndef OPENGL_ES2 + if(!GLEW_ARB_framebuffer_object || !GLEW_EXT_framebuffer_object) + return false; +#endif + return m_useFBO; +} + +bool Graphics::canUseBilinearFiltering() +{ + return m_useBilinearFiltering; +} + +bool Graphics::canUseHardwareBuffers() +{ +#ifndef OPENGL_ES2 + if(!GLEW_ARB_vertex_buffer_object) + return false; +#endif + return m_useHardwareBuffers; +} + +bool Graphics::canUseNonPowerOfTwoTextures() +{ +#ifndef OPENGL_ES2 + if(!GLEW_ARB_texture_non_power_of_two) + return false; +#endif + return m_useNonPowerOfTwoTextures; +} + +bool Graphics::canUseMipmaps() +{ + return m_useMipmaps; +} + +bool Graphics::canUseHardwareMipmaps() +{ +#ifndef OPENGL_ES2 + // glGenerateMipmap is supported when framebuffers are too + if(!GLEW_ARB_framebuffer_object || !GLEW_EXT_framebuffer_object) + return false; +#endif + return m_useHardwareMipmaps; } diff --git a/src/framework/graphics/graphics.h b/src/framework/graphics/graphics.h index 85e25934..b7ceb6fc 100644 --- a/src/framework/graphics/graphics.h +++ b/src/framework/graphics/graphics.h @@ -29,35 +29,53 @@ class Graphics { public: + Graphics(); + + enum PainterEngine { + Painter_Any, + Painter_OpenGL1, + Painter_OpenGL2 + }; + void init(); void terminate(); bool parseOption(const std::string& option); - bool canUseFBO() { return m_useFBO; } - bool canUseBilinearFiltering() { return m_useBilinearFiltering; } - bool canUseHardwareBuffers() { return m_useHardwareBuffers; } - bool canGenerateMipmaps() { return m_generateMipmaps; } - bool canGenerateHardwareMipmaps() { return m_generateHardwareMipmaps; } - + bool selectPainterEngine(PainterEngine painterEngine); + PainterEngine getPainterEngine(); + void resize(const Size& size); void beginRender(); void endRender(); void setViewportSize(const Size& size); - int getMaxTextureSize(); + int getMaxTextureSize() { return m_maxTextureSize; } const Size& getViewportSize() { return m_viewportSize; } TexturePtr& getEmptyTexture() { return m_emptyTexture; } + bool canUseDrawArrays(); + bool canUseShaders(); + bool canUseFBO(); + bool canUseBilinearFiltering(); + bool canUseHardwareBuffers(); + bool canUseNonPowerOfTwoTextures(); + bool canUseMipmaps(); + bool canUseHardwareMipmaps(); + private: Size m_viewportSize; TexturePtr m_emptyTexture; + int m_maxTextureSize; + Boolean m_useDrawArrays; Boolean m_useFBO; Boolean m_useHardwareBuffers; Boolean m_useBilinearFiltering; - Boolean m_generateMipmaps; - Boolean m_generateHardwareMipmaps; + Boolean m_useNonPowerOfTwoTextures; + Boolean m_useMipmaps; + Boolean m_useHardwareMipmaps; + PainterEngine m_prefferedPainterEngine; }; extern Graphics g_graphics; diff --git a/src/framework/graphics/hardwarebuffer.h b/src/framework/graphics/hardwarebuffer.h index 24f53f36..475abeb6 100644 --- a/src/framework/graphics/hardwarebuffer.h +++ b/src/framework/graphics/hardwarebuffer.h @@ -40,7 +40,7 @@ public: DynamicDraw = GL_DYNAMIC_DRAW }; - HardwareBuffer(Type type ) { + HardwareBuffer(Type type) { m_type = type; m_id = 0; glGenBuffers(1, &m_id); @@ -53,7 +53,6 @@ public: void bind() { glBindBuffer(m_type, m_id); } static void unbind(Type type) { glBindBuffer(type, 0); } void write(void *data, int count, UsagePattern usage) { glBufferData(m_type, count, data, usage); } - //void read(void *data, int count); private: Type m_type; diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp index 7dcf68c9..92054440 100644 --- a/src/framework/graphics/painter.cpp +++ b/src/framework/graphics/painter.cpp @@ -21,162 +21,132 @@ */ #include "painter.h" -#include "texture.h" -#include "paintershadersources.h" -#include "paintershaderprogram.h" -#include "shaderprogram.h" #include "graphics.h" -#include "vertexarray.h" -Painter g_painter; +Painter *g_painter = nullptr; -void Painter::init() +Painter::Painter() { - setColor(Color::white); - setOpacity(1.0f); - setCompositionMode(CompositionMode_Normal); - releaseCustomProgram(); - - m_drawTexturedProgram = PainterShaderProgramPtr(new PainterShaderProgram); - m_drawTexturedProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); - m_drawTexturedProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslTextureSrcFragmentShader); - m_drawTexturedProgram->link(); - - m_drawSolidColorProgram = PainterShaderProgramPtr(new PainterShaderProgram); - m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader + glslPositionOnlyVertexShader); - m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslSolidColorFragmentShader); - m_drawSolidColorProgram->link(); + m_glTextureId = 0; + m_oldStateIndex = 0; + m_color = Color::white; + m_opacity = 1.0f; + m_compositionMode = CompositionMode_Normal; + m_shaderProgram = nullptr; + m_texture = nullptr; } -void Painter::terminate() +void Painter::resetState() { - m_drawTexturedProgram.reset(); - m_drawSolidColorProgram.reset(); + resetColor(); + resetOpacity(); + resetCompositionMode(); + resetClipRect(); + resetShaderProgram(); + resetTexture(); } -void Painter::drawProgram(PainterShaderProgram *program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode) +void Painter::refreshState() { - if(coordsBuffer.getVertexCount() == 0) - return; + updateGlCompositionMode(); + updateGlClipRect(); + updateGlTexture(); +} - program->setProjectionMatrix(m_projectionMatrix); - program->setOpacity(m_opacity); - program->setColor(m_color); - program->draw(coordsBuffer, drawMode); +void Painter::saveAndResetState() +{ + assert(m_oldStateIndex<10); + m_olderStates[m_oldStateIndex].projectionMatrix = m_projectionMatrix; + m_olderStates[m_oldStateIndex].textureMatrix = m_textureMatrix; + m_olderStates[m_oldStateIndex].color = m_color; + m_olderStates[m_oldStateIndex].opacity = m_opacity; + m_olderStates[m_oldStateIndex].compositionMode = m_compositionMode; + m_olderStates[m_oldStateIndex].clipRect = m_clipRect; + m_olderStates[m_oldStateIndex].shaderProgram = m_shaderProgram; + m_olderStates[m_oldStateIndex].texture = m_texture; + m_oldStateIndex++; + resetState(); } -void Painter::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) +void Painter::restoreSavedState() { - PainterShaderProgram *program = m_customProgram ? m_customProgram : m_drawTexturedProgram.get(); - program->setTexture(texture); - drawProgram(program, coordsBuffer); + m_oldStateIndex--; + setProjectionMatrix(m_olderStates[m_oldStateIndex].projectionMatrix); + setTextureMatrix(m_olderStates[m_oldStateIndex].textureMatrix); + setColor(m_olderStates[m_oldStateIndex].color); + setOpacity(m_olderStates[m_oldStateIndex].opacity); + setCompositionMode(m_olderStates[m_oldStateIndex].compositionMode); + setClipRect(m_olderStates[m_oldStateIndex].clipRect); + setShaderProgram(m_olderStates[m_oldStateIndex].shaderProgram); + setTexture(m_olderStates[m_oldStateIndex].texture); } -void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +void Painter::setCompositionMode(Painter::CompositionMode compositionMode) { - if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + if(m_compositionMode == compositionMode) return; - - m_coordsBuffer.clear(); - m_coordsBuffer.addQuad(dest, src); - PainterShaderProgram *program = m_customProgram ? m_customProgram : m_drawTexturedProgram.get(); - program->setTexture(texture); - drawProgram(program, m_coordsBuffer, PainterShaderProgram::TriangleStrip); + m_compositionMode = compositionMode; + updateGlCompositionMode(); } -void Painter::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +void Painter::setClipRect(const Rect& clipRect) { - if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + if(m_clipRect == clipRect) return; - - m_coordsBuffer.clear(); - m_coordsBuffer.addRepeatedRects(dest, src); - drawTextureCoords(m_coordsBuffer, texture); + m_clipRect = clipRect; + updateGlClipRect(); } -void Painter::drawFilledRect(const Rect& dest) +void Painter::setTexture(Texture* texture) { - if(dest.isEmpty()) + if(m_texture == texture) return; - m_coordsBuffer.clear(); - m_coordsBuffer.addRect(dest); - drawProgram(m_customProgram ? m_customProgram : m_drawSolidColorProgram.get(), m_coordsBuffer); + m_texture = texture; + + if(texture) { + m_glTextureId = texture->getId(); + setTextureMatrix(texture->getTransformMatrix()); + } else + m_glTextureId = 0; + m_texture = texture; + + updateGlTexture(); } -void Painter::drawBoundingRect(const Rect& dest, int innerLineWidth) +void Painter::updateGlTexture() { - if(dest.isEmpty() || innerLineWidth == 0) - return; - - m_coordsBuffer.clear(); - m_coordsBuffer.addBoudingRect(dest, innerLineWidth); - drawProgram(m_customProgram ? m_customProgram : m_drawSolidColorProgram.get(), m_coordsBuffer); + glBindTexture(GL_TEXTURE_2D, m_glTextureId); } -void Painter::setCompositionMode(Painter::CompositionMode compositionMode) +void Painter::updateGlCompositionMode() { - switch(compositionMode) { - case CompositionMode_Normal: - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - break; - case CompositionMode_Multiply: - glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); - break; - case CompositionMode_Add: - glBlendFunc(GL_ONE, GL_ONE); - break; - case CompositionMode_Replace: - glBlendFunc(GL_ONE, GL_ZERO); - break; - case CompositionMode_DestBlending: - glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); - break; + glEnable(GL_BLEND); + switch(m_compositionMode) { + case CompositionMode_Normal: + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + case CompositionMode_Multiply: + glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); + break; + case CompositionMode_Add: + glBlendFunc(GL_ONE, GL_ONE); + break; + case CompositionMode_Replace: + glBlendFunc(GL_ONE, GL_ZERO); + break; + case CompositionMode_DestBlending: + glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); + break; } - m_compostionMode = compositionMode; } -void Painter::setClipRect(const Rect& clipRect) +void Painter::updateGlClipRect() { - if(m_clipRect == clipRect) - return; - - if(clipRect.isValid()) { + if(m_clipRect.isValid()) { glEnable(GL_SCISSOR_TEST); - glScissor(clipRect.left(), g_graphics.getViewportSize().height() - clipRect.bottom() - 1, clipRect.width(), clipRect.height()); + glScissor(m_clipRect.left(), g_graphics.getViewportSize().height() - m_clipRect.bottom() - 1, m_clipRect.width(), m_clipRect.height()); } else { glDisable(GL_SCISSOR_TEST); } - m_clipRect = clipRect; -} - -void Painter::saveAndResetState() -{ - m_oldCustomProgram = m_customProgram; - m_oldProjectionMatrix = m_projectionMatrix; - m_oldColor = m_color; - m_oldOpacity = m_opacity; - m_oldCompostionMode = m_compostionMode; - m_oldClipRect = m_clipRect; - - releaseCustomProgram(); - resetClipRect(); - setColor(Color::white); - setOpacity(1); - setCompositionMode(CompositionMode_Normal); -} - -void Painter::restoreSavedState() -{ - m_customProgram = m_oldCustomProgram; - setColor(m_oldColor); - setOpacity(m_oldOpacity); - setCompositionMode(m_oldCompostionMode); - setClipRect(m_oldClipRect); - - m_oldCustomProgram = nullptr; - m_oldColor = Color::white; - m_oldOpacity = 1; - m_oldCompostionMode = CompositionMode_Normal; - m_oldClipRect = Rect(); } diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h index 0ceb0133..c2991a33 100644 --- a/src/framework/graphics/painter.h +++ b/src/framework/graphics/painter.h @@ -24,7 +24,6 @@ #define PAINTER_H #include "declarations.h" -#include #include "coordsbuffer.h" #include "paintershaderprogram.h" #include "texture.h" @@ -39,58 +38,90 @@ public: CompositionMode_Replace, CompositionMode_DestBlending }; + enum DrawMode { + Triangles = GL_TRIANGLES, + TriangleStrip = GL_TRIANGLE_STRIP + }; + + struct PainterState { + Matrix3 projectionMatrix; + Matrix2 textureMatrix; + Color color; + float opacity; + Painter::CompositionMode compositionMode; + Rect clipRect; + Texture *texture; + PainterShaderProgram *shaderProgram; + }; + + Painter(); + virtual ~Painter() { } + + virtual void bind() { refreshState(); } + virtual void unbind() { } - void init(); - void terminate(); + void resetState(); + virtual void refreshState(); + void saveAndResetState(); + void restoreSavedState(); - void drawProgram(PainterShaderProgram *program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode = PainterShaderProgram::Triangles); - void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); - void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + virtual void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles) = 0; + virtual void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) = 0; + virtual void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0; void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); } - void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); - void drawFilledRect(const Rect& dest); - void drawBoundingRect(const Rect& dest, int innerLineWidth = 1); + virtual void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0; + virtual void drawFilledRect(const Rect& dest) = 0; + virtual void drawBoundingRect(const Rect& dest, int innerLineWidth = 1) = 0; - void setColor(const Color& color) { m_color = color; } - Color getColor() { return m_color; } + virtual void setProjectionMatrix(const Matrix3& projectionMatrix) { m_projectionMatrix = projectionMatrix; } + virtual void setTextureMatrix(const Matrix2& textureMatrix) { m_textureMatrix = textureMatrix; } + virtual void setColor(const Color& color) { m_color = color; } + virtual void setOpacity(float opacity) { m_opacity = opacity; } + virtual void setCompositionMode(CompositionMode compositionMode); + virtual void setClipRect(const Rect& clipRect); + virtual void setShaderProgram(PainterShaderProgram *shaderProgram) { m_shaderProgram = shaderProgram; } + virtual void setTexture(Texture *texture); - void setOpacity(float opacity) { m_opacity = opacity; } - float getOpacity() { return m_opacity; } + void setShaderProgram(const PainterShaderProgramPtr& shaderProgram) { setShaderProgram(shaderProgram.get()); } + void setTexture(const TexturePtr& texture) { setTexture(texture.get()); } - void setClipRect(const Rect& clipRect); + Matrix3 getProjectionMatrix() { return m_projectionMatrix; } + Matrix2 getTextureMatrix() { return m_textureMatrix; } + Color getColor() { return m_color; } + float getOpacity() { return m_opacity; } + CompositionMode getCompositionMode() { return m_compositionMode; } Rect getClipRect() { return m_clipRect; } - void resetClipRect() { setClipRect(Rect()); } + PainterShaderProgram *getShaderProgram() { return m_shaderProgram; } - void setCustomProgram(const PainterShaderProgramPtr& program) { m_customProgram = program.get(); } - void releaseCustomProgram() { m_customProgram = nullptr; } - void setCompositionMode(CompositionMode compositionMode); + void resetColor() { setColor(Color::white); } + void resetOpacity() { setOpacity(1.0f); } + void resetClipRect() { setClipRect(Rect()); } void resetCompositionMode() { setCompositionMode(CompositionMode_Normal); } + void resetShaderProgram() { setShaderProgram(nullptr); } + void resetTexture() { setTexture(nullptr); } - void setProjectionMatrix(const Matrix3& projectionMatrix) { m_projectionMatrix = projectionMatrix; } - Matrix3 getProjectionMatrix() { return m_projectionMatrix; } +protected: + void updateGlTexture(); + void updateGlCompositionMode(); + void updateGlClipRect(); - void saveAndResetState(); - void restoreSavedState(); + CoordsBuffer m_coordsBuffer; -private: - PainterShaderProgramPtr m_drawTexturedProgram; - PainterShaderProgramPtr m_drawSolidColorProgram; - PainterShaderProgram *m_customProgram; Matrix3 m_projectionMatrix; + Matrix2 m_textureMatrix; Color m_color; float m_opacity; - CompositionMode m_compostionMode; - CoordsBuffer m_coordsBuffer; + CompositionMode m_compositionMode; Rect m_clipRect; + Texture *m_texture; + PainterShaderProgram *m_shaderProgram; + + PainterState m_olderStates[10]; + int m_oldStateIndex; - PainterShaderProgram *m_oldCustomProgram; - Matrix3 m_oldProjectionMatrix; - Color m_oldColor; - float m_oldOpacity; - Rect m_oldClipRect; - CompositionMode m_oldCompostionMode; + GLuint m_glTextureId; }; -extern Painter g_painter; +extern Painter *g_painter; #endif diff --git a/src/framework/graphics/painterogl1.cpp b/src/framework/graphics/painterogl1.cpp new file mode 100644 index 00000000..6c3b9fc2 --- /dev/null +++ b/src/framework/graphics/painterogl1.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "painterogl1.h" +#include "graphics.h" + +PainterOGL1 *g_painterOGL1 = nullptr; + +PainterOGL1::PainterOGL1() +{ + m_matrixMode = GL_PROJECTION; + resetState(); +} + +void PainterOGL1::refreshState() +{ + Painter::refreshState(); + updateGlColor(); + updateGlMatrixMode(); + updateGlProjectionMatrix(); + updateGlTextureMatrix(); +} + +void PainterOGL1::bind() +{ + Painter::bind(); + + // vertex and texture coord arrays are always enabled + // to avoid massive enable/disables, thus improving frame rate + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); +} + +void PainterOGL1::unbind() +{ + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode) +{ + int vertexCount = coordsBuffer.getVertexCount(); + if(vertexCount == 0) + return; + + bool textured = coordsBuffer.getTextureCoordCount() != 0; + if(textured) + glEnable(GL_TEXTURE_2D); + else + glDisable(GL_TEXTURE_2D); + + // use vertex arrays if possible, much faster + if(g_graphics.canUseDrawArrays()) { + // update coords buffer hardware caches if enabled + coordsBuffer.updateCaches(); + bool hardwareCached = coordsBuffer.isHardwareCached(); + + // only set texture coords arrays when needed + if(textured) { + if(hardwareCached) { + coordsBuffer.getHardwareTextureCoordArray()->bind(); + glTexCoordPointer(2, GL_FLOAT, 0, nullptr); + } else + glTexCoordPointer(2, GL_FLOAT, 0, coordsBuffer.getTextureCoordArray()); + } + + // set vertex array + if(hardwareCached) { + coordsBuffer.getHardwareVertexArray()->bind(); + glVertexPointer(2, GL_FLOAT, 0, nullptr); + } else + glVertexPointer(2, GL_FLOAT, 0, coordsBuffer.getVertexArray()); + + if(hardwareCached) + HardwareBuffer::unbind(HardwareBuffer::VertexBuffer); + + // draw the element in coords buffers + glDrawArrays(drawMode, 0, vertexCount); + } else { + int verticesSize = vertexCount*2; + float *vertices = coordsBuffer.getVertexArray(); + float *texCoords = coordsBuffer.getTextureCoordArray(); + + // use glBegin/glEnd, this is not available in OpenGL ES + // and is considered much slower then glDrawArrays, + // but this code is executed in really old graphics cards + glBegin(drawMode); + for(int i=0;igetId()) + return; + + setTexture(texture.get()); + drawCoords(coordsBuffer); +} + +void PainterOGL1::drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addQuad(dest, src); + + setTexture(texture.get()); + drawCoords(m_coordsBuffer, TriangleStrip); +} + +void PainterOGL1::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addRepeatedRects(dest, src); + + setTexture(texture.get()); + drawCoords(m_coordsBuffer); +} + +void PainterOGL1::drawFilledRect(const Rect& dest) +{ + if(dest.isEmpty()) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addRect(dest); + + setTexture(nullptr); + drawCoords(m_coordsBuffer); +} + +void PainterOGL1::drawBoundingRect(const Rect& dest, int innerLineWidth) +{ + if(dest.isEmpty() || innerLineWidth == 0) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addBoudingRect(dest, innerLineWidth); + + setTexture(nullptr); + drawCoords(m_coordsBuffer); +} + +void PainterOGL1::setMatrixMode(PainterOGL1::MatrixMode matrixMode) +{ + if(m_matrixMode == matrixMode) + return; + m_matrixMode = matrixMode; + updateGlMatrixMode(); +} + +void PainterOGL1::setProjectionMatrix(const Matrix3& projectionMatrix) +{ + m_projectionMatrix = projectionMatrix; + updateGlProjectionMatrix(); +} + +void PainterOGL1::setTextureMatrix(const Matrix2& textureMatrix) +{ + m_textureMatrix = textureMatrix; + updateGlTextureMatrix(); +} + +void PainterOGL1::setColor(const Color& color) +{ + if(m_color == color) + return; + m_color = color; + updateGlColor(); +} + +void PainterOGL1::setOpacity(float opacity) +{ + if(m_opacity == opacity) + return; + m_opacity = opacity; + updateGlColor(); +} + +void PainterOGL1::updateGlColor() +{ + glColor4f(m_color.rF(), m_color.gF(), m_color.bF(), m_color.aF() * m_opacity); +} + +void PainterOGL1::updateGlMatrixMode() +{ + glMatrixMode(m_matrixMode); +} + +void PainterOGL1::updateGlProjectionMatrix() +{ + float glProjectionMatrix[] = { + m_projectionMatrix(1,1), m_projectionMatrix(1,2), 0.0f, m_projectionMatrix(1,3), + m_projectionMatrix(2,1), m_projectionMatrix(2,2), 0.0f, m_projectionMatrix(2,3), + 0.0f, 0.0f, 1.0f, 0.0f, + m_projectionMatrix(3,1), m_projectionMatrix(3,2), 0.0f, m_projectionMatrix(3,3), + }; + + setMatrixMode(MatrixProjection); + glLoadMatrixf(glProjectionMatrix); +} + +void PainterOGL1::updateGlTextureMatrix() +{ + float glTextureMatrix[] = { + m_textureMatrix(1,1), m_textureMatrix(1,2), 0.0f, 0.0f, + m_textureMatrix(2,1), m_textureMatrix(2,2), 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }; + + setMatrixMode(MatrixTexture); + glLoadMatrixf(glTextureMatrix); +} diff --git a/src/framework/graphics/painterogl1.h b/src/framework/graphics/painterogl1.h new file mode 100644 index 00000000..eb98282d --- /dev/null +++ b/src/framework/graphics/painterogl1.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PAINTEROGL1_H +#define PAINTEROGL1_H + +#include "painter.h" + +/** + * Painter using OpenGL 1.0 fixed-function rendering pipeline, + * compatible with OpenGL ES 1.0 and intended to be used on + * older graphics cards. Shaders are not available + * for this painter engine. + */ +class PainterOGL1 : public Painter +{ +public: + enum MatrixMode { + MatrixProjection = GL_PROJECTION, + MatrixTexture = GL_TEXTURE + }; + + PainterOGL1(); + + void bind(); + void unbind(); + + void refreshState(); + + void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); + void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); + void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawFilledRect(const Rect& dest); + void drawBoundingRect(const Rect& dest, int innerLineWidth); + + void setMatrixMode(MatrixMode matrixMode); + void setProjectionMatrix(const Matrix3& projectionMatrix); + void setTextureMatrix(const Matrix2& textureMatrix); + void setColor(const Color& color); + void setOpacity(float opacity); + +private: + void updateGlColor(); + void updateGlMatrixMode(); + void updateGlProjectionMatrix(); + void updateGlTextureMatrix(); + + GLenum m_matrixMode; +}; + +extern PainterOGL1 *g_painterOGL1; + +#endif diff --git a/src/framework/graphics/painterogl2.cpp b/src/framework/graphics/painterogl2.cpp new file mode 100644 index 00000000..33a68a49 --- /dev/null +++ b/src/framework/graphics/painterogl2.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "painterogl2.h" +#include "texture.h" +#include "paintershadermanager.h" + +PainterOGL2 *g_painterOGL2 = nullptr; + +PainterOGL2::PainterOGL2() +{ + m_drawProgram = nullptr; + resetState(); + + g_shaders.init(); +} + +PainterOGL2::~PainterOGL2() +{ + g_shaders.terminate(); +} + +void PainterOGL2::bind() +{ + Painter::bind(); + + // vertex and texture coord attributes are always enabled + // to avoid massive enable/disables, thus improving frame rate + PainterShaderProgram::enableAttributeArray(PainterShaderProgram::VERTEX_ATTR); + PainterShaderProgram::enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR); +} + +void PainterOGL2::unbind() +{ + PainterShaderProgram::disableAttributeArray(PainterShaderProgram::VERTEX_ATTR); + PainterShaderProgram::disableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR); + PainterShaderProgram::release(); +} + +void PainterOGL2::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode) +{ + int vertexCount = coordsBuffer.getVertexCount(); + if(vertexCount == 0) + return; + + bool textured = coordsBuffer.getTextureCoordCount() > 0; + + // update shader with the current painter state + m_drawProgram->bind(); + m_drawProgram->setProjectionMatrix(m_projectionMatrix); + if(textured) + m_drawProgram->setTextureMatrix(m_textureMatrix); + m_drawProgram->setOpacity(m_opacity); + m_drawProgram->setColor(m_color); + m_drawProgram->updateTime(); + + // update coords buffer hardware caches if enabled + coordsBuffer.updateCaches(); + bool hardwareCached = coordsBuffer.isHardwareCached(); + + // only set texture coords arrays when needed + if(textured) { + if(hardwareCached) { + coordsBuffer.getHardwareTextureCoordArray()->bind(); + m_drawProgram->setAttributeArray(PainterShaderProgram::TEXCOORD_ATTR, nullptr, 2); + } else + m_drawProgram->setAttributeArray(PainterShaderProgram::TEXCOORD_ATTR, coordsBuffer.getTextureCoordArray(), 2); + } + + // set vertex array + if(hardwareCached) { + coordsBuffer.getHardwareVertexArray()->bind(); + m_drawProgram->setAttributeArray(PainterShaderProgram::VERTEX_ATTR, nullptr, 2); + HardwareBuffer::unbind(HardwareBuffer::VertexBuffer); + } else + m_drawProgram->setAttributeArray(PainterShaderProgram::VERTEX_ATTR, coordsBuffer.getVertexArray(), 2); + + // draw the element in coords buffers + glDrawArrays(drawMode, 0, vertexCount); +} + +void PainterOGL2::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) +{ + if(!texture->getId()) + return; + + setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawTexturedProgram().get()); + setTexture(texture); + drawCoords(coordsBuffer); +} + +void PainterOGL2::drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addQuad(dest, src); + + setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawTexturedProgram().get()); + setTexture(texture); + drawCoords(m_coordsBuffer, TriangleStrip); +} + +void PainterOGL2::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addRepeatedRects(dest, src); + + setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawTexturedProgram().get()); + setTexture(texture); + drawCoords(m_coordsBuffer); +} + +void PainterOGL2::drawFilledRect(const Rect& dest) +{ + if(dest.isEmpty()) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addRect(dest); + + setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawSolidColorProgram().get()); + drawCoords(m_coordsBuffer); +} + +void PainterOGL2::drawBoundingRect(const Rect& dest, int innerLineWidth) +{ + if(dest.isEmpty() || innerLineWidth == 0) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addBoudingRect(dest, innerLineWidth); + + setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawSolidColorProgram().get()); + drawCoords(m_coordsBuffer); +} diff --git a/src/framework/graphics/painterogl2.h b/src/framework/graphics/painterogl2.h new file mode 100644 index 00000000..dddc0778 --- /dev/null +++ b/src/framework/graphics/painterogl2.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PAINTEROGL2_H +#define PAINTEROGL2_H + +#include "painter.h" + +/** + * Painter using OpenGL 2.0 programmable rendering pipeline, + * compatible with OpenGL ES 2.0. Only recent cards support + * this painter engine. + */ +class PainterOGL2 : public Painter +{ +public: + PainterOGL2(); + ~PainterOGL2(); + + void bind(); + void unbind(); + + void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); + void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); + void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawFilledRect(const Rect& dest); + void drawBoundingRect(const Rect& dest, int innerLineWidth = 1); + + void setDrawProgram(PainterShaderProgram *drawProgram) { m_drawProgram = drawProgram; } + +private: + PainterShaderProgram *m_drawProgram; +}; + +extern PainterOGL2 *g_painterOGL2; + +#endif diff --git a/src/framework/graphics/painterogl2_shadersources.h b/src/framework/graphics/painterogl2_shadersources.h new file mode 100644 index 00000000..c9102ce3 --- /dev/null +++ b/src/framework/graphics/painterogl2_shadersources.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +static const std::string glslMainVertexShader = "\n\ + highp vec4 calculatePosition();\n\ + void main() {\n\ + gl_Position = calculatePosition();\n\ + }\n"; + +static const std::string glslMainWithTexCoordsVertexShader = "\n\ + attribute highp vec2 a_texCoord;\n\ + uniform highp mat2 textureMatrix;\n\ + varying highp vec2 texCoord;\n\ + highp vec4 calculatePosition();\n\ + void main()\n\ + {\n\ + gl_Position = calculatePosition();\n\ + texCoord = textureMatrix * a_texCoord;\n\ + }\n"; + +static std::string glslPositionOnlyVertexShader = "\n\ + attribute highp vec2 a_vertex;\n\ + uniform highp mat3 projectionMatrix;\n\ + highp vec4 calculatePosition() {\n\ + return vec4(projectionMatrix * vec3(a_vertex.xy, 1), 1);\n\ + }\n"; + +static const std::string glslMainFragmentShader = "\n\ + uniform lowp float opacity;\n\ + lowp vec4 calculatePixel();\n\ + void main()\n\ + {\n\ + gl_FragColor = calculatePixel();\n\ + gl_FragColor.a *= opacity;\n\ + }\n"; + +static const std::string glslTextureSrcFragmentShader = "\n\ + varying mediump vec2 texCoord;\n\ + uniform lowp vec4 color;\n\ + uniform sampler2D tex0;\n\ + lowp vec4 calculatePixel() {\n\ + return texture2D(tex0, texCoord) * color;\n\ + }\n"; + +static const std::string glslSolidColorFragmentShader = "\n\ + uniform lowp vec4 color;\n\ + lowp vec4 calculatePixel() {\n\ + return color;\n\ + }\n"; diff --git a/src/framework/graphics/paintershadermanager.cpp b/src/framework/graphics/paintershadermanager.cpp new file mode 100644 index 00000000..1c69f991 --- /dev/null +++ b/src/framework/graphics/paintershadermanager.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "paintershadermanager.h" +#include "painterogl2.h" +#include "texture.h" +#include "painterogl2_shadersources.h" +#include "paintershaderprogram.h" +#include "shaderprogram.h" +#include "graphics.h" + +PainterShaderManager g_shaders; + +void PainterShaderManager::init() +{ + m_drawTexturedProgram = createShader(); + assert(m_drawTexturedProgram); + m_drawTexturedProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + m_drawTexturedProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslTextureSrcFragmentShader); + m_drawTexturedProgram->link(); + + m_drawSolidColorProgram = createShader(); + assert(m_drawSolidColorProgram); + m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader + glslPositionOnlyVertexShader); + m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslSolidColorFragmentShader); + m_drawSolidColorProgram->link(); +} + +void PainterShaderManager::terminate() +{ + m_drawTexturedProgram = nullptr; + m_drawSolidColorProgram = nullptr; +} + +PainterShaderProgramPtr PainterShaderManager::createShader() +{ + if(!g_graphics.canUseShaders()) + return nullptr; + return PainterShaderProgramPtr(new PainterShaderProgram); +} + +PainterShaderProgramPtr PainterShaderManager::createTexturedFragmentShader(const std::string& shaderFile) +{ + PainterShaderProgramPtr shader = createShader(); + if(!shader) + return nullptr; + + shader->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + shader->addShaderFromSourceFile(Shader::Fragment, shaderFile); + + if(!shader->link()) + return nullptr; + + return shader; +} diff --git a/src/framework/graphics/paintershadermanager.h b/src/framework/graphics/paintershadermanager.h new file mode 100644 index 00000000..5b011263 --- /dev/null +++ b/src/framework/graphics/paintershadermanager.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#ifndef PAINTERSHADERMANAGER_H +#define PAINTERSHADERMANAGER_H + +#include "paintershaderprogram.h" + +class PainterShaderManager +{ +public: + void init(); + void terminate(); + + PainterShaderProgramPtr createShader(); + PainterShaderProgramPtr createTexturedFragmentShader(const std::string& shaderFile); + + const PainterShaderProgramPtr& getDrawTexturedProgram() { return m_drawTexturedProgram; } + const PainterShaderProgramPtr& getDrawSolidColorProgram() { return m_drawSolidColorProgram; } + +private: + PainterShaderProgramPtr m_drawTexturedProgram; + PainterShaderProgramPtr m_drawSolidColorProgram; +}; + +extern PainterShaderManager g_shaders; + +#endif diff --git a/src/framework/graphics/paintershaderprogram.cpp b/src/framework/graphics/paintershaderprogram.cpp index f5e7b857..dd5bd135 100644 --- a/src/framework/graphics/paintershaderprogram.cpp +++ b/src/framework/graphics/paintershaderprogram.cpp @@ -32,8 +32,6 @@ PainterShaderProgram::PainterShaderProgram() m_opacity = 1; m_color = Color::white; m_time = 0; - m_lastTexture = -1; - m_textures.fill(0); } bool PainterShaderProgram::link() @@ -43,7 +41,7 @@ bool PainterShaderProgram::link() bindAttributeLocation(TEXCOORD_ATTR, "a_texCoord"); if(ShaderProgram::link()) { bindUniformLocation(PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); - bindUniformLocation(TEXTURE_TRANSFORM_MATRIX_UNIFORM, "texTransformMatrix"); + bindUniformLocation(TEXTURE_MATRIX_UNIFORM, "textureMatrix"); bindUniformLocation(COLOR_UNIFORM, "color"); bindUniformLocation(OPACITY_UNIFORM, "opacity"); bindUniformLocation(TIME_UNIFORM, "time"); @@ -52,15 +50,13 @@ bool PainterShaderProgram::link() bind(); setUniformValue(PROJECTION_MATRIX_UNIFORM, m_projectionMatrix); - setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, m_textureTransformMatrix); + setUniformValue(TEXTURE_MATRIX_UNIFORM, m_textureMatrix); setUniformValue(COLOR_UNIFORM, m_color); setUniformValue(OPACITY_UNIFORM, m_opacity); setUniformValue(TIME_UNIFORM, m_time); setUniformValue(TEX0_UNIFORM, 0); setUniformValue(TEX1_UNIFORM, 1); - - enableAttributeArray(PainterShaderProgram::VERTEX_ATTR); - enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR); + release(); return true; } return false; @@ -76,6 +72,16 @@ void PainterShaderProgram::setProjectionMatrix(const Matrix3& projectionMatrix) m_projectionMatrix = projectionMatrix; } +void PainterShaderProgram::setTextureMatrix(const Matrix2& textureMatrix) +{ + if(textureMatrix == m_textureMatrix) + return; + + bind(); + setUniformValue(TEXTURE_MATRIX_UNIFORM, textureMatrix); + m_textureMatrix = textureMatrix; +} + void PainterShaderProgram::setColor(const Color& color) { if(color == m_color) @@ -96,68 +102,13 @@ void PainterShaderProgram::setOpacity(float opacity) m_opacity = opacity; } -void PainterShaderProgram::setTexture(const TexturePtr& texture, int index) +void PainterShaderProgram::updateTime() { - assert(index >= 0 && index <= 1); - - uint texId = texture ? texture->getId() : 0; - - if(m_textures[index] == texId) - return; - - m_textures[index] = texId; - m_lastTexture = std::max(m_lastTexture, index); - - if(texture && index == 0) { - const Matrix2& textureTransformMatrix = texture->getTransformMatrix(); - if(m_textureTransformMatrix != textureTransformMatrix) { - bind(); - setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix); - m_textureTransformMatrix = textureTransformMatrix; - } - } -} - -void PainterShaderProgram::draw(CoordsBuffer& coordsBuffer, DrawMode drawMode) -{ - bind(); - float time = g_clock.timeElapsed(m_startTime); - if(m_time != time) { - setUniformValue(TIME_UNIFORM, time); - m_time = time; - } - - int vertexCount = coordsBuffer.getVertexCount(); - if(vertexCount == 0) + if(m_time == time) return; - coordsBuffer.updateCaches(); - bool hardwareCached = coordsBuffer.isHardwareCached(); - - if(hardwareCached) - coordsBuffer.getHardwareVertexBuffer()->bind(); - setAttributeArray(PainterShaderProgram::VERTEX_ATTR, hardwareCached ? 0 : coordsBuffer.getVertexBuffer(), 2); - - bool hasTexture = coordsBuffer.getTextureVertexCount() != 0; - if(hasTexture) { - if(hardwareCached) - coordsBuffer.getHardwareTextureVertexBuffer()->bind(); - setAttributeArray(PainterShaderProgram::TEXCOORD_ATTR, hardwareCached ? 0 : coordsBuffer.getTextureVertexBuffer(), 2); - } - - if(hardwareCached) - HardwareBuffer::unbind(HardwareBuffer::VertexBuffer); - - if(m_lastTexture == 0) { - glBindTexture(GL_TEXTURE_2D, m_textures[0]); - } else { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, m_textures[1]); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_textures[0]); - } - - glDrawArrays(drawMode, 0, vertexCount); + bind(); + setUniformValue(TIME_UNIFORM, time); + m_time = time; } - diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h index fff052aa..ccf2d3fd 100644 --- a/src/framework/graphics/paintershaderprogram.h +++ b/src/framework/graphics/paintershaderprogram.h @@ -29,11 +29,12 @@ class PainterShaderProgram : public ShaderProgram { +protected: enum { VERTEX_ATTR = 0, TEXCOORD_ATTR = 1, PROJECTION_MATRIX_UNIFORM = 0, - TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1, + TEXTURE_MATRIX_UNIFORM = 1, COLOR_UNIFORM = 2, OPACITY_UNIFORM = 3, TIME_UNIFORM = 4, @@ -42,34 +43,28 @@ class PainterShaderProgram : public ShaderProgram //TEX2_UNIFORM = 7, //TEX3_UNIFORM = 8, }; -public: - enum DrawMode { - Triangles = GL_TRIANGLES, - TriangleStrip = GL_TRIANGLE_STRIP - }; + friend class PainterOGL2; + +public: PainterShaderProgram(); bool link(); void setProjectionMatrix(const Matrix3& projectionMatrix); + void setTextureMatrix(const Matrix2& textureMatrix); void setColor(const Color& color); void setOpacity(float opacity); - void setTexture(const TexturePtr& texture, int index = 0); - void setUniformTexture(int location, const TexturePtr& texture, int index); - void draw(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); + void updateTime(); private: - DrawMode m_drawMode; float m_startTime; - std::array m_textures; Color m_color; float m_opacity; Matrix3 m_projectionMatrix; - Matrix2 m_textureTransformMatrix; + Matrix2 m_textureMatrix; float m_time; - int m_lastTexture; }; #endif diff --git a/src/framework/graphics/particle.cpp b/src/framework/graphics/particle.cpp index 5d82cde3..4f1bfa13 100644 --- a/src/framework/graphics/particle.cpp +++ b/src/framework/graphics/particle.cpp @@ -45,14 +45,14 @@ Particle::Particle(const Point& pos, const Size& startSize, const Size& finalSiz void Particle::render() { - g_painter.setColor(m_color); + g_painter->setColor(m_color); if(!m_texture) - g_painter.drawFilledRect(m_rect); + g_painter->drawFilledRect(m_rect); else { - g_painter.setCompositionMode(m_compositionMode); - g_painter.drawTexturedRect(m_rect, m_texture); - g_painter.setCompositionMode(Painter::CompositionMode_Normal); + g_painter->setCompositionMode(m_compositionMode); + g_painter->drawTexturedRect(m_rect, m_texture); + g_painter->setCompositionMode(Painter::CompositionMode_Normal); } } diff --git a/src/framework/graphics/shaderprogram.h b/src/framework/graphics/shaderprogram.h index 7a991caa..31976820 100644 --- a/src/framework/graphics/shaderprogram.h +++ b/src/framework/graphics/shaderprogram.h @@ -44,8 +44,8 @@ public: static void release(); std::string log(); - void disableAttributeArray(int location) { glDisableVertexAttribArray(location); } - void enableAttributeArray(int location) { glEnableVertexAttribArray(location); } + static void disableAttributeArray(int location) { glDisableVertexAttribArray(location); } + static void enableAttributeArray(int location) { glEnableVertexAttribArray(location); } void disableAttributeArray(const char *name) { glDisableVertexAttribArray(getAttributeLocation(name)); } void enableAttributeArray(const char *name) { glEnableVertexAttribArray(getAttributeLocation(name)); } diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index 602fc0ec..12a5c455 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -99,20 +99,23 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int void Texture::generateMipmaps() { - if(g_graphics.canGenerateHardwareMipmaps()) - generateHardwareMipmaps(); - else { + if(!generateHardwareMipmaps()) { // fallback to software mipmaps generation, this can be slow - //FIXME: disable because mipmaps size needs to be in base of 2, + //FIXME: disabled because mipmaps size needs to be in base of 2, // and the current algorithmn does not support that //generateSoftwareMipmaps(getPixels()); } } -void Texture::generateHardwareMipmaps() +bool Texture::generateHardwareMipmaps() { - if(!g_graphics.canGenerateHardwareMipmaps()) - return; + if(!g_graphics.canUseHardwareMipmaps()) + return false; + +#ifndef OPENGL_ES2 + if(!GLEW_ARB_framebuffer_object) + return false; +#endif bind(); @@ -122,6 +125,7 @@ void Texture::generateHardwareMipmaps() } glGenerateMipmap(GL_TEXTURE_2D); + return true; } void Texture::setSmooth(bool smooth) @@ -146,10 +150,10 @@ std::vector Texture::getPixels() FrameBufferPtr fb(new FrameBuffer(m_size)); fb->bind(); fb->clear(Color::alpha); - g_painter.saveAndResetState(); - g_painter.drawTexturedRect(Rect(0,0,m_size), shared_from_this()); + g_painter->saveAndResetState(); + g_painter->drawTexturedRect(Rect(0,0,m_size), shared_from_this()); glReadPixels(0, 0, m_size.width(), m_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); - g_painter.restoreSavedState(); + g_painter->restoreSavedState(); fb->release(); #else // copy pixels from opengl memory diff --git a/src/framework/graphics/texture.h b/src/framework/graphics/texture.h index abb93f99..391df007 100644 --- a/src/framework/graphics/texture.h +++ b/src/framework/graphics/texture.h @@ -36,15 +36,16 @@ public: /// Tries to generate mipmaps via hardware, otherwise fallback to software implementation void generateMipmaps(); - /// Generate mipmaps via hardware - void generateHardwareMipmaps(); + /// Generate mipmaps via hardware if supported + bool generateHardwareMipmaps(); /// Generate mipmaps via software, which has a special algorithm for combining alpha pixels void generateSoftwareMipmaps(std::vector inPixels); - /// Activate texture altialising + /// Activate texture anti-aliasing giving a better look when they are resized void setSmooth(bool smooth); GLuint getId() { return m_textureId; } + /// Return actual texture pixels std::vector getPixels(); int getWidth() { return m_size.width(); } diff --git a/src/framework/ui/uiframecounter.cpp b/src/framework/ui/uiframecounter.cpp index 390008a3..5860883e 100644 --- a/src/framework/ui/uiframecounter.cpp +++ b/src/framework/ui/uiframecounter.cpp @@ -47,7 +47,7 @@ void UIFrameCounter::drawSelf() } m_frameCount++; - g_painter.setColor(Color::white); + g_painter->setColor(Color::white); m_font->drawText(m_fpsText, m_rect, m_align); } diff --git a/src/framework/ui/uitextedit.cpp b/src/framework/ui/uitextedit.cpp index 220d2741..8a200d14 100644 --- a/src/framework/ui/uitextedit.cpp +++ b/src/framework/ui/uitextedit.cpp @@ -53,9 +53,9 @@ void UITextEdit::drawSelf() int textLength = m_text.length(); const TexturePtr& texture = m_font->getTexture(); - g_painter.setColor(m_color); + g_painter->setColor(m_color); for(int i=0;idrawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]); // render cursor if(isExplicitlyEnabled() && (isActive() || m_alwaysActive) && m_cursorPos >= 0) { @@ -69,7 +69,7 @@ void UITextEdit::drawSelf() cursorRect = Rect(m_drawArea.left()-1, m_drawArea.top(), 1, m_font->getGlyphHeight()); else cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight()); - g_painter.drawFilledRect(cursorRect); + g_painter->drawFilledRect(cursorRect); } else if(g_clock.ticksElapsed(m_cursorTicks) >= 2*delay) { m_cursorTicks = g_clock.ticks(); } diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 25312741..d53ba62c 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -54,19 +54,19 @@ UIWidget::~UIWidget() void UIWidget::draw(const Rect& visibleRect) { if(m_clipping) - g_painter.setClipRect(visibleRect); + g_painter->setClipRect(visibleRect); drawSelf(); if(m_children.size() > 0) { if(m_clipping) - g_painter.setClipRect(visibleRect.intersection(getClippingRect())); + g_painter->setClipRect(visibleRect.intersection(getClippingRect())); drawChildren(visibleRect); } if(m_clipping) - g_painter.resetClipRect(); + g_painter->resetClipRect(); } void UIWidget::drawSelf() @@ -97,22 +97,22 @@ void UIWidget::drawChildren(const Rect& visibleRect) continue; // store current graphics opacity - float oldOpacity = g_painter.getOpacity(); + float oldOpacity = g_painter->getOpacity(); // decrease to self opacity if(child->getOpacity() < oldOpacity) - g_painter.setOpacity(child->getOpacity()); + g_painter->setOpacity(child->getOpacity()); child->draw(childVisibleRect); // debug draw box if(g_ui.isDrawingDebugBoxes()) { - g_painter.setColor(Color::green); - g_painter.drawBoundingRect(child->getRect()); + g_painter->setColor(Color::green); + g_painter->drawBoundingRect(child->getRect()); } //g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Color::red); - g_painter.setOpacity(oldOpacity); + g_painter->setOpacity(oldOpacity); } } diff --git a/src/framework/ui/uiwidgetbasestyle.cpp b/src/framework/ui/uiwidgetbasestyle.cpp index 6437547f..208b9ad2 100644 --- a/src/framework/ui/uiwidgetbasestyle.cpp +++ b/src/framework/ui/uiwidgetbasestyle.cpp @@ -323,8 +323,8 @@ void UIWidget::drawBackground(const Rect& screenCoords) drawRect.translate(m_backgroundRect.topLeft()); if(m_backgroundRect.isValid()) drawRect.resize(m_backgroundRect.size()); - g_painter.setColor(m_backgroundColor); - g_painter.drawFilledRect(drawRect); + g_painter->setColor(m_backgroundColor); + g_painter->drawFilledRect(drawRect); } } @@ -332,31 +332,31 @@ void UIWidget::drawBorder(const Rect& screenCoords) { // top if(m_borderWidth.top > 0) { - g_painter.setColor(m_borderColor.top); + g_painter->setColor(m_borderColor.top); Rect borderRect(screenCoords.topLeft(), screenCoords.width(), m_borderWidth.top); - g_painter.drawFilledRect(borderRect); + g_painter->drawFilledRect(borderRect); } // right if(m_borderWidth.right > 0) { - g_painter.setColor(m_borderColor.right); + g_painter->setColor(m_borderColor.right); Rect borderRect(screenCoords.topRight() - Point(m_borderWidth.right - 1, 0), m_borderWidth.right, screenCoords.height()); - g_painter.drawFilledRect(borderRect); + g_painter->drawFilledRect(borderRect); } // bottom if(m_borderWidth.bottom > 0) { - g_painter.setColor(m_borderColor.bottom); + g_painter->setColor(m_borderColor.bottom); Rect borderRect(screenCoords.bottomLeft() - Point(0, m_borderWidth.bottom - 1), screenCoords.width(), m_borderWidth.bottom); - g_painter.drawFilledRect(borderRect); + g_painter->drawFilledRect(borderRect); } // left if(m_borderWidth.left > 0) { - g_painter.setColor(m_borderColor.left); + g_painter->setColor(m_borderColor.left); Rect borderRect(screenCoords.topLeft(), m_borderWidth.left, screenCoords.height()); - g_painter.drawFilledRect(borderRect); + g_painter->drawFilledRect(borderRect); } } @@ -372,8 +372,8 @@ void UIWidget::drawIcon(const Rect& screenCoords) drawRect.resize(m_icon->getSize()); drawRect.moveCenter(screenCoords.center()); } - g_painter.setColor(m_iconColor); - g_painter.drawTexturedRect(drawRect, m_icon); + g_painter->setColor(m_iconColor); + g_painter->drawTexturedRect(drawRect, m_icon); } } diff --git a/src/framework/ui/uiwidgetimage.cpp b/src/framework/ui/uiwidgetimage.cpp index be3a900d..aca4cfdf 100644 --- a/src/framework/ui/uiwidgetimage.cpp +++ b/src/framework/ui/uiwidgetimage.cpp @@ -167,8 +167,8 @@ void UIWidget::drawImage(const Rect& screenCoords) m_imageTexture->setSmooth(m_imageSmooth); - g_painter.setColor(m_imageColor); - g_painter.drawTextureCoords(m_imageCoordsBuffer, m_imageTexture); + g_painter->setColor(m_imageColor); + g_painter->drawTextureCoords(m_imageCoordsBuffer, m_imageTexture); } void UIWidget::setImageSource(const std::string& source) diff --git a/src/framework/ui/uiwidgettext.cpp b/src/framework/ui/uiwidgettext.cpp index 5c1c9cd6..01095f04 100644 --- a/src/framework/ui/uiwidgettext.cpp +++ b/src/framework/ui/uiwidgettext.cpp @@ -87,8 +87,8 @@ void UIWidget::drawText(const Rect& screenCoords) m_font->calculateDrawTextCoords(m_textCoordsBuffer, m_drawText, screenCoords.translated(m_textOffset), m_textAlign); } - g_painter.setColor(m_color); - g_painter.drawTextureCoords(m_textCoordsBuffer, m_font->getTexture()); + g_painter->setColor(m_color); + g_painter->drawTextureCoords(m_textCoordsBuffer, m_font->getTexture()); } void UIWidget::onTextChange(const std::string& text, const std::string& oldText) diff --git a/src/framework/util/compiler.h b/src/framework/util/compiler.h index b4fb9dd3..f8861d37 100644 --- a/src/framework/util/compiler.h +++ b/src/framework/util/compiler.h @@ -23,7 +23,16 @@ #ifndef __COMPILER_H__ #define __COMPILER_H__ +#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#error "sorry, you need gcc 4.6 or greater to compile" +#endif + +#if !defined(__GXX_EXPERIMENTAL_CXX0X__) +#error "sorry, you must enable C++0x to compile" +#endif + // hack to enable std::thread on mingw32 4.6 +/* #if !defined(_GLIBCXX_HAS_GTHREADS) && defined(__GNUG__) #include #include @@ -45,5 +54,6 @@ namespace std { using boost::condition_variable_any; } #endif +*/ #endif diff --git a/src/framework/util/types.h b/src/framework/util/types.h index 99b14af4..080143fe 100644 --- a/src/framework/util/types.h +++ b/src/framework/util/types.h @@ -40,12 +40,11 @@ typedef int32_t int32; typedef int16_t int16; typedef int8_t int8; -// note that on 32 bit platforms the max ticks will overflow for valeus above 2,147,483,647 -// thus this means that the app may crash after running 24 days without restarting +// note that on 32 bit platforms the max ticks will overflow for values above 2,147,483,647 +// thus this means that the app may cause unknown behavior after running 24 days without restarting typedef long ticks_t; typedef std::function SimpleCallback; -typedef std::function BooleanCallback; // boolean with default value initializer template diff --git a/src/otclient/core/animatedtext.cpp b/src/otclient/core/animatedtext.cpp index 11d9b89b..81ba6ccf 100644 --- a/src/otclient/core/animatedtext.cpp +++ b/src/otclient/core/animatedtext.cpp @@ -40,7 +40,7 @@ void AnimatedText::draw(const Point& dest, const Rect& visibleRect) if(visibleRect.contains(rect)) { //TODO: cache into a framebuffer - g_painter.setColor(m_color); + g_painter->setColor(m_color); m_font->drawText(m_text, rect, Fw::AlignLeft); } } diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index 9a433f1b..1974344d 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include #include "spritemanager.h" @@ -59,25 +59,27 @@ Creature::Creature() : Thing() m_informationFont = g_fonts.getFont("verdana-11px-rounded"); } +/* PainterShaderProgramPtr outfitProgram; int HEAD_COLOR_UNIFORM = 10; int BODY_COLOR_UNIFORM = 11; int LEGS_COLOR_UNIFORM = 12; int FEET_COLOR_UNIFORM = 13; int MASK_TEXTURE_UNIFORM = 14; +*/ void Creature::draw(const Point& dest, float scaleFactor, bool animate) { Point animationOffset = animate ? m_walkOffset : Point(0,0); if(m_showTimedSquare && animate) { - g_painter.setColor(m_timedSquareColor); - g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 3)*scaleFactor, Size(28, 28)*scaleFactor), std::max((int)(2*scaleFactor), 1)); + g_painter->setColor(m_timedSquareColor); + g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 3)*scaleFactor, Size(28, 28)*scaleFactor), std::max((int)(2*scaleFactor), 1)); } if(m_showStaticSquare && animate) { - g_painter.setColor(m_staticSquareColor); - g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 1)*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor), std::max((int)(2*scaleFactor), 1)); + g_painter->setColor(m_staticSquareColor); + g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 1)*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor), std::max((int)(2*scaleFactor), 1)); } internalDrawOutfit(dest + animationOffset * scaleFactor, scaleFactor, animate, animate, m_direction); @@ -86,7 +88,8 @@ void Creature::draw(const Point& dest, float scaleFactor, bool animate) void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction) { - g_painter.setColor(Color::white); + g_painter->setColor(Color::white); + /* if(!outfitProgram) { outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram); outfitProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); @@ -97,6 +100,7 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor"); outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor"); } + */ int xPattern = 0, yPattern = 0, zPattern = 0; @@ -124,13 +128,15 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1)))) continue; - g_painter.setCustomProgram(outfitProgram); + /* + g_painter->setShaderProgram(outfitProgram); outfitProgram->bind(); outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor()); outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor()); outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); + */ for(int h = 0; h < getDimensionHeight(); h++) { for(int w = 0; w < getDimensionWidth(); w++) { @@ -140,14 +146,14 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani int maskId = getSpriteId(w, h, 1, xPattern, yPattern, zPattern, animationPhase); maskTex = g_sprites.getSpriteTexture(maskId); } - outfitProgram->setTexture(maskTex, 1); + //outfitProgram->setTexture(maskTex, 1); internalDraw(dest + (-Point(w,h)*Otc::TILE_PIXELS)*scaleFactor, scaleFactor, w, h, xPattern, yPattern, zPattern, 0, animationPhase); } } - g_painter.releaseCustomProgram(); + //g_painter->resetShaderProgram(); } // outfit is a creature imitating an item or the invisible effect } else { @@ -182,12 +188,12 @@ void Creature::drawOutfit(const Rect& destRect, bool resize) if(!outfitBuffer) outfitBuffer = FrameBufferPtr(new FrameBuffer(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS))); - g_painter.saveAndResetState(); + g_painter->saveAndResetState(); outfitBuffer->bind(); outfitBuffer->clear(Color::alpha); internalDrawOutfit(Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South); outfitBuffer->release(); - g_painter.restoreSavedState(); + g_painter->restoreSavedState(); if(resize) { Rect srcRect; @@ -227,26 +233,26 @@ void Creature::drawInformation(const Point& point, bool useGray, const Rect& par healthRect.setWidth((m_healthPercent / 100.0) * 25); // draw - g_painter.setColor(Color::black); - g_painter.drawFilledRect(backgroundRect); + g_painter->setColor(Color::black); + g_painter->drawFilledRect(backgroundRect); - g_painter.setColor(fillColor); - g_painter.drawFilledRect(healthRect); + g_painter->setColor(fillColor); + g_painter->drawFilledRect(healthRect); if(m_informationFont) m_informationFont->drawText(m_name, textRect, Fw::AlignTopCenter); if(m_skull != Otc::SkullNone && m_skullTexture) { - g_painter.setColor(Color::white); - g_painter.drawTexturedRect(Rect(point.x + 12, point.y + 5, m_skullTexture->getSize()), m_skullTexture); + g_painter->setColor(Color::white); + g_painter->drawTexturedRect(Rect(point.x + 12, point.y + 5, m_skullTexture->getSize()), m_skullTexture); } if(m_shield != Otc::ShieldNone && m_shieldTexture && m_showShieldTexture) { - g_painter.setColor(Color::white); - g_painter.drawTexturedRect(Rect(point.x, point.y + 5, m_shieldTexture->getSize()), m_shieldTexture); + g_painter->setColor(Color::white); + g_painter->drawTexturedRect(Rect(point.x, point.y + 5, m_shieldTexture->getSize()), m_shieldTexture); } if(m_emblem != Otc::EmblemNone && m_emblemTexture) { - g_painter.setColor(Color::white); - g_painter.drawTexturedRect(Rect(point.x + 12, point.y + 16, m_emblemTexture->getSize()), m_emblemTexture); + g_painter->setColor(Color::white); + g_painter->drawTexturedRect(Rect(point.x + 12, point.y + 16, m_emblemTexture->getSize()), m_emblemTexture); } } diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp index d4d71759..0265b39b 100644 --- a/src/otclient/core/item.cpp +++ b/src/otclient/core/item.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include Item::Item() : Thing() { @@ -50,9 +50,10 @@ ItemPtr Item::create(int id) return item; } +/* PainterShaderProgramPtr itemProgram; int ITEM_ID_UNIFORM = 10; - +*/ void Item::draw(const Point& dest, float scaleFactor, bool animate) { if(m_id == 0) @@ -165,6 +166,7 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate) } // setup item drawing shader + /* if(!itemProgram) { itemProgram = PainterShaderProgramPtr(new PainterShaderProgram); itemProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); @@ -172,15 +174,16 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate) itemProgram->link(); itemProgram->bindUniformLocation(ITEM_ID_UNIFORM, "itemId"); } - g_painter.setCustomProgram(itemProgram); + g_painter->setShaderProgram(itemProgram); //itemProgram->bind(); //itemProgram->setUniformValue(ITEM_ID_UNIFORM, (int)m_id); + */ // now we can draw the item internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, animationPhase); // release draw shader - g_painter.releaseCustomProgram(); + g_painter->resetShaderProgram(); } void Item::setId(uint32 id) diff --git a/src/otclient/core/mapview.cpp b/src/otclient/core/mapview.cpp index 4fe8ffbe..23dbabaa 100644 --- a/src/otclient/core/mapview.cpp +++ b/src/otclient/core/mapview.cpp @@ -24,8 +24,7 @@ #include #include -#include -#include +#include #include "creature.h" #include "map.h" #include "tile.h" @@ -34,8 +33,6 @@ #include "missile.h" #include -//int AWARE_AREA_UNIFORM = 10; - MapView::MapView() { m_viewMode = NEAR_VIEW; @@ -47,11 +44,7 @@ MapView::MapView() m_framebuffer = FrameBufferPtr(new FrameBuffer()); setVisibleDimension(Size(15, 11)); - m_shaderProgram = PainterShaderProgramPtr(new PainterShaderProgram); - m_shaderProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); - m_shaderProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/map.frag"); - m_shaderProgram->link(); - //m_shaderProgram->bindUniformLocation(AWARE_AREA_UNIFORM, "awareArea"); + m_shaderProgram = g_shaders.createTexturedFragmentShader("/game_shaders/map.frag"); } void MapView::draw(const Rect& rect) @@ -78,16 +71,15 @@ void MapView::draw(const Rect& rect) Size tileSize = Size(1,1) * m_tileSize; if(m_mustDrawVisibleTilesCache || (drawFlags & Otc::DrawAnimations)) { - g_painter.saveAndResetState(); m_framebuffer->bind(); if(m_mustCleanFramebuffer) { Rect clearRect = Rect(0, 0, m_drawDimension * m_tileSize); // drawing a black rect is actually faster than FrameBuffer::clear() - g_painter.setColor(Color::black); - g_painter.drawFilledRect(clearRect); - g_painter.setColor(Color::white); + g_painter->setColor(Color::black); + g_painter->drawFilledRect(clearRect); + g_painter->setColor(Color::white); // m_framebuffer->clear(Color::black); } @@ -105,8 +97,8 @@ void MapView::draw(const Rect& rect) if(!m_drawMinimapColors) tile->draw(transformPositionTo2D(tile->getPosition()), scaleFactor, drawFlags); else { - g_painter.setColor(tile->getMinimapColor()); - g_painter.drawFilledRect(Rect(transformPositionTo2D(tile->getPosition()), tileSize)); + g_painter->setColor(tile->getMinimapColor()); + g_painter->drawFilledRect(Rect(transformPositionTo2D(tile->getPosition()), tileSize)); } } @@ -118,7 +110,6 @@ void MapView::draw(const Rect& rect) } m_framebuffer->release(); - g_painter.restoreSavedState(); // generating mipmaps each frame can be slow in older cards //m_framebuffer->getTexture()->generateHardwareMipmaps(); @@ -126,7 +117,7 @@ void MapView::draw(const Rect& rect) m_mustDrawVisibleTilesCache = false; } - g_painter.setCustomProgram(m_shaderProgram); + //g_painter->setShaderProgram(m_shaderProgram); Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize; if(m_followingCreature) @@ -139,39 +130,20 @@ void MapView::draw(const Rect& rect) drawOffset.y += (srcVisible.height() - srcSize.height()) / 2; Rect srcRect = Rect(drawOffset, srcSize); - /* - // pass aware area to the shader program - Rect awareRect; - if(m_followingCreature) { - Point awareOffset = transformPositionTo2D(m_followingCreature->getPosition().translated(-Otc::AWARE_X_LEFT_TILES + 1, -Otc::AWARE_Y_TOP_TILES + 1)); - awareOffset += m_followingCreature->getWalkOffset() * scaleFactor; - - awareRect.setTopLeft(awareOffset); - awareRect.resize(Otc::VISIBLE_X_TILES * m_tileSize, Otc::VISIBLE_Y_TILES * m_tileSize); - } - - m_shaderProgram->bind(); - m_shaderProgram->setUniformValue(AWARE_AREA_UNIFORM, - awareRect.left()/(float)m_framebuffer->getSize().width(), - awareRect.top()/(float)m_framebuffer->getSize().height(), - awareRect.right()/(float)m_framebuffer->getSize().width(), - awareRect.bottom()/(float)m_framebuffer->getSize().height()); - */ - #if 0 // debug source area - g_painter.saveAndResetState(); + g_painter->saveAndResetState(); m_framebuffer->bind(); - g_painter.setColor(Color::green); - g_painter.drawBoundingRect(srcRect, 2); + g_painter->setColor(Color::green); + g_painter->drawBoundingRect(srcRect, 2); m_framebuffer->release(); - g_painter.restoreSavedState(); + g_painter->restoreSavedState(); m_framebuffer->draw(rect); #else m_framebuffer->draw(rect, srcRect); #endif - g_painter.releaseCustomProgram(); + g_painter->resetShaderProgram(); // this could happen if the player position is not known yet if(!cameraPosition.isValid()) @@ -231,9 +203,9 @@ void MapView::draw(const Rect& rect) Rect hRect(0, 0, 10, 2); vRect.moveCenter(rect.center()); hRect.moveCenter(rect.center()); - g_painter.setColor(Color::white); - g_painter.drawFilledRect(vRect); - g_painter.drawFilledRect(hRect); + g_painter->setColor(Color::white); + g_painter->drawFilledRect(vRect); + g_painter->drawFilledRect(hRect); } } diff --git a/src/otclient/core/spritemanager.cpp b/src/otclient/core/spritemanager.cpp index e230c6af..c0411ad7 100644 --- a/src/otclient/core/spritemanager.cpp +++ b/src/otclient/core/spritemanager.cpp @@ -137,7 +137,7 @@ TexturePtr SpriteManager::loadSpriteTexture(int id) TexturePtr spriteTex(new Texture(32, 32, 4, &pixels[0])); spriteTex->setSmooth(true); - if(g_graphics.canGenerateMipmaps()) + if(g_graphics.canUseMipmaps()) spriteTex->generateSoftwareMipmaps(pixels); return spriteTex; diff --git a/src/otclient/core/statictext.cpp b/src/otclient/core/statictext.cpp index f158b0b6..53619467 100644 --- a/src/otclient/core/statictext.cpp +++ b/src/otclient/core/statictext.cpp @@ -40,7 +40,7 @@ void StaticText::draw(const Point& dest, const Rect& parentRect) // draw only if the real center is not too far from the parent center, or its a yell if((boundRect.center() - rect.center()).length() < parentRect.width() / 15 || isYell()) { //TODO: cache into a framebuffer - g_painter.setColor(m_color); + g_painter->setColor(m_color); m_font->drawText(m_text, boundRect, Fw::AlignCenter); } } diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index c7d67a5c..c61da97d 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -82,8 +82,8 @@ void Thing::internalDraw(const Point& dest, float scaleFactor, int w, int h, int int spriteId = getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animationPhase); if(spriteId) { Rect drawRect(dest - getDisplacement()*scaleFactor, Size(scaledSize, scaledSize)); - g_painter.setColor(Color::white); - g_painter.drawTexturedRect(drawRect, g_sprites.getSpriteTexture(spriteId)); + g_painter->setColor(Color::white); + g_painter->drawTexturedRect(drawRect, g_sprites.getSpriteTexture(spriteId)); } } diff --git a/src/otclient/ui/uicreature.cpp b/src/otclient/ui/uicreature.cpp index f2e43489..ae83bb19 100644 --- a/src/otclient/ui/uicreature.cpp +++ b/src/otclient/ui/uicreature.cpp @@ -29,7 +29,7 @@ void UICreature::drawSelf() UIWidget::drawSelf(); if(m_creature) { - g_painter.setColor(Color::white); + g_painter->setColor(Color::white); Rect drawRect = getClippingRect(); m_creature->drawOutfit(drawRect, !m_fixedCreatureSize); } diff --git a/src/otclient/ui/uiitem.cpp b/src/otclient/ui/uiitem.cpp index 6fa6d5fd..a7057b3e 100644 --- a/src/otclient/ui/uiitem.cpp +++ b/src/otclient/ui/uiitem.cpp @@ -41,12 +41,12 @@ void UIItem::drawSelf() dest += (1 - scaleFactor)*32; dest += m_item->getDisplacement() * scaleFactor; - g_painter.setColor(Color::white); + g_painter->setColor(Color::white); m_item->draw(dest, scaleFactor, true); if(m_font && m_item->isStackable() && m_item->getCount() > 1) { std::string count = Fw::tostring(m_item->getCount()); - g_painter.setColor(Color(231, 231, 231)); + g_painter->setColor(Color(231, 231, 231)); m_font->drawText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight); } //m_font->drawText(Fw::tostring(m_item->getId()), m_rect, Fw::AlignBottomRight); diff --git a/src/otclient/ui/uimap.cpp b/src/otclient/ui/uimap.cpp index 9838541a..b12c38dc 100644 --- a/src/otclient/ui/uimap.cpp +++ b/src/otclient/ui/uimap.cpp @@ -49,9 +49,10 @@ void UIMap::drawSelf() UIWidget::drawSelf(); // draw map border - g_painter.setColor(Color::black); - g_painter.drawBoundingRect(m_mapRect.expanded(1)); + g_painter->setColor(Color::black); + g_painter->drawBoundingRect(m_mapRect.expanded(1)); + g_painter->setColor(Color::white); m_mapView->draw(m_mapRect); }