diff --git a/src/client/lightview.h b/src/client/lightview.h index c14363e4..22926b88 100644 --- a/src/client/lightview.h +++ b/src/client/lightview.h @@ -25,7 +25,7 @@ #include "declarations.h" #include -#include +#include #include "thingtype.h" struct LightSource { diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 27a94365..27cc7137 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -342,6 +342,8 @@ if(FRAMEWORK_GRAPHICS) ${CMAKE_CURRENT_LIST_DIR}/graphics/image.h ${CMAKE_CURRENT_LIST_DIR}/graphics/painter.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/painter.h + ${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl.h ${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl1.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl1.h ${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl2.cpp diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index 432e30bb..898db23d 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -184,8 +184,8 @@ bool Graphics::isPainterEngineAvailable(Graphics::PainterEngine painterEngine) bool Graphics::selectPainterEngine(PainterEngine painterEngine) { - Painter *painter = nullptr; - Painter *fallbackPainter = nullptr; + PainterOGL *painter = nullptr; + PainterOGL *fallbackPainter = nullptr; PainterEngine fallbackPainterEngine = Painter_Any; #ifdef PAINTER_DX9 diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp index 91a7f211..7a739497 100644 --- a/src/framework/graphics/painter.cpp +++ b/src/framework/graphics/painter.cpp @@ -29,289 +29,5 @@ Painter *g_painter = nullptr; Painter::Painter() { - m_glTextureId = 0; - m_oldStateIndex = 0; - m_color = Color::white; - m_opacity = 1.0f; - m_compositionMode = CompositionMode_Normal; - m_blendEquation = BlendEquation_Add; - m_shaderProgram = nullptr; - m_texture = nullptr; - m_alphaWriting = false; - setResolution(g_window.getSize()); -} - -void Painter::resetState() -{ - resetColor(); - resetOpacity(); - resetCompositionMode(); - resetBlendEquation(); - resetClipRect(); - resetShaderProgram(); - resetTexture(); - resetAlphaWriting(); - resetTransformMatrix(); -} - -void Painter::refreshState() -{ - updateGlViewport(); - updateGlCompositionMode(); - updateGlBlendEquation(); - updateGlClipRect(); - updateGlTexture(); - updateGlAlphaWriting(); -} - -void Painter::saveState() -{ - assert(m_oldStateIndex<10); - m_olderStates[m_oldStateIndex].resolution = m_resolution; - m_olderStates[m_oldStateIndex].transformMatrix = m_transformMatrix; - 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].blendEquation = m_blendEquation; - m_olderStates[m_oldStateIndex].clipRect = m_clipRect; - m_olderStates[m_oldStateIndex].shaderProgram = m_shaderProgram; - m_olderStates[m_oldStateIndex].texture = m_texture; - m_olderStates[m_oldStateIndex].alphaWriting = m_alphaWriting; - m_oldStateIndex++; -} - -void Painter::saveAndResetState() -{ - saveState(); - resetState(); -} - -void Painter::restoreSavedState() -{ - m_oldStateIndex--; - setResolution(m_olderStates[m_oldStateIndex].resolution); - setTransformMatrix(m_olderStates[m_oldStateIndex].transformMatrix); - 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); - setBlendEquation(m_olderStates[m_oldStateIndex].blendEquation); - setClipRect(m_olderStates[m_oldStateIndex].clipRect); - setShaderProgram(m_olderStates[m_oldStateIndex].shaderProgram); - setTexture(m_olderStates[m_oldStateIndex].texture); - setAlphaWriting(m_olderStates[m_oldStateIndex].alphaWriting); -} - -void Painter::clear(const Color& color) -{ - glClearColor(color.rF(), color.gF(), color.bF(), color.aF()); - glClear(GL_COLOR_BUFFER_BIT); -} - -void Painter::clearRect(const Color& color, const Rect& rect) -{ - Rect oldClipRect = m_clipRect; - setClipRect(rect); - glClearColor(color.rF(), color.gF(), color.bF(), color.aF()); - glClear(GL_COLOR_BUFFER_BIT); - setClipRect(oldClipRect); -} - -void Painter::setCompositionMode(Painter::CompositionMode compositionMode) -{ - if(m_compositionMode == compositionMode) - return; - m_compositionMode = compositionMode; - updateGlCompositionMode(); -} - -void Painter::setBlendEquation(Painter::BlendEquation blendEquation) -{ - if(m_blendEquation == blendEquation) - return; - m_blendEquation = blendEquation; - updateGlBlendEquation(); -} - -void Painter::setClipRect(const Rect& clipRect) -{ - if(m_clipRect == clipRect) - return; - m_clipRect = clipRect; - updateGlClipRect(); -} - -void Painter::setTexture(Texture* texture) -{ - if(m_texture == texture) - return; - - m_texture = texture; - - uint glTextureId; - if(texture) { - setTextureMatrix(texture->getTransformMatrix()); - glTextureId = texture->getId(); - } else - glTextureId = 0; - - if(m_glTextureId != glTextureId) { - m_glTextureId = glTextureId; - updateGlTexture(); - } -} - -void Painter::setAlphaWriting(bool enable) -{ - if(m_alphaWriting == enable) - return; - - m_alphaWriting = enable; - updateGlAlphaWriting(); -} - -void Painter::setResolution(const Size& resolution) -{ - // The projection matrix converts from Painter's coordinate system to GL's coordinate system - // * GL's viewport is 2x2, Painter's is width x height - // * GL has +y -> -y going from bottom -> top, Painter is the other way round - // * GL has [0,0] in the center, Painter has it in the top-left - // - // This results in the Projection matrix below. - // - // 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/resolution.width(), 0.0f, 0.0f, - 0.0f, -2.0f/resolution.height(), 0.0f, - -1.0f, 1.0f, 1.0f }; - - m_resolution = resolution; - - setProjectionMatrix(projectionMatrix); - if(g_painter == this) - updateGlViewport(); -} - -void Painter::scale(float x, float y) -{ - Matrix3 scaleMatrix = { - x, 0.0f, 0.0f, - 0.0f, y, 0.0f, - 0.0f, 0.0f, 1.0f - }; - - setTransformMatrix(m_transformMatrix * scaleMatrix.transposed()); -} - -void Painter::translate(float x, float y) -{ - Matrix3 translateMatrix = { - 1.0f, 0.0f, x, - 0.0f, 1.0f, y, - 0.0f, 0.0f, 1.0f - }; - - setTransformMatrix(m_transformMatrix * translateMatrix.transposed()); -} - -void Painter::rotate(float angle) -{ - Matrix3 rotationMatrix = { - std::cos(angle), -std::sin(angle), 0.0f, - std::sin(angle), std::cos(angle), 0.0f, - 0.0f, 0.0f, 1.0f - }; - - setTransformMatrix(m_transformMatrix * rotationMatrix.transposed()); -} - -void Painter::rotate(float x, float y, float angle) -{ - translate(-x, -y); - rotate(angle); - translate(x, y); -} - -void Painter::pushTransformMatrix() -{ - m_transformMatrixStack.push_back(m_transformMatrix); - assert(m_transformMatrixStack.size() < 100); -} - -void Painter::popTransformMatrix() -{ - assert(m_transformMatrixStack.size() > 0); - setTransformMatrix(m_transformMatrixStack.back()); - m_transformMatrixStack.pop_back(); -} - -void Painter::updateGlTexture() -{ - if(m_glTextureId != 0) - glBindTexture(GL_TEXTURE_2D, m_glTextureId); -} - -void Painter::updateGlCompositionMode() -{ - switch(m_compositionMode) { - case CompositionMode_Normal: - if(g_graphics.canUseBlendFuncSeparate()) - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); - else - 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; - case CompositionMode_Light: - glBlendFunc(GL_ZERO, GL_SRC_COLOR); - break; - } -} - -void Painter::updateGlBlendEquation() -{ - if(!g_graphics.canUseBlendEquation()) - return; - glBlendEquation(m_blendEquation); -} - -void Painter::updateGlClipRect() -{ - if(m_clipRect.isValid()) { - glEnable(GL_SCISSOR_TEST); - glScissor(m_clipRect.left(), m_resolution.height() - m_clipRect.bottom() - 1, m_clipRect.width(), m_clipRect.height()); - } else { - glScissor(0, 0, m_resolution.width(), m_resolution.height()); - glDisable(GL_SCISSOR_TEST); - } -} - -void Painter::updateGlAlphaWriting() -{ - if(m_alphaWriting) - glColorMask(1,1,1,1); - else - glColorMask(1,1,1,0); -} - -void Painter::updateGlViewport() -{ - glViewport(0, 0, m_resolution.width(), m_resolution.height()); + } diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h index f84d9260..b2ce5937 100644 --- a/src/framework/graphics/painter.h +++ b/src/framework/graphics/painter.h @@ -31,6 +31,10 @@ class Painter { public: + enum BlendEquation { + BlendEquation_Add, + BlendEquation_Max + }; enum CompositionMode { CompositionMode_Normal, CompositionMode_Multiply, @@ -43,130 +47,75 @@ public: Triangles = GL_TRIANGLES, TriangleStrip = GL_TRIANGLE_STRIP }; - enum BlendEquation { - BlendEquation_Add = 0x8006, // GL_FUNC_ADD - BlendEquation_Max = 0x8008 // GL_MAX - }; - struct PainterState { - Size resolution; - Matrix3 transformMatrix; - Matrix3 projectionMatrix; - Matrix3 textureMatrix; - Color color; - float opacity; - Painter::CompositionMode compositionMode; - Painter::BlendEquation blendEquation; - Rect clipRect; - Texture *texture; - PainterShaderProgram *shaderProgram; - bool alphaWriting; - }; Painter(); virtual ~Painter() { } - virtual void bind() { refreshState(); } + virtual void bind() { } virtual void unbind() { } - void resetState(); - virtual void refreshState(); - void saveState(); - void saveAndResetState(); - void restoreSavedState(); + virtual void saveState() = 0; + virtual void saveAndResetState() = 0; + virtual void restoreSavedState() = 0; - void clear(const Color& color); - void clearRect(const Color& color, const Rect& rect); + virtual void clear(const Color& color) = 0; 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; - virtual void drawUpsideDownTexturedRect(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())); } + virtual void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0; virtual void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0; virtual void drawFilledRect(const Rect& dest) = 0; virtual void drawFilledTriangle(const Point& a, const Point& b, const Point& c) = 0; virtual void drawBoundingRect(const Rect& dest, int innerLineWidth = 1) = 0; - virtual void setTransformMatrix(const Matrix3& transformMatrix) { m_transformMatrix = transformMatrix; } - virtual void setProjectionMatrix(const Matrix3& projectionMatrix) { m_projectionMatrix = projectionMatrix; } - virtual void setTextureMatrix(const Matrix3& textureMatrix) { m_textureMatrix = textureMatrix; } + virtual void setTexture(Texture *texture) = 0; + virtual void setClipRect(const Rect& clipRect) = 0; virtual void setColor(const Color& color) { m_color = color; } - virtual void setOpacity(float opacity) { m_opacity = opacity; } - virtual void setCompositionMode(CompositionMode compositionMode); - virtual void setBlendEquation(BlendEquation blendEquation); - virtual void setClipRect(const Rect& clipRect); + virtual void setAlphaWriting(bool enable) = 0; + virtual void setBlendEquation(BlendEquation blendEquation) = 0; virtual void setShaderProgram(PainterShaderProgram *shaderProgram) { m_shaderProgram = shaderProgram; } - virtual void setTexture(Texture *texture); - void setAlphaWriting(bool enable); - void setShaderProgram(const PainterShaderProgramPtr& shaderProgram) { setShaderProgram(shaderProgram.get()); } - void setTexture(const TexturePtr& texture) { setTexture(texture.get()); } - void setResolution(const Size& resolution); - void scale(float x, float y); + virtual void scale(float x, float y) = 0; void scale(float factor) { scale(factor, factor); } - void translate(float x, float y); + virtual void translate(float x, float y) = 0; void translate(const Point& p) { translate(p.x, p.y); } - void rotate(float angle); - void rotate(float x, float y, float angle); + virtual void rotate(float angle) = 0; + virtual void rotate(float x, float y, float angle) = 0; void rotate(const Point& p, float angle) { rotate(p.x, p.y, angle); } - void pushTransformMatrix(); - void popTransformMatrix(); + virtual void setOpacity(float opacity) { m_opacity = opacity; } + virtual void setResolution(const Size& resolution) { m_resolution = resolution; } - Matrix3 getTransformMatrix() { return m_transformMatrix; } - Matrix3 getProjectionMatrix() { return m_projectionMatrix; } - Matrix3 getTextureMatrix() { return m_textureMatrix; } + Size getResolution() { return m_resolution; } Color getColor() { return m_color; } float getOpacity() { return m_opacity; } - CompositionMode getCompositionMode() { return m_compositionMode; } - BlendEquation getBlendEquation() { return m_blendEquation; } Rect getClipRect() { return m_clipRect; } - PainterShaderProgram *getShaderProgram() { return m_shaderProgram; } - bool getAlphaWriting() { return m_alphaWriting; } - Size getResolution() { return m_resolution; } + CompositionMode getCompositionMode() { return m_compositionMode; } + + virtual void setCompositionMode(CompositionMode compositionMode) = 0; + + virtual void pushTransformMatrix() = 0; + virtual void popTransformMatrix() = 0; - void resetColor() { setColor(Color::white); } - void resetOpacity() { setOpacity(1.0f); } void resetClipRect() { setClipRect(Rect()); } + void resetOpacity() { setOpacity(1.0f); } void resetCompositionMode() { setCompositionMode(CompositionMode_Normal); } - void resetBlendEquation() { setBlendEquation(BlendEquation_Add); } + void resetColor() { setColor(Color::white); } void resetShaderProgram() { setShaderProgram(nullptr); } - void resetTexture() { setTexture(nullptr); } - void resetAlphaWriting() { setAlphaWriting(false); } - void resetTransformMatrix() { setTransformMatrix(Matrix3()); } virtual bool hasShaders() = 0; protected: - void updateGlTexture(); - void updateGlCompositionMode(); - void updateGlBlendEquation(); - void updateGlClipRect(); - void updateGlAlphaWriting(); - void updateGlViewport(); - - CoordsBuffer m_coordsBuffer; - - std::vector m_transformMatrixStack; - Matrix3 m_transformMatrix; - Matrix3 m_projectionMatrix; - Matrix3 m_textureMatrix; - Color m_color; - float m_opacity; - CompositionMode m_compositionMode; - BlendEquation m_blendEquation; - Rect m_clipRect; - Texture *m_texture; PainterShaderProgram *m_shaderProgram; - bool m_alphaWriting; + CompositionMode m_compositionMode; + Color m_color; Size m_resolution; - - PainterState m_olderStates[10]; - int m_oldStateIndex; - - uint m_glTextureId; + float m_opacity; + Rect m_clipRect; }; extern Painter *g_painter; diff --git a/src/framework/graphics/painterogl.cpp b/src/framework/graphics/painterogl.cpp new file mode 100644 index 00000000..146d231f --- /dev/null +++ b/src/framework/graphics/painterogl.cpp @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2010-2013 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 "painterogl.h" +#include "graphics.h" + +#include + +PainterOGL::PainterOGL() +{ + m_glTextureId = 0; + m_oldStateIndex = 0; + m_color = Color::white; + m_opacity = 1.0f; + m_compositionMode = CompositionMode_Normal; + m_blendEquation = BlendEquation_Add; + m_shaderProgram = nullptr; + m_texture = nullptr; + m_alphaWriting = false; + setResolution(g_window.getSize()); +} + +void PainterOGL::resetState() +{ + resetColor(); + resetOpacity(); + resetCompositionMode(); + resetBlendEquation(); + resetClipRect(); + resetShaderProgram(); + resetTexture(); + resetAlphaWriting(); + resetTransformMatrix(); +} + +void PainterOGL::refreshState() +{ + updateGlViewport(); + updateGlCompositionMode(); + updateGlBlendEquation(); + updateGlClipRect(); + updateGlTexture(); + updateGlAlphaWriting(); +} + +void PainterOGL::saveState() +{ + assert(m_oldStateIndex<10); + m_olderStates[m_oldStateIndex].resolution = m_resolution; + m_olderStates[m_oldStateIndex].transformMatrix = m_transformMatrix; + 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].blendEquation = m_blendEquation; + m_olderStates[m_oldStateIndex].clipRect = m_clipRect; + m_olderStates[m_oldStateIndex].shaderProgram = m_shaderProgram; + m_olderStates[m_oldStateIndex].texture = m_texture; + m_olderStates[m_oldStateIndex].alphaWriting = m_alphaWriting; + m_oldStateIndex++; +} + +void PainterOGL::saveAndResetState() +{ + saveState(); + resetState(); +} + +void PainterOGL::restoreSavedState() +{ + m_oldStateIndex--; + setResolution(m_olderStates[m_oldStateIndex].resolution); + setTransformMatrix(m_olderStates[m_oldStateIndex].transformMatrix); + 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); + setBlendEquation(m_olderStates[m_oldStateIndex].blendEquation); + setClipRect(m_olderStates[m_oldStateIndex].clipRect); + setShaderProgram(m_olderStates[m_oldStateIndex].shaderProgram); + setTexture(m_olderStates[m_oldStateIndex].texture); + setAlphaWriting(m_olderStates[m_oldStateIndex].alphaWriting); +} + +void PainterOGL::clear(const Color& color) +{ + glClearColor(color.rF(), color.gF(), color.bF(), color.aF()); + glClear(GL_COLOR_BUFFER_BIT); +} + +void PainterOGL::clearRect(const Color& color, const Rect& rect) +{ + Rect oldClipRect = m_clipRect; + setClipRect(rect); + glClearColor(color.rF(), color.gF(), color.bF(), color.aF()); + glClear(GL_COLOR_BUFFER_BIT); + setClipRect(oldClipRect); +} + +void PainterOGL::setCompositionMode(Painter::CompositionMode compositionMode) +{ + if(m_compositionMode == compositionMode) + return; + m_compositionMode = compositionMode; + updateGlCompositionMode(); +} + +void PainterOGL::setBlendEquation(Painter::BlendEquation blendEquation) +{ + if(m_blendEquation == blendEquation) + return; + m_blendEquation = blendEquation; + updateGlBlendEquation(); +} + +void PainterOGL::setClipRect(const Rect& clipRect) +{ + if(m_clipRect == clipRect) + return; + m_clipRect = clipRect; + updateGlClipRect(); +} + +void PainterOGL::setTexture(Texture* texture) +{ + if(m_texture == texture) + return; + + m_texture = texture; + + uint glTextureId; + if(texture) { + setTextureMatrix(texture->getTransformMatrix()); + glTextureId = texture->getId(); + } else + glTextureId = 0; + + if(m_glTextureId != glTextureId) { + m_glTextureId = glTextureId; + updateGlTexture(); + } +} + +void PainterOGL::setAlphaWriting(bool enable) +{ + if(m_alphaWriting == enable) + return; + + m_alphaWriting = enable; + updateGlAlphaWriting(); +} + +void PainterOGL::setResolution(const Size& resolution) +{ + // The projection matrix converts from Painter's coordinate system to GL's coordinate system + // * GL's viewport is 2x2, Painter's is width x height + // * GL has +y -> -y going from bottom -> top, Painter is the other way round + // * GL has [0,0] in the center, Painter has it in the top-left + // + // This results in the Projection matrix below. + // + // 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/resolution.width(), 0.0f, 0.0f, + 0.0f, -2.0f/resolution.height(), 0.0f, + -1.0f, 1.0f, 1.0f }; + + m_resolution = resolution; + + setProjectionMatrix(projectionMatrix); + if(g_painter == this) + updateGlViewport(); +} + +void PainterOGL::scale(float x, float y) +{ + Matrix3 scaleMatrix = { + x, 0.0f, 0.0f, + 0.0f, y, 0.0f, + 0.0f, 0.0f, 1.0f + }; + + setTransformMatrix(m_transformMatrix * scaleMatrix.transposed()); +} + +void PainterOGL::translate(float x, float y) +{ + Matrix3 translateMatrix = { + 1.0f, 0.0f, x, + 0.0f, 1.0f, y, + 0.0f, 0.0f, 1.0f + }; + + setTransformMatrix(m_transformMatrix * translateMatrix.transposed()); +} + +void PainterOGL::rotate(float angle) +{ + Matrix3 rotationMatrix = { + std::cos(angle), -std::sin(angle), 0.0f, + std::sin(angle), std::cos(angle), 0.0f, + 0.0f, 0.0f, 1.0f + }; + + setTransformMatrix(m_transformMatrix * rotationMatrix.transposed()); +} + +void PainterOGL::rotate(float x, float y, float angle) +{ + translate(-x, -y); + rotate(angle); + translate(x, y); +} + +void PainterOGL::pushTransformMatrix() +{ + m_transformMatrixStack.push_back(m_transformMatrix); + assert(m_transformMatrixStack.size() < 100); +} + +void PainterOGL::popTransformMatrix() +{ + assert(m_transformMatrixStack.size() > 0); + setTransformMatrix(m_transformMatrixStack.back()); + m_transformMatrixStack.pop_back(); +} + +void PainterOGL::updateGlTexture() +{ + if(m_glTextureId != 0) + glBindTexture(GL_TEXTURE_2D, m_glTextureId); +} + +void PainterOGL::updateGlCompositionMode() +{ + switch(m_compositionMode) { + case CompositionMode_Normal: + if(g_graphics.canUseBlendFuncSeparate()) + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + else + 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; + case CompositionMode_Light: + glBlendFunc(GL_ZERO, GL_SRC_COLOR); + break; + } +} + +void PainterOGL::updateGlBlendEquation() +{ + if(!g_graphics.canUseBlendEquation()) + return; + if(m_blendEquation == BlendEquation_Add) + glBlendEquation(0x8006); // GL_FUNC_ADD + else if(m_blendEquation == BlendEquation_Max) + glBlendEquation(0x8008); // GL_MAX +} + +void PainterOGL::updateGlClipRect() +{ + if(m_clipRect.isValid()) { + glEnable(GL_SCISSOR_TEST); + glScissor(m_clipRect.left(), m_resolution.height() - m_clipRect.bottom() - 1, m_clipRect.width(), m_clipRect.height()); + } else { + glScissor(0, 0, m_resolution.width(), m_resolution.height()); + glDisable(GL_SCISSOR_TEST); + } +} + +void PainterOGL::updateGlAlphaWriting() +{ + if(m_alphaWriting) + glColorMask(1,1,1,1); + else + glColorMask(1,1,1,0); +} + +void PainterOGL::updateGlViewport() +{ + glViewport(0, 0, m_resolution.width(), m_resolution.height()); +} diff --git a/src/framework/graphics/painterogl.h b/src/framework/graphics/painterogl.h new file mode 100644 index 00000000..1ec6494b --- /dev/null +++ b/src/framework/graphics/painterogl.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2010-2013 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 PAINTEROGL_H +#define PAINTEROGL_H + +#include "declarations.h" +#include "coordsbuffer.h" +#include "paintershaderprogram.h" +#include "texture.h" +#include "painter.h" + +class PainterOGL : public Painter +{ +public: + struct PainterState { + Size resolution; + Matrix3 transformMatrix; + Matrix3 projectionMatrix; + Matrix3 textureMatrix; + Color color; + float opacity; + Painter::CompositionMode compositionMode; + Painter::BlendEquation blendEquation; + Rect clipRect; + Texture *texture; + PainterShaderProgram *shaderProgram; + bool alphaWriting; + }; + + PainterOGL(); + virtual ~PainterOGL() { } + + virtual void bind() { refreshState(); } + virtual void unbind() { } + + void resetState(); + virtual void refreshState(); + void saveState(); + void saveAndResetState(); + void restoreSavedState(); + + void clear(const Color& color); + void clearRect(const Color& color, const Rect& rect); + + virtual void setTransformMatrix(const Matrix3& transformMatrix) { m_transformMatrix = transformMatrix; } + virtual void setProjectionMatrix(const Matrix3& projectionMatrix) { m_projectionMatrix = projectionMatrix; } + virtual void setTextureMatrix(const Matrix3& textureMatrix) { m_textureMatrix = textureMatrix; } + virtual void setCompositionMode(CompositionMode compositionMode); + virtual void setBlendEquation(BlendEquation blendEquation); + virtual void setClipRect(const Rect& clipRect); + virtual void setShaderProgram(PainterShaderProgram *shaderProgram) { m_shaderProgram = shaderProgram; } + virtual void setTexture(Texture *texture); + virtual void setAlphaWriting(bool enable); + + void setTexture(const TexturePtr& texture) { setTexture(texture.get()); } + void setResolution(const Size& resolution); + + void scale(float x, float y); + void translate(float x, float y); + void rotate(float angle); + void rotate(float x, float y, float angle); + + void pushTransformMatrix(); + void popTransformMatrix(); + + Matrix3 getTransformMatrix() { return m_transformMatrix; } + Matrix3 getProjectionMatrix() { return m_projectionMatrix; } + Matrix3 getTextureMatrix() { return m_textureMatrix; } + BlendEquation getBlendEquation() { return m_blendEquation; } + PainterShaderProgram *getShaderProgram() { return m_shaderProgram; } + bool getAlphaWriting() { return m_alphaWriting; } + + void resetBlendEquation() { setBlendEquation(BlendEquation_Add); } + void resetTexture() { setTexture(nullptr); } + void resetAlphaWriting() { setAlphaWriting(false); } + void resetTransformMatrix() { setTransformMatrix(Matrix3()); } + +protected: + void updateGlTexture(); + void updateGlCompositionMode(); + void updateGlBlendEquation(); + void updateGlClipRect(); + void updateGlAlphaWriting(); + void updateGlViewport(); + + CoordsBuffer m_coordsBuffer; + + std::vector m_transformMatrixStack; + Matrix3 m_transformMatrix; + Matrix3 m_projectionMatrix; + Matrix3 m_textureMatrix; + + BlendEquation m_blendEquation; + Texture *m_texture; + bool m_alphaWriting; + + PainterState m_olderStates[10]; + int m_oldStateIndex; + + uint m_glTextureId; +}; + +#endif diff --git a/src/framework/graphics/painterogl1.cpp b/src/framework/graphics/painterogl1.cpp index 362698a0..2efa7b0b 100644 --- a/src/framework/graphics/painterogl1.cpp +++ b/src/framework/graphics/painterogl1.cpp @@ -35,7 +35,7 @@ PainterOGL1::PainterOGL1() void PainterOGL1::refreshState() { - Painter::refreshState(); + PainterOGL::refreshState(); updateGlColor(); updateGlMatrixMode(); updateGlTransformMatrix(); @@ -46,7 +46,7 @@ void PainterOGL1::refreshState() void PainterOGL1::bind() { - Painter::bind(); + PainterOGL::bind(); // vertex and texture coord arrays are always enabled // to avoid massive enable/disables, thus improving frame rate @@ -107,7 +107,10 @@ void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode) HardwareBuffer::unbind(HardwareBuffer::VertexBuffer); // draw the element in coords buffers - glDrawArrays(drawMode, 0, vertexCount); + if(drawMode == Triangles) + glDrawArrays(GL_TRIANGLES, 0, vertexCount); + else if(drawMode == TriangleStrip) + glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexCount); } #ifndef OPENGL_ES else { @@ -118,7 +121,10 @@ void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode) // 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); + if(drawMode == Triangles) + glBegin(GL_TRIANGLES); + else if(drawMode == TriangleStrip) + glBegin(GL_TRIANGLE_STRIP); for(int i=0;isetAttributeArray(PainterShaderProgram::VERTEX_ATTR, coordsBuffer.getVertexArray(), 2); // draw the element in coords buffers - glDrawArrays(drawMode, 0, vertexCount); + if(drawMode == Triangles) + glDrawArrays(GL_TRIANGLES, 0, vertexCount); + else if(drawMode == TriangleStrip) + glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexCount); if(!textured) PainterShaderProgram::enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR); diff --git a/src/framework/graphics/painterogl2.h b/src/framework/graphics/painterogl2.h index ac3d6b46..08ab078a 100644 --- a/src/framework/graphics/painterogl2.h +++ b/src/framework/graphics/painterogl2.h @@ -25,14 +25,14 @@ #define PAINTER_OGL2 -#include "painter.h" +#include "painterogl.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 +class PainterOGL2 : public PainterOGL { public: PainterOGL2(); diff --git a/src/framework/graphics/particle.h b/src/framework/graphics/particle.h index f75f2dad..fa6da84d 100644 --- a/src/framework/graphics/particle.h +++ b/src/framework/graphics/particle.h @@ -24,7 +24,7 @@ #define PARTICLE_H #include "declarations.h" -#include "painter.h" +#include "painterogl.h" class Particle : public stdext::shared_object { diff --git a/src/framework/graphics/particletype.h b/src/framework/graphics/particletype.h index fbad2136..76ddc887 100644 --- a/src/framework/graphics/particletype.h +++ b/src/framework/graphics/particletype.h @@ -24,7 +24,7 @@ #define PARTICLETYPE_H #include "declarations.h" -#include +#include #include #include