diff --git a/modules/game_shaders/outfit.frag b/modules/game_shaders/outfit.frag index 214d9089..edff06fb 100644 --- a/modules/game_shaders/outfit.frag +++ b/modules/game_shaders/outfit.frag @@ -11,24 +11,19 @@ uniform vec4 bodyColor; uniform vec4 legsColor; uniform vec4 feetColor; -const vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0); -const vec4 red = vec4(1.0, 0.0, 0.0, 1.0); -const vec4 green = vec4(0.0, 1.0, 0.0, 1.0); -const vec4 blue = vec4(0.0, 0.0, 1.0, 1.0); - vec4 calcOutfitPixel() { vec4 pixel = texture2D(texture, textureCoords); vec4 maskColor = texture2D(maskTexture, textureCoords); vec4 outColor = vec4(1.0, 1.0, 1.0, 1.0); - if(maskColor == yellow) + if(maskColor.r > 0.1 && maskColor.g > 0.1) outColor = headColor; - else if(maskColor == red) + else if(maskColor.r > 0.1) outColor = bodyColor; - else if(maskColor == green) + else if(maskColor.g > 0.1) outColor = legsColor; - else if(maskColor == blue) + else if(maskColor.b > 0.1) outColor = feetColor; return pixel * outColor; diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp index 176ae75e..12638d55 100644 --- a/src/framework/graphics/painter.cpp +++ b/src/framework/graphics/painter.cpp @@ -60,8 +60,8 @@ void Painter::drawProgram(const PainterShaderProgramPtr& program, CoordsBuffer& return; program->setProjectionMatrix(m_projectionMatrix); - program->setOpacity(m_currentOpacity); - program->setColor(m_currentColor); + program->setOpacity(m_opacity); + program->setColor(m_color); program->draw(coordsBuffer, drawMode); } @@ -141,4 +141,32 @@ void Painter::setCompositionMode(Painter::CompositionMode compositionMode) glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); break; } + m_compostionMode = compositionMode; +} + +void Painter::saveAndResetState() +{ + m_oldCustomProgram = m_customProgram; + m_oldProjectionMatrix = m_projectionMatrix; + m_oldColor = m_color; + m_oldOpacity = m_opacity; + m_oldCompostionMode = m_compostionMode; + + releaseCustomProgram(); + setColor(Fw::white); + setOpacity(1); + setCompositionMode(CompositionMode_Normal); +} + +void Painter::restoreSavedState() +{ + setCustomProgram(m_oldCustomProgram); + setColor(m_oldColor); + setOpacity(m_oldOpacity); + setCompositionMode(m_oldCompostionMode); + + m_oldCustomProgram = nullptr; + m_oldColor = Fw::white; + m_oldOpacity = 1; + m_oldCompostionMode = CompositionMode_Normal; } diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h index 7a30632d..4693e353 100644 --- a/src/framework/graphics/painter.h +++ b/src/framework/graphics/painter.h @@ -50,11 +50,11 @@ public: void drawFilledRect(const Rect& dest); void drawBoundingRect(const Rect& dest, int innerLineWidth = 1); - void setColor(const Color& color) { m_currentColor = color; } - Color getColor() { return m_currentColor; } + void setColor(const Color& color) { m_color = color; } + Color getColor() { return m_color; } - void setOpacity(float opacity) { m_currentOpacity = opacity; } - float getOpacity() { return m_currentOpacity; } + void setOpacity(float opacity) { m_opacity = opacity; } + float getOpacity() { return m_opacity; } void setCustomProgram(PainterShaderProgramPtr program); void releaseCustomProgram() { m_customProgram = nullptr; } @@ -64,14 +64,24 @@ public: void setProjectionMatrix(const Matrix3& projectionMatrix) { m_projectionMatrix = projectionMatrix; } Matrix3 getProjectionMatrix() { return m_projectionMatrix; } + void saveAndResetState(); + void restoreSavedState(); + private: PainterShaderProgramPtr m_drawTexturedProgram; PainterShaderProgramPtr m_drawSolidColorProgram; PainterShaderProgramPtr m_customProgram; Matrix3 m_projectionMatrix; - Color m_currentColor; - float m_currentOpacity; + Color m_color; + float m_opacity; + CompositionMode m_compostionMode; CoordsBuffer m_coordsBuffer; + + PainterShaderProgramPtr m_oldCustomProgram; + Matrix3 m_oldProjectionMatrix; + Color m_oldColor; + float m_oldOpacity; + CompositionMode m_oldCompostionMode; }; extern Painter g_painter; diff --git a/src/framework/graphics/paintershaderprogram.cpp b/src/framework/graphics/paintershaderprogram.cpp index 9a79f8b7..9cf48bbb 100644 --- a/src/framework/graphics/paintershaderprogram.cpp +++ b/src/framework/graphics/paintershaderprogram.cpp @@ -26,6 +26,11 @@ #include "texturemanager.h" #include +PainterShaderProgram::PainterShaderProgram() +{ + m_textures.fill(std::make_tuple(-1, 0)); +} + bool PainterShaderProgram::link() { bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); @@ -63,12 +68,9 @@ void PainterShaderProgram::setOpacity(float opacity) void PainterShaderProgram::setUniformTexture(int location, const TexturePtr& texture, int index) { - if(index > 0) - glActiveTexture(GL_TEXTURE0 + index); - glBindTexture(GL_TEXTURE_2D, texture ? texture->getId() : 0); - if(index > 0) - glActiveTexture(GL_TEXTURE0); - setUniformValue(location, index); + assert(index >= 0 && index <= 1); + + m_textures[index] = std::make_tuple(location, texture ? texture->getId() : 0); } void PainterShaderProgram::setTexture(const TexturePtr& texture) @@ -112,6 +114,18 @@ void PainterShaderProgram::draw(const CoordsBuffer& coordsBuffer, DrawMode drawM mustDisableTexCoordsArray = true; } + for(int i=0;i<(int)m_textures.size();++i) { + int location = std::get<0>(m_textures[i]); + if(location == -1) + break; + int id = std::get<1>(m_textures[i]); + setUniformValue(location, i); + + glActiveTexture(GL_TEXTURE0+i); + glBindTexture(GL_TEXTURE_2D, id); + } + glActiveTexture(GL_TEXTURE0); + glDrawArrays(drawMode, 0, numVertices); if(mustDisableVertexArray) diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h index a9c376c8..4f492a5a 100644 --- a/src/framework/graphics/paintershaderprogram.h +++ b/src/framework/graphics/paintershaderprogram.h @@ -45,6 +45,8 @@ public: TriangleStrip = GL_TRIANGLE_STRIP }; + PainterShaderProgram(); + bool link(); void setProjectionMatrix(const Matrix3& projectionMatrix); @@ -57,6 +59,7 @@ public: private: DrawMode m_drawMode; Timer m_startTimer; + std::array, 4> m_textures; }; #endif diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index cb97145e..89e42b3d 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -122,8 +122,10 @@ std::vector Texture::getPixels() FrameBufferPtr fb(new FrameBuffer(m_size)); std::vector pixels(m_size.area()*4, 0); fb->bind(); + 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(); fb->release(); return pixels; } diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index 98e0dad3..5b8b70e5 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -66,16 +66,15 @@ int MASK_TEXTURE_UNIFORM = 14; void Creature::draw(const Point& dest, float scaleFactor) { int scaledTileSize = Otc::TILE_PIXELS * scaleFactor; - Point scaledWalkOffset = m_walkOffset * scaleFactor; if(m_showVolatileSquare) { g_painter.setColor(m_volatileSquareColor); - g_painter.drawBoundingRect(Rect(dest + scaledWalkOffset - (getDisplacement() + 3)*scaleFactor, Size(28*scaleFactor, 28*scaleFactor)), 2*scaleFactor); + g_painter.drawBoundingRect(Rect(dest + (m_walkOffset - getDisplacement() + 3)*scaleFactor, Size(28*scaleFactor, 28*scaleFactor)), 2*scaleFactor); } if(m_showStaticSquare) { g_painter.setColor(m_staticSquareColor); - g_painter.drawBoundingRect(Rect(dest + scaledWalkOffset - (getDisplacement() + 1)*scaleFactor, Size(scaledTileSize, scaledTileSize)), 2*scaleFactor); + g_painter.drawBoundingRect(Rect(dest + (m_walkOffset - getDisplacement() + 1)*scaleFactor, Size(scaledTileSize, scaledTileSize)), 2*scaleFactor); } g_painter.setColor(Fw::white); @@ -116,14 +115,15 @@ void Creature::draw(const Point& dest, float scaleFactor) if(!spriteTex) continue; + TexturePtr maskTex; if(getLayers() > 1) { int maskId = getSpriteId(w, h, 1, m_xPattern, m_yPattern, m_zPattern, m_animation); - TexturePtr maskTex = g_sprites.getSpriteTexture(maskId); - outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); + maskTex = g_sprites.getSpriteTexture(maskId); } + outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); - Rect drawRect((dest.x + scaledWalkOffset.x - w*scaledTileSize) - getDisplacementX()*scaleFactor, - (dest.y + scaledWalkOffset.y - h*scaledTileSize) - getDisplacementY()*scaleFactor, + Rect drawRect(dest.x + (m_walkOffset.x - w*Otc::TILE_PIXELS - getDisplacementX())*scaleFactor, + dest.y + (m_walkOffset.y - h*Otc::TILE_PIXELS - getDisplacementY())*scaleFactor, scaledTileSize, scaledTileSize); g_painter.drawTexturedRect(drawRect, spriteTex); } @@ -134,10 +134,10 @@ void Creature::draw(const Point& dest, float scaleFactor) } else if(m_outfit.getCategory() == ThingsType::Item) { for(int l = 0; l < getLayers(); l++) - internalDraw(dest + scaledWalkOffset, scaleFactor, l); + internalDraw(dest + m_walkOffset * scaleFactor, scaleFactor, l); } else if(m_outfit.getCategory() == ThingsType::Effect) - internalDraw(dest + scaledWalkOffset, scaleFactor, 0); + internalDraw(dest + m_walkOffset * scaleFactor, scaleFactor, 0); } void Creature::drawInformation(const Point& point, bool useGray, const Rect& parentRect)