diff --git a/data/images/shaders/snow.png b/data/images/shaders/snow.png new file mode 100644 index 00000000..6a43d684 Binary files /dev/null and b/data/images/shaders/snow.png differ diff --git a/data/shaders/map_snow_fragment.frag b/data/shaders/map_snow_fragment.frag new file mode 100644 index 00000000..6ffdb68c --- /dev/null +++ b/data/shaders/map_snow_fragment.frag @@ -0,0 +1,25 @@ + +varying vec2 v_TexCoord; + +uniform vec4 u_Color; +uniform sampler2D u_Tex0; +uniform sampler2D u_Tex1; +uniform float u_Time; +uniform vec2 u_WalkOffset; + +vec2 snowDirection = vec2(1.0, 0.2); +float snowSpeed = 0.08; +float snowPressure = 0.4; +float snowZoom = 0.6; + +void main() +{ + gl_FragColor = texture2D(u_Tex0, v_TexCoord) * u_Color; + + vec2 snowCoord = (v_TexCoord + vec2(u_WalkOffset.x, u_WalkOffset.y) + (snowDirection * u_Time * snowSpeed)) / snowZoom; + vec4 effectPixel = texture2D(u_Tex1, snowCoord) * snowPressure; + + gl_FragColor += (effectPixel.rgba); + if(gl_FragColor.a < 0.01) + discard; +} diff --git a/data/shaders/map_snow_vertex.frag b/data/shaders/map_snow_vertex.frag new file mode 100644 index 00000000..39881d62 --- /dev/null +++ b/data/shaders/map_snow_vertex.frag @@ -0,0 +1,19 @@ +attribute vec2 a_TexCoord; +attribute vec2 a_Vertex; + +varying vec2 v_TexCoord; +varying vec2 v_TexCoord2; + +uniform mat3 u_TextureMatrix; +uniform mat3 u_TransformMatrix; +uniform mat3 u_ProjectionMatrix; + +uniform vec2 u_Offset; +uniform vec2 u_Center; + +void main() +{ + gl_Position = vec4((u_ProjectionMatrix * u_TransformMatrix * vec3(a_Vertex.xy, 1.0)).xy, 1.0, 1.0); + v_TexCoord = (u_TextureMatrix * vec3(a_TexCoord,1.0)).xy; +} + diff --git a/modules/game_shaders/shaders.lua b/modules/game_shaders/shaders.lua index 180a8626..f570b749 100644 --- a/modules/game_shaders/shaders.lua +++ b/modules/game_shaders/shaders.lua @@ -6,6 +6,9 @@ function init() g_shaders.createShader("map_rainbow", "/shaders/map_rainbow_vertex", "/shaders/map_rainbow_fragment") g_shaders.addTexture("map_rainbow", "/images/shaders/rainbow.png") + + g_shaders.createShader("map_snow", "/shaders/map_snow_vertex", "/shaders/map_snow_fragment") + g_shaders.addTexture("map_snow", "/images/shaders/snow.png") -- use modules.game_interface.gameMapPanel:setShader("map_rainbow") to set shader diff --git a/src/client/mapview.cpp b/src/client/mapview.cpp index 524406f4..fd33ca93 100644 --- a/src/client/mapview.cpp +++ b/src/client/mapview.cpp @@ -155,7 +155,27 @@ void MapView::drawMapBackground(const Rect& rect, const TilePtr& crosshairTile) g_drawQueue->setOpacity(floorStart, fading); } -} + if(!m_shader.empty() && isFollowingCreature()) { + g_drawQueue->setShader(m_shader); + + Point walkOffset = transformPositionTo2D(getCameraPosition(), m_shaderPosition); + walkOffset.y = -walkOffset.y; + + g_drawQueue->setWalkOffset( + PointF( + (walkOffset.x / static_cast(m_optimizedSize.width())), + (walkOffset.y / static_cast(m_optimizedSize.height())) + ) + ); + } +} + +void MapView::setShader(const std::string& shader) +{ + m_shader = shader; + if (!m_shader.empty()) + m_shaderPosition = getCameraPosition(); +} void MapView::drawFloor(short floor, const Position& cameraPosition, const TilePtr& crosshairTile) { diff --git a/src/client/mapview.h b/src/client/mapview.h index 55c73862..63bfaf34 100644 --- a/src/client/mapview.h +++ b/src/client/mapview.h @@ -113,8 +113,11 @@ class MapView : public LuaObject void setFloorFading(int value) { m_floorFading = value; } void setCrosshair(const std::string& file); - //void setShader(const PainterShaderProgramPtr& shader, float fadein, float fadeout); - //PainterShaderProgramPtr getShader() { return m_shader; } + void setShader(const std::string& shader); + std::string getShader() + { + return m_shader; + } Position getPosition(const Point& point, const Size& mapSize); @@ -156,6 +159,9 @@ class MapView : public LuaObject bool m_drawPlayerBars = true; stdext::boolean m_smooth; + std::string m_shader; + Position m_shaderPosition; + stdext::timer m_fadingFloorTimers[Otc::MAX_Z + 1]; stdext::boolean m_follow; diff --git a/src/client/uimap.cpp b/src/client/uimap.cpp index f9e934be..11822b70 100644 --- a/src/client/uimap.cpp +++ b/src/client/uimap.cpp @@ -65,9 +65,6 @@ void UIMap::drawSelf(Fw::DrawPane drawPane) g_drawQueue->markMapPosition(); } else if(drawPane == Fw::MapBackgroundPane) { m_mapView->drawMapBackground(m_mapRect, getTile(m_mousePosition)); - if (!m_shader.empty()) { - g_drawQueue->setShader(m_shader); - } } else if (drawPane == Fw::MapForegroundPane) { m_mapView->drawMapForeground(m_mapRect); } diff --git a/src/client/uimap.h b/src/client/uimap.h index c6edbd9a..2a21bd3c 100644 --- a/src/client/uimap.h +++ b/src/client/uimap.h @@ -91,11 +91,14 @@ class UIMap : public UIWidget void setShader(const std::string& shader) { - m_shader = shader; + if(m_mapView) + m_mapView->setShader(shader); } std::string getShader() { - return m_shader; + if(m_mapView) + return m_mapView->getShader(); + return ""; } protected: @@ -115,7 +118,6 @@ class UIMap : public UIWidget bool m_limitVisibleRange; int m_maxZoomIn; int m_maxZoomOut; - std::string m_shader; }; #endif diff --git a/src/framework/core/graphicalapplication.cpp b/src/framework/core/graphicalapplication.cpp index 1f49c911..e9de9690 100644 --- a/src/framework/core/graphicalapplication.cpp +++ b/src/framework/core/graphicalapplication.cpp @@ -286,6 +286,11 @@ void GraphicalApplication::run() PainterShaderProgramPtr shader = nullptr; if (!toDrawMapQueue->getShader().empty()) { shader = g_shaders.getShader(toDrawMapQueue->getShader()); + + if(shader) { + auto walkOffset = toDrawMapQueue->getWalkOffset(); + shader->updateWalkOffset(walkOffset); + } } if (shader) { g_painter->setShaderProgram(shader); diff --git a/src/framework/graphics/drawqueue.h b/src/framework/graphics/drawqueue.h index 5f61b7bb..699f414c 100644 --- a/src/framework/graphics/drawqueue.h +++ b/src/framework/graphics/drawqueue.h @@ -327,6 +327,16 @@ class DrawQueue { return m_shader; } + void setWalkOffset(const PointF& offset) + { + m_walkOffset = offset; + } + + const PointF& getWalkOffset() + { + return m_walkOffset; + } + private: std::vector m_queue; std::vector m_conditions; @@ -336,6 +346,7 @@ class DrawQueue { bool m_useFrameBuffer = false; float m_scaling = 1.f; std::string m_shader; + PointF m_walkOffset; friend struct DrawQueueConditionMark; }; diff --git a/src/framework/graphics/paintershaderprogram.cpp b/src/framework/graphics/paintershaderprogram.cpp index c12a02e6..f9e31d43 100644 --- a/src/framework/graphics/paintershaderprogram.cpp +++ b/src/framework/graphics/paintershaderprogram.cpp @@ -58,6 +58,8 @@ void PainterShaderProgram::setupUniforms() bindUniformLocation(OFFSET_UNIFORM, "u_Offset"); bindUniformLocation(CENTER_UNIFORM, "u_Center"); + bindUniformLocation(MAP_WALKOFFSET_UNIFORM, "u_WalkOffset"); + // VALUES setUniformValue(TRANSFORM_MATRIX_UNIFORM, m_transformMatrix); setUniformValue(PROJECTION_MATRIX_UNIFORM, m_projectionMatrix); @@ -80,6 +82,7 @@ void PainterShaderProgram::setupUniforms() setUniformValue(RESOLUTION_UNIFORM, (float)m_resolution.width(), (float)m_resolution.height()); setUniformValue(OFFSET_UNIFORM, (float)m_offset.x, (float)m_offset.y); setUniformValue(CENTER_UNIFORM, (float)m_center.x, (float)m_center.y); + setUniformValue(MAP_WALKOFFSET_UNIFORM, (float)m_walkOffset.x, (float)m_walkOffset.y); } bool PainterShaderProgram::link() @@ -202,6 +205,17 @@ void PainterShaderProgram::updateTime() m_time = time; } +void PainterShaderProgram::updateWalkOffset(const PointF& offset) +{ + if (m_walkOffset == offset) + return; + + m_walkOffset = offset; + + bind(); + setUniformValue(MAP_WALKOFFSET_UNIFORM, m_walkOffset.x, m_walkOffset.y); +} + void PainterShaderProgram::addMultiTexture(const std::string& file) { if (m_multiTextures.size() > 3) diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h index 4fa79792..aba66a44 100644 --- a/src/framework/graphics/paintershaderprogram.h +++ b/src/framework/graphics/paintershaderprogram.h @@ -53,7 +53,8 @@ class PainterShaderProgram : public ShaderProgram { RESOLUTION_UNIFORM = 13, OFFSET_UNIFORM = 14, - CENTER_UNIFORM = 15 + CENTER_UNIFORM = 15, + MAP_WALKOFFSET_UNIFORM = 16 }; friend class Painter; @@ -75,6 +76,7 @@ class PainterShaderProgram : public ShaderProgram { void setOffset(const Point& offset); void setCenter(const Point& center); void updateTime(); + void updateWalkOffset(const PointF& offset); void addMultiTexture(const std::string& file); void bindMultiTextures(); @@ -95,6 +97,7 @@ class PainterShaderProgram : public ShaderProgram { Matrix3 m_textureMatrix; Size m_resolution; Point m_offset; + PointF m_walkOffset; Point m_center; float m_time; std::vector m_multiTextures;