From 7e33efbe9a293dbf8919e2eee584b6571339227d Mon Sep 17 00:00:00 2001 From: Renato Date: Wed, 1 Mar 2023 17:02:40 -0300 Subject: [PATCH 1/4] first commit --- src/client/lightview.cpp | 100 +++++++++++++++++------ src/client/lightview.h | 33 +++++--- src/client/mapview.cpp | 10 +-- src/framework/graphics/coordsbuffer.h | 7 ++ src/framework/graphics/drawpool.cpp | 2 +- src/framework/graphics/drawpoolmanager.h | 1 + src/framework/graphics/texture.cpp | 5 ++ src/framework/graphics/texture.h | 1 + src/framework/graphics/vertexarray.h | 15 ++++ 9 files changed, 130 insertions(+), 44 deletions(-) diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index 40e0c25d14..1c138e6f14 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -26,54 +26,104 @@ #include "mapview.h" #include "spritemanager.h" -LightView::LightView() : m_pool(g_drawPool.get(DrawPoolType::LIGHT)) {} +LightView::LightView() : m_pool(g_drawPool.get(DrawPoolType::LIGHT)) {} -void LightView::setSmooth(bool enabled) const { m_pool->setSmooth(enabled); } - -void LightView::resize(const Size& size, const uint8_t tileSize) { m_pool->resize(size * (m_tileSize = tileSize)); } +void LightView::resize(const Size& size, const uint8_t tileSize) { + m_lightTexture = nullptr; + m_mapSize = size; + m_tiles.resize(size.area(), TileShade{ 0, 0 }); +} void LightView::addLightSource(const Point& pos, const Light& light) { if (!isDark()) return; - if (!m_sources.empty()) { - auto& prevLight = m_sources.back(); + if (!m_lights.empty()) { + auto& prevLight = m_lights.back(); if (prevLight.pos == pos && prevLight.color == light.color) { - prevLight.intensity = std::max(prevLight.intensity, light.intensity); + prevLight.intensity = std::max(prevLight.intensity, light.intensity); return; } } + m_lights.emplace_back(pos, light.intensity, light.color); +} - m_sources.emplace_back(pos, light.color, light.intensity, g_drawPool.getOpacity()); +void LightView::setFieldBrightness(const Point& pos, size_t start, uint8_t color) +{ + size_t index = (pos.y / g_drawPool.getScaledSpriteSize()) * m_mapSize.width() + (pos.x / g_drawPool.getScaledSpriteSize()); + if (index >= m_tiles.size()) return; + m_tiles[index].start = start; + m_tiles[index].color = color; } void LightView::draw(const Rect& dest, const Rect& src) { + static std::vector buffer; + // draw light, only if there is darkness m_pool->setEnable(isDark()); if (!isDark() || !m_pool->isValid()) return; - g_drawPool.use(m_pool->getType(), dest, src, m_globalLightColor); - - const float size = m_tileSize * 3.3; + if (buffer.size() < 4u * m_mapSize.area()) + buffer.resize(m_mapSize.area() * 4); - bool _clr = true; - for (const auto& light : m_sources) { - if (light.color) { - const auto& color = Color::from8bit(light.color, std::min(light.opacity, light.intensity / 6.f)); - const uint16_t radius = light.intensity * m_tileSize; + updateCoords(dest, src); + g_drawPool.use(m_pool->getType()); - g_drawPool.setBlendEquation(BlendEquation::MAX, true); - g_drawPool.addTexturedRect(Rect(light.pos - radius, Size(radius * 2)), g_sprites.getLightTexture(), color); - _clr = true; - } else { - // Empty the lightings references - if (_clr) { g_drawPool.flush(); _clr = false; } + for (int x = 0; x < m_mapSize.width(); ++x) { + for (int y = 0; y < m_mapSize.height(); ++y) { + const Point pos(x * g_drawPool.getScaledSpriteSize() + g_drawPool.getScaledSpriteSize() / 2, y * g_drawPool.getScaledSpriteSize() + g_drawPool.getScaledSpriteSize() / 2); - g_drawPool.setOpacity(light.opacity, true); - g_drawPool.addTexturedRect(Rect(light.pos - m_tileSize * 1.8, size, size), g_sprites.getShadeTexture(), m_globalLightColor); + int index = (y * m_mapSize.width() + x); + int colorIndex = index * 4; + buffer[colorIndex] = m_globalLightColor.r(); + buffer[colorIndex + 1] = m_globalLightColor.g(); + buffer[colorIndex + 2] = m_globalLightColor.b(); + buffer[colorIndex + 3] = 255; // alpha channel + for (size_t i = m_tiles[index].start; i < m_lights.size(); ++i) { + const auto& light = m_lights[i]; + float distance = std::sqrt((pos.x - light.pos.x) * (pos.x - light.pos.x) + + (pos.y - light.pos.y) * (pos.y - light.pos.y)); + distance /= g_drawPool.getScaledSpriteSize(); + float intensity = (-distance + light.intensity) * 0.2f; + if (intensity < 0.01f) continue; + if (intensity > 1.0f) intensity = 1.0f; + Color lightColor = Color::from8bit(light.color) * intensity; + buffer[colorIndex] = std::max(buffer[colorIndex], lightColor.r()); + buffer[colorIndex + 1] = std::max(buffer[colorIndex + 1], lightColor.g()); + buffer[colorIndex + 2] = std::max(buffer[colorIndex + 2], lightColor.b()); + } } } - m_sources.clear(); + m_lights.clear(); + + g_drawPool.addAction([&] { + if (!m_lightTexture) { + m_lightTexture = std::make_shared(m_mapSize); + m_lightTexture->setSmooth(true); + } + + m_lightTexture->updatePixels(buffer.data()); + + g_painter->resetColor(); + g_painter->setCompositionMode(CompositionMode::MULTIPLY); + g_painter->setTexture(m_lightTexture.get()); + g_painter->drawCoords(m_coords); + }); +} + +void LightView::updateCoords(const Rect& dest, const Rect& src) { + if (m_dest != dest || m_src != src) { + m_dest = dest; + m_src = src; + + Point offset = src.topLeft(); + Size size = src.size(); + + m_coords.clear(); + m_coords.addRect(RectF(dest.left(), dest.top(), dest.width(), dest.height()), + RectF((float)offset.x / g_drawPool.getScaledSpriteSize(), (float)offset.y / g_drawPool.getScaledSpriteSize(), + (float)size.width() / g_drawPool.getScaledSpriteSize(), (float)size.height() / g_drawPool.getScaledSpriteSize())); + } } diff --git a/src/client/lightview.h b/src/client/lightview.h index 380788fff6..9435ab33ab 100644 --- a/src/client/lightview.h +++ b/src/client/lightview.h @@ -36,7 +36,7 @@ class LightView : public LuaObject void draw(const Rect& dest, const Rect& src); void addLightSource(const Point& pos, const Light& light); - void addShade(const Point& pos, const float opacity) { m_sources.emplace_back(pos, opacity); } + void setFieldBrightness(const Point& pos, size_t start, uint8_t color); void setGlobalLight(const Light& light) { @@ -45,29 +45,36 @@ class LightView : public LuaObject m_pool->repaint(); } - void setSmooth(bool enabled) const; - const Light& getGlobalLight() const { return m_globalLight; } bool isDark() const { return m_globalLight.intensity < 250; } + size_t size() { return m_lights.size(); } + private: - struct Source + struct TileLight : public Light { - Source(const Point& p, float o) : pos(p), opacity(o) {}; - Source(const Point& p, uint8_t c, uint16_t i, float o) : pos(p), color(c), intensity(i), opacity(o) {}; - Point pos; - uint8_t color{ 0 }; - uint16_t intensity{ 0 }; - float opacity{ 1.f }; + TileLight(const Point& pos, uint8_t intensity, uint8_t color) : Light(intensity, color), pos(pos) {} }; - uint8_t m_tileSize{ SPRITE_SIZE }; + struct TileShade + { + size_t start; + uint8_t color; + }; + + void updateCoords(const Rect& dest, const Rect& src); Light m_globalLight; Color m_globalLightColor{ Color::white }; - DrawPoolFramed* m_pool{ nullptr }; + DrawPool* m_pool{ nullptr }; + + TexturePtr m_lightTexture; + Size m_mapSize; + std::vector m_lights; + std::vector m_tiles; - std::vector m_sources; + Rect m_dest, m_src; + CoordsBuffer m_coords; }; diff --git a/src/client/mapview.cpp b/src/client/mapview.cpp index b4bd40abbf..69b6f4aa13 100644 --- a/src/client/mapview.cpp +++ b/src/client/mapview.cpp @@ -133,6 +133,8 @@ void MapView::drawFloor() if (m_drawHealthBars) { flags |= Otc::DrawBars; } if (m_drawManaBar) { flags |= Otc::DrawManaBar; } + size_t lightFloorStart = m_lightView ? m_lightView->size() : 0; + for (int_fast8_t z = m_floorMax; z >= m_floorMin; --z) { const float fadeLevel = getFadeLevel(z); if (fadeLevel == 0.f) break; @@ -149,7 +151,7 @@ void MapView::drawFloor() if (alwaysTransparent && tile->getPosition().isInRange(_camera, TRANSPARENT_FLOOR_VIEW_RANGE, TRANSPARENT_FLOOR_VIEW_RANGE, true)) continue; - lightView->addShade(transformPositionTo2D(tile->getPosition(), cameraPosition), fadeLevel); + m_lightView->setFieldBrightness(transformPositionTo2D(tile->getPosition(), cameraPosition), lightFloorStart, 0); } } @@ -340,7 +342,7 @@ void MapView::updateVisibleTiles() tile->onAddInMapView(); } - if (isDrawingLights() && tile->canShade(static_self_cast())) + if (isDrawingLights() && (tile->isFullyOpaque() || tile->isFullGround())) floor.shades.emplace_back(tile); if (addTile || !floor.shades.empty()) { @@ -399,9 +401,9 @@ void MapView::updateGeometry(const Size& visibleDimension) m_virtualCenterOffset = (drawDimension / 2 - Size(1)).toPoint(); m_rectDimension = { 0, 0, bufferSize }; + if (m_lightView) m_lightView->resize(m_drawDimension, tileSize); g_mainDispatcher.addEvent([=, this]() { m_pool->resize(bufferSize); - if (m_lightView) m_lightView->resize(drawDimension, tileSize); }); const uint8_t left = std::min(g_map.getAwareRange().left, (m_drawDimension.width() / 2) - 1); @@ -547,8 +549,6 @@ void MapView::setAntiAliasingMode(const AntialiasingMode mode) g_drawPool.get(DrawPoolType::MAP) ->setSmooth(mode != ANTIALIASING_DISABLED); - if (m_lightView) m_lightView->setSmooth(mode != ANTIALIASING_DISABLED); - updateGeometry(m_visibleDimension); } diff --git a/src/framework/graphics/coordsbuffer.h b/src/framework/graphics/coordsbuffer.h index 9357574103..948a27fd76 100644 --- a/src/framework/graphics/coordsbuffer.h +++ b/src/framework/graphics/coordsbuffer.h @@ -48,6 +48,13 @@ class CoordsBuffer if (src.isValid()) m_textureCoordArray.addRect(src); } + + void addRect(const RectF& dest, const RectF& src) + { + m_vertexArray.addRect(dest); + m_textureCoordArray.addRect(src); + } + void addQuad(const Rect& dest, const Rect& src) { m_vertexArray.addQuad(dest); diff --git a/src/framework/graphics/drawpool.cpp b/src/framework/graphics/drawpool.cpp index c8c7c32dee..ebd2c61a54 100644 --- a/src/framework/graphics/drawpool.cpp +++ b/src/framework/graphics/drawpool.cpp @@ -31,7 +31,7 @@ FPS60 = 1000 / 60; DrawPool* DrawPool::create(const DrawPoolType type) { DrawPool* pool; - if (type == DrawPoolType::MAP || type == DrawPoolType::LIGHT || type == DrawPoolType::FOREGROUND) { + if (type == DrawPoolType::MAP || type == DrawPoolType::FOREGROUND) { pool = new DrawPoolFramed; const auto& frameBuffer = pool->toPoolFramed()->m_framebuffer; diff --git a/src/framework/graphics/drawpoolmanager.h b/src/framework/graphics/drawpoolmanager.h index 163fbd7d75..1c21feadf5 100644 --- a/src/framework/graphics/drawpoolmanager.h +++ b/src/framework/graphics/drawpoolmanager.h @@ -85,6 +85,7 @@ class DrawPoolManager void setScaleFactor(float scale) const { getCurrentPool()->setScaleFactor(scale); } inline float getScaleFactor() const { return getCurrentPool()->getScaleFactor(); } + inline uint16_t getScaledSpriteSize() const { return SPRITE_SIZE * getScaleFactor(); } void flush() const { if (getCurrentPool()) getCurrentPool()->flush(); } diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index 0adf09a472..9993260a59 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -80,6 +80,11 @@ Texture* Texture::create() } void Texture::updateImage(const ImagePtr& image) { m_image = image; setupSize(image->getSize()); } + +void Texture::updatePixels(uint8_t* pixels, int level, int channels, bool compress) { + bind(); + setupPixels(level, m_size, pixels, channels, compress); +} void Texture::uploadPixels(const ImagePtr& image, bool buildMipmaps, bool compress) { if (!setupSize(image->getSize())) diff --git a/src/framework/graphics/texture.h b/src/framework/graphics/texture.h index de69f1ae40..d89194ab9a 100644 --- a/src/framework/graphics/texture.h +++ b/src/framework/graphics/texture.h @@ -35,6 +35,7 @@ class Texture Texture* create(); void uploadPixels(const ImagePtr& image, bool buildMipmaps = false, bool compress = false); void updateImage(const ImagePtr& image); + void updatePixels(uint8_t* pixels, int level = 0, int channels = 4, bool compress = false); virtual void buildHardwareMipmaps(); diff --git a/src/framework/graphics/vertexarray.h b/src/framework/graphics/vertexarray.h index 3081285963..4a8baaeda8 100644 --- a/src/framework/graphics/vertexarray.h +++ b/src/framework/graphics/vertexarray.h @@ -66,6 +66,21 @@ class VertexArray addVertex(right, bottom); } + void addRect(const RectF& rect) + { + float top = rect.top(); + float right = rect.right() + 1.f; + float bottom = rect.bottom() + 1.f; + float left = rect.left(); + + addVertex(left, top); + addVertex(right, top); + addVertex(left, bottom); + addVertex(left, bottom); + addVertex(right, top); + addVertex(right, bottom); + } + void addQuad(const Rect& rect) { const float top = rect.top(); From 9e15abf5213b1b708150d05bba510780c9306179 Mon Sep 17 00:00:00 2001 From: Renato Date: Wed, 1 Mar 2023 21:13:43 -0300 Subject: [PATCH 2/4] improv --- src/client/lightview.cpp | 99 ++++++++++++++++++++++++---------------- src/client/lightview.h | 14 ++++-- src/client/mapview.cpp | 15 +++--- src/client/mapview.h | 7 +++ src/client/tile.cpp | 13 ------ src/client/tile.h | 2 +- 6 files changed, 86 insertions(+), 64 deletions(-) diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index 1c138e6f14..3a32bb234c 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -31,7 +31,9 @@ LightView::LightView() : m_pool(g_drawPool.get(DrawPoolType::LIGHT)) { void LightView::resize(const Size& size, const uint8_t tileSize) { m_lightTexture = nullptr; m_mapSize = size; - m_tiles.resize(size.area(), TileShade{ 0, 0 }); + m_tiles.resize(size.area(), {}); + if (m_pixels.size() < 4u * m_mapSize.area()) + m_pixels.resize(m_mapSize.area() * 4); } void LightView::addLightSource(const Point& pos, const Light& light) @@ -45,72 +47,50 @@ void LightView::addLightSource(const Point& pos, const Light& light) return; } } - m_lights.emplace_back(pos, light.intensity, light.color); + m_lights.emplace_back(pos, light.intensity, light.color, g_drawPool.getOpacity()); + + stdext::hash_union(m_updatingHash, pos.hash()); + stdext::hash_combine(m_updatingHash, light.intensity); + stdext::hash_combine(m_updatingHash, light.color); + stdext::hash_combine(m_updatingHash, g_drawPool.getOpacity()); } -void LightView::setFieldBrightness(const Point& pos, size_t start, uint8_t color) +void LightView::setFieldBrightness(const Point& pos, size_t start, float brightness) { size_t index = (pos.y / g_drawPool.getScaledSpriteSize()) * m_mapSize.width() + (pos.x / g_drawPool.getScaledSpriteSize()); if (index >= m_tiles.size()) return; - m_tiles[index].start = start; - m_tiles[index].color = color; + + auto& tile = m_tiles[index]; + + tile.start = start; + tile.brightness = brightness; } void LightView::draw(const Rect& dest, const Rect& src) { - static std::vector buffer; - // draw light, only if there is darkness m_pool->setEnable(isDark()); if (!isDark() || !m_pool->isValid()) return; - if (buffer.size() < 4u * m_mapSize.area()) - buffer.resize(m_mapSize.area() * 4); - updateCoords(dest, src); g_drawPool.use(m_pool->getType()); - for (int x = 0; x < m_mapSize.width(); ++x) { - for (int y = 0; y < m_mapSize.height(); ++y) { - const Point pos(x * g_drawPool.getScaledSpriteSize() + g_drawPool.getScaledSpriteSize() / 2, y * g_drawPool.getScaledSpriteSize() + g_drawPool.getScaledSpriteSize() / 2); - - int index = (y * m_mapSize.width() + x); - int colorIndex = index * 4; - buffer[colorIndex] = m_globalLightColor.r(); - buffer[colorIndex + 1] = m_globalLightColor.g(); - buffer[colorIndex + 2] = m_globalLightColor.b(); - buffer[colorIndex + 3] = 255; // alpha channel - for (size_t i = m_tiles[index].start; i < m_lights.size(); ++i) { - const auto& light = m_lights[i]; - float distance = std::sqrt((pos.x - light.pos.x) * (pos.x - light.pos.x) + - (pos.y - light.pos.y) * (pos.y - light.pos.y)); - distance /= g_drawPool.getScaledSpriteSize(); - float intensity = (-distance + light.intensity) * 0.2f; - if (intensity < 0.01f) continue; - if (intensity > 1.0f) intensity = 1.0f; - Color lightColor = Color::from8bit(light.color) * intensity; - buffer[colorIndex] = std::max(buffer[colorIndex], lightColor.r()); - buffer[colorIndex + 1] = std::max(buffer[colorIndex + 1], lightColor.g()); - buffer[colorIndex + 2] = std::max(buffer[colorIndex + 2], lightColor.b()); - } - } - } - - m_lights.clear(); - - g_drawPool.addAction([&] { + g_drawPool.addAction([&, updatePixel = updatePixels()] { if (!m_lightTexture) { m_lightTexture = std::make_shared(m_mapSize); m_lightTexture->setSmooth(true); } - m_lightTexture->updatePixels(buffer.data()); + if (updatePixel) + m_lightTexture->updatePixels(m_pixels.data()); g_painter->resetColor(); g_painter->setCompositionMode(CompositionMode::MULTIPLY); g_painter->setTexture(m_lightTexture.get()); g_painter->drawCoords(m_coords); }); + + m_lights.clear(); } void LightView::updateCoords(const Rect& dest, const Rect& src) { @@ -127,3 +107,42 @@ void LightView::updateCoords(const Rect& dest, const Rect& src) { (float)size.width() / g_drawPool.getScaledSpriteSize(), (float)size.height() / g_drawPool.getScaledSpriteSize())); } } + +bool LightView::updatePixels() { + bool updatePixel = m_updatingHash != m_hash; + if (updatePixel) { + for (int x = 0; x < m_mapSize.width(); ++x) { + for (int y = 0; y < m_mapSize.height(); ++y) { + const Point pos(x * g_drawPool.getScaledSpriteSize() + g_drawPool.getScaledSpriteSize() / 2, y * g_drawPool.getScaledSpriteSize() + g_drawPool.getScaledSpriteSize() / 2); + + int index = (y * m_mapSize.width() + x); + + const auto& tile = m_tiles[index]; + + int colorIndex = index * 4; + m_pixels[colorIndex] = m_globalLightColor.r() * tile.brightness; + m_pixels[colorIndex + 1] = m_globalLightColor.g() * tile.brightness; + m_pixels[colorIndex + 2] = m_globalLightColor.b() * tile.brightness; + m_pixels[colorIndex + 3] = 255; // alpha channel + for (size_t i = tile.start; i < m_lights.size(); ++i) { + const auto& light = m_lights[i]; + float distance = std::sqrt((pos.x - light.pos.x) * (pos.x - light.pos.x) + + (pos.y - light.pos.y) * (pos.y - light.pos.y)); + distance /= g_drawPool.getScaledSpriteSize(); + float intensity = (-distance + (light.intensity * light.brightness)) * 0.2f; + if (intensity < 0.01f) continue; + if (intensity > 1.0f) intensity = 1.0f; + Color lightColor = Color::from8bit(light.color) * intensity; + m_pixels[colorIndex] = std::max(m_pixels[colorIndex], lightColor.r()); + m_pixels[colorIndex + 1] = std::max(m_pixels[colorIndex + 1], lightColor.g()); + m_pixels[colorIndex + 2] = std::max(m_pixels[colorIndex + 2], lightColor.b()); + } + } + } + + m_hash = m_updatingHash; + m_updatingHash = 0; + } + + return updatePixel; +} diff --git a/src/client/lightview.h b/src/client/lightview.h index 9435ab33ab..0394acb900 100644 --- a/src/client/lightview.h +++ b/src/client/lightview.h @@ -36,7 +36,7 @@ class LightView : public LuaObject void draw(const Rect& dest, const Rect& src); void addLightSource(const Point& pos, const Light& light); - void setFieldBrightness(const Point& pos, size_t start, uint8_t color); + void setFieldBrightness(const Point& pos, size_t start, float brightness); void setGlobalLight(const Light& light) { @@ -54,16 +54,21 @@ class LightView : public LuaObject struct TileLight : public Light { Point pos; - TileLight(const Point& pos, uint8_t intensity, uint8_t color) : Light(intensity, color), pos(pos) {} + float brightness{ 1.f }; + + TileLight(const Point& pos, uint8_t intensity, uint8_t color, float brightness) : Light(intensity, color), pos(pos), brightness(brightness) {} }; struct TileShade { - size_t start; - uint8_t color; + size_t start{ 0 }; + float brightness{ 0 }; }; void updateCoords(const Rect& dest, const Rect& src); + bool updatePixels(); + + size_t m_hash{ 0 }, m_updatingHash{ 0 }; Light m_globalLight; Color m_globalLightColor{ Color::white }; @@ -74,6 +79,7 @@ class LightView : public LuaObject Size m_mapSize; std::vector m_lights; std::vector m_tiles; + std::vector m_pixels; Rect m_dest, m_src; CoordsBuffer m_coords; diff --git a/src/client/mapview.cpp b/src/client/mapview.cpp index 69b6f4aa13..f23d302431 100644 --- a/src/client/mapview.cpp +++ b/src/client/mapview.cpp @@ -133,8 +133,6 @@ void MapView::drawFloor() if (m_drawHealthBars) { flags |= Otc::DrawBars; } if (m_drawManaBar) { flags |= Otc::DrawManaBar; } - size_t lightFloorStart = m_lightView ? m_lightView->size() : 0; - for (int_fast8_t z = m_floorMax; z >= m_floorMin; --z) { const float fadeLevel = getFadeLevel(z); if (fadeLevel == 0.f) break; @@ -146,12 +144,14 @@ void MapView::drawFloor() const auto& map = m_cachedVisibleTiles[z]; - if (isDrawingLights() && z < m_floorMax) { + if (m_lightView && (m_fadeType != FadeType::OUT$ || fadeLevel == 1.f)) { + const size_t lightFloorStart = m_lightView ? m_lightView->size() : 0; + for (const auto& tile : map.shades) { if (alwaysTransparent && tile->getPosition().isInRange(_camera, TRANSPARENT_FLOOR_VIEW_RANGE, TRANSPARENT_FLOOR_VIEW_RANGE, true)) continue; - m_lightView->setFieldBrightness(transformPositionTo2D(tile->getPosition(), cameraPosition), lightFloorStart, 0); + m_lightView->setFieldBrightness(transformPositionTo2D(tile->getPosition(), cameraPosition), lightFloorStart, fadeLevel); } } @@ -285,15 +285,18 @@ void MapView::updateVisibleTiles() // Fading System by Kondra https://github.com/OTCv8/otclientv8 if (!m_lastCameraPosition.isValid() || m_lastCameraPosition.z != m_posInfo.camera.z || m_lastCameraPosition.distance(m_posInfo.camera) >= 3) { + m_fadeType = FadeType::NONE$; for (int iz = m_cachedLastVisibleFloor; iz >= cachedFirstVisibleFloor; --iz) { m_fadingFloorTimers[iz].restart(m_floorFading * 1000); } } else if (prevFirstVisibleFloor < m_cachedFirstVisibleFloor) { // hiding new floor + m_fadeType = FadeType::OUT$; for (int iz = prevFirstVisibleFloor; iz < m_cachedFirstVisibleFloor; ++iz) { const int shift = std::max(0, m_floorFading - m_fadingFloorTimers[iz].elapsed_millis()); m_fadingFloorTimers[iz].restart(shift * 1000); } } else if (prevFirstVisibleFloor > m_cachedFirstVisibleFloor) { // showing floor + m_fadeType = FadeType::IN$; m_lastFadeLevel = 0.f; for (int iz = m_cachedFirstVisibleFloor; iz < prevFirstVisibleFloor; ++iz) { const int shift = std::max(0, m_floorFading - m_fadingFloorTimers[iz].elapsed_millis()); @@ -321,7 +324,7 @@ void MapView::updateVisibleTiles() Position tilePos = m_posInfo.camera.translated(ix - m_virtualCenterOffset.x, iy - m_virtualCenterOffset.y); // adjust tilePos to the wanted floor tilePos.coveredUp(m_posInfo.camera.z - iz); - if (const TilePtr& tile = g_map.getTile(tilePos)) { + if (const auto& tile = g_map.getTile(tilePos)) { // skip tiles that have nothing if (!tile->isDrawable()) continue; @@ -342,7 +345,7 @@ void MapView::updateVisibleTiles() tile->onAddInMapView(); } - if (isDrawingLights() && (tile->isFullyOpaque() || tile->isFullGround())) + if (isDrawingLights() && tile->canShade()) floor.shades.emplace_back(tile); if (addTile || !floor.shades.empty()) { diff --git a/src/client/mapview.h b/src/client/mapview.h index b14258d3f2..7249d0ddff 100644 --- a/src/client/mapview.h +++ b/src/client/mapview.h @@ -191,6 +191,11 @@ class MapView : public LuaObject friend class LightView; private: + enum class FadeType + { + NONE$, IN$, OUT$ + }; + struct MapObject { std::vector shades; @@ -289,6 +294,8 @@ class MapView : public LuaObject bool m_drawHighlightTarget{ false }; bool m_shiftPressed{ false }; + FadeType m_fadeType{ FadeType::NONE$ }; + AntialiasingMode m_antiAliasingMode{ AntialiasingMode::ANTIALIASING_DISABLED }; std::array m_cachedVisibleTiles; diff --git a/src/client/tile.cpp b/src/client/tile.cpp index c26696eeaa..ebea72ac42 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -611,19 +611,6 @@ void Tile::onAddInMapView() } } -bool Tile::canShade(const MapViewPtr& mapView) -{ - for (const auto dir : { Otc::North, Otc::NorthWest, Otc::West }) { - const auto& pos = m_position.translatedToDirection(dir); - const auto& tile = g_map.getTile(pos); - - if ((!tile && mapView->isInRangeEx(pos, true)) || (tile && !tile->isFullyOpaque() && !tile->isFullGround() && !tile->hasTopGround(true))) - return false; - } - - return isFullyOpaque() || hasTopGround(true) || isFullGround(); -} - bool Tile::hasBlockingCreature() const { for (const auto& thing : m_things) diff --git a/src/client/tile.h b/src/client/tile.h index 2ff968ee1b..f1dfaa4d56 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -161,7 +161,7 @@ class Tile : public LuaObject bool limitsFloorsView(bool isFreeView = false); - bool canShade(const MapViewPtr& mapView); + bool canShade() { return isFullyOpaque() || hasTopGround() || isFullGround(); } bool canRender(uint32_t& flags, const Position& cameraPosition, AwareRange viewPort); bool canErase() { From ec3d2f05af7d7fc2d4196ae24a197008b7d5ccbd Mon Sep 17 00:00:00 2001 From: Renato Date: Wed, 1 Mar 2023 22:03:42 -0300 Subject: [PATCH 3/4] Update lightview.cpp --- src/client/lightview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index 3a32bb234c..095eb3bfa8 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -31,7 +31,7 @@ LightView::LightView() : m_pool(g_drawPool.get(DrawPoolType::LIGHT)) { void LightView::resize(const Size& size, const uint8_t tileSize) { m_lightTexture = nullptr; m_mapSize = size; - m_tiles.resize(size.area(), {}); + m_tiles.resize(size.area()); if (m_pixels.size() < 4u * m_mapSize.area()) m_pixels.resize(m_mapSize.area() * 4); } @@ -91,6 +91,7 @@ void LightView::draw(const Rect& dest, const Rect& src) }); m_lights.clear(); + m_tiles.assign(m_mapSize.area(), {}); } void LightView::updateCoords(const Rect& dest, const Rect& src) { From bc8dbc5bae57b6c8b581cb12d99f423a291aafa5 Mon Sep 17 00:00:00 2001 From: Renato Date: Wed, 1 Mar 2023 23:25:55 -0300 Subject: [PATCH 4/4] update --- src/client/lightview.cpp | 18 ++++++------------ src/client/lightview.h | 16 ++++------------ src/client/mapview.cpp | 4 +--- 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index 095eb3bfa8..9caad27aa0 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -55,15 +55,11 @@ void LightView::addLightSource(const Point& pos, const Light& light) stdext::hash_combine(m_updatingHash, g_drawPool.getOpacity()); } -void LightView::setFieldBrightness(const Point& pos, size_t start, float brightness) +void LightView::resetShade(const Point& pos) { size_t index = (pos.y / g_drawPool.getScaledSpriteSize()) * m_mapSize.width() + (pos.x / g_drawPool.getScaledSpriteSize()); if (index >= m_tiles.size()) return; - - auto& tile = m_tiles[index]; - - tile.start = start; - tile.brightness = brightness; + m_tiles[index] = m_lights.size(); } void LightView::draw(const Rect& dest, const Rect& src) @@ -118,14 +114,12 @@ bool LightView::updatePixels() { int index = (y * m_mapSize.width() + x); - const auto& tile = m_tiles[index]; - int colorIndex = index * 4; - m_pixels[colorIndex] = m_globalLightColor.r() * tile.brightness; - m_pixels[colorIndex + 1] = m_globalLightColor.g() * tile.brightness; - m_pixels[colorIndex + 2] = m_globalLightColor.b() * tile.brightness; + m_pixels[colorIndex] = m_globalLightColor.r(); + m_pixels[colorIndex + 1] = m_globalLightColor.g(); + m_pixels[colorIndex + 2] = m_globalLightColor.b(); m_pixels[colorIndex + 3] = 255; // alpha channel - for (size_t i = tile.start; i < m_lights.size(); ++i) { + for (size_t i = m_tiles[index]; i < m_lights.size(); ++i) { const auto& light = m_lights[i]; float distance = std::sqrt((pos.x - light.pos.x) * (pos.x - light.pos.x) + (pos.y - light.pos.y) * (pos.y - light.pos.y)); diff --git a/src/client/lightview.h b/src/client/lightview.h index 0394acb900..84d9126236 100644 --- a/src/client/lightview.h +++ b/src/client/lightview.h @@ -36,7 +36,7 @@ class LightView : public LuaObject void draw(const Rect& dest, const Rect& src); void addLightSource(const Point& pos, const Light& light); - void setFieldBrightness(const Point& pos, size_t start, float brightness); + void resetShade(const Point& pos); void setGlobalLight(const Light& light) { @@ -48,8 +48,6 @@ class LightView : public LuaObject const Light& getGlobalLight() const { return m_globalLight; } bool isDark() const { return m_globalLight.intensity < 250; } - size_t size() { return m_lights.size(); } - private: struct TileLight : public Light { @@ -59,12 +57,6 @@ class LightView : public LuaObject TileLight(const Point& pos, uint8_t intensity, uint8_t color, float brightness) : Light(intensity, color), pos(pos), brightness(brightness) {} }; - struct TileShade - { - size_t start{ 0 }; - float brightness{ 0 }; - }; - void updateCoords(const Rect& dest, const Rect& src); bool updatePixels(); @@ -75,12 +67,12 @@ class LightView : public LuaObject DrawPool* m_pool{ nullptr }; - TexturePtr m_lightTexture; - Size m_mapSize; std::vector m_lights; - std::vector m_tiles; + std::vector m_tiles; std::vector m_pixels; + Size m_mapSize; Rect m_dest, m_src; CoordsBuffer m_coords; + TexturePtr m_lightTexture; }; diff --git a/src/client/mapview.cpp b/src/client/mapview.cpp index f23d302431..d6cfadc46f 100644 --- a/src/client/mapview.cpp +++ b/src/client/mapview.cpp @@ -145,13 +145,11 @@ void MapView::drawFloor() const auto& map = m_cachedVisibleTiles[z]; if (m_lightView && (m_fadeType != FadeType::OUT$ || fadeLevel == 1.f)) { - const size_t lightFloorStart = m_lightView ? m_lightView->size() : 0; - for (const auto& tile : map.shades) { if (alwaysTransparent && tile->getPosition().isInRange(_camera, TRANSPARENT_FLOOR_VIEW_RANGE, TRANSPARENT_FLOOR_VIEW_RANGE, true)) continue; - m_lightView->setFieldBrightness(transformPositionTo2D(tile->getPosition(), cameraPosition), lightFloorStart, fadeLevel); + m_lightView->resetShade(transformPositionTo2D(tile->getPosition(), cameraPosition)); } }