From 702acf212490c0386f5fcd332f7ae68b7a1013bf Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Tue, 18 Jul 2023 18:43:20 -0300 Subject: [PATCH 1/6] update --- data/setup.otml | 2 +- src/client/lightview.cpp | 16 +++++++++++++--- src/client/lightview.h | 6 +++++- src/client/mapview.cpp | 7 +++++-- src/framework/graphics/drawpoolmanager.cpp | 14 +++++++++----- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/data/setup.otml b/data/setup.otml index 9732949b4e..edd10256b5 100644 --- a/data/setup.otml +++ b/data/setup.otml @@ -3,7 +3,7 @@ game last-supported-version: 1316 map - viewport: 8 6 + viewport: 32 24 max-z: 15 sea-floor: 7 underground-floor: 8 diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index f6d8578a47..01f01d580d 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -34,9 +34,21 @@ LightView::LightView(const Size& size, const uint16_t tileSize) : m_pool(g_drawP m_texture = std::make_shared(m_mapSize); m_texture->setSmooth(true); }); + + m_thread = std::thread([&]() { + std::unique_lock lock(m_pool->getMutex()); + m_condition.wait(lock, [&]() -> bool { + updatePixels(); + m_lights.clear(); + m_tiles.assign(m_mapSize.area(), {}); + return m_texture == nullptr; + }); + }); } void LightView::resize(const Size& size, const uint16_t tileSize) { + std::scoped_lock l(m_pool->getMutex()); + m_mapSize = size; m_tileSize = tileSize; m_tiles.resize(size.area()); @@ -101,9 +113,7 @@ void LightView::resetShade(const Point& pos) void LightView::draw(const Rect& dest, const Rect& src) { updateCoords(dest, src); - updatePixels(); - m_lights.clear(); - m_tiles.assign(m_mapSize.area(), {}); + m_condition.notify_one(); } void LightView::updateCoords(const Rect& dest, const Rect& src) { diff --git a/src/client/lightview.h b/src/client/lightview.h index 0435663ccc..43f8075ee1 100644 --- a/src/client/lightview.h +++ b/src/client/lightview.h @@ -26,12 +26,13 @@ #include #include "declarations.h" #include "thingtype.h" +#include class LightView : public LuaObject { public: LightView(const Size& size, const uint16_t tileSize); - ~LightView() { m_texture = nullptr; } + ~LightView() { m_texture = nullptr; m_condition.notify_one(); m_thread.join(); } void resize(const Size& size, uint16_t tileSize); void draw(const Rect& dest, const Rect& src); @@ -107,4 +108,7 @@ class LightView : public LuaObject std::vector m_pixels; std::vector m_lights; std::vector m_tileColors; + + std::condition_variable m_condition; + std::thread m_thread; }; diff --git a/src/client/mapview.cpp b/src/client/mapview.cpp index ca60014682..8b1a04fedb 100644 --- a/src/client/mapview.cpp +++ b/src/client/mapview.cpp @@ -112,6 +112,9 @@ void MapView::draw() } } + if (isDrawingLights()) + m_lightView->draw(m_posInfo.rect, m_posInfo.srcRect); + drawFloor(); // this could happen if the player position is not known yet @@ -119,12 +122,12 @@ void MapView::draw() return; } - if (isDrawingLights()) - m_lightView->draw(m_posInfo.rect, m_posInfo.srcRect); + } void MapView::drawFloor() { + std::scoped_lock l(g_drawPool.get(DrawPoolType::LIGHT)->getMutex()); g_drawPool.use(DrawPoolType::MAP, m_posInfo.rect, m_posInfo.srcRect, Color::black); { const auto& cameraPosition = m_posInfo.camera; diff --git a/src/framework/graphics/drawpoolmanager.cpp b/src/framework/graphics/drawpoolmanager.cpp index 48e389ac5c..e375343329 100644 --- a/src/framework/graphics/drawpoolmanager.cpp +++ b/src/framework/graphics/drawpoolmanager.cpp @@ -63,10 +63,14 @@ void DrawPoolManager::draw() std::scoped_lock l(map->m_mutex); if (drawPool(map)) { drawPool(get(DrawPoolType::CREATURE_INFORMATION)); - drawPool(get(DrawPoolType::LIGHT)); } } + const auto& light = get(DrawPoolType::LIGHT); { + std::scoped_lock l(light->m_mutex); + drawPool(light); + } + const auto& text = get(DrawPoolType::TEXT); { std::scoped_lock l(text->m_mutex); drawPool(text); @@ -143,7 +147,7 @@ void DrawPoolManager::addTexturedRect(const Rect& dest, const TexturePtr& textur DrawPool::DrawMethod method{ .type = DrawPool::DrawMethodType::RECT, - .dest = dest, .src = src + .dest = dest, .src = src }; getCurrentPool()->add(color, texture, method, DrawMode::TRIANGLE_STRIP, condutor); @@ -184,7 +188,7 @@ void DrawPoolManager::addFilledTriangle(const Point& a, const Point& b, const Po if (a == b || a == c || b == c) return; - DrawPool::DrawMethod method{ .type = DrawPool::DrawMethodType::TRIANGLE, .a = a, .b = b, .c = c }; + DrawPool::DrawMethod method{.type = DrawPool::DrawMethodType::TRIANGLE, .a = a, .b = b, .c = c }; getCurrentPool()->add(color, nullptr, method); } @@ -196,8 +200,8 @@ void DrawPoolManager::addBoundingRect(const Rect& dest, const Color& color, uint DrawPool::DrawMethod method{ .type = DrawPool::DrawMethodType::BOUNDING_RECT, - .dest = dest, - .intValue = innerLineWidth + .dest = dest, + .intValue = innerLineWidth }; getCurrentPool()->add(color, nullptr, method); From 55f664f77125e583858b52f372205ba05c747837 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Tue, 18 Jul 2023 21:45:48 -0300 Subject: [PATCH 2/6] update --- src/client/lightview.cpp | 112 ++++++++++++++++++++------------------- src/client/lightview.h | 47 ++++------------ src/client/mapview.cpp | 6 +-- 3 files changed, 71 insertions(+), 94 deletions(-) diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index 01f01d580d..48325c4839 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -26,21 +26,20 @@ #include "spritemanager.h" #include +#include #include LightView::LightView(const Size& size, const uint16_t tileSize) : m_pool(g_drawPool.get(DrawPoolType::LIGHT)) { resize(size, tileSize); g_mainDispatcher.addEvent([&] { - m_texture = std::make_shared(m_mapSize); + m_texture = std::make_shared(m_lightData.mapSize); m_texture->setSmooth(true); }); - m_thread = std::thread([&]() { + m_thread = std::thread([this]() { std::unique_lock lock(m_pool->getMutex()); - m_condition.wait(lock, [&]() -> bool { + m_condition.wait(lock, [this]() -> bool { updatePixels(); - m_lights.clear(); - m_tiles.assign(m_mapSize.area(), {}); return m_texture == nullptr; }); }); @@ -48,30 +47,17 @@ LightView::LightView(const Size& size, const uint16_t tileSize) : m_pool(g_drawP void LightView::resize(const Size& size, const uint16_t tileSize) { std::scoped_lock l(m_pool->getMutex()); - - m_mapSize = size; - m_tileSize = tileSize; - m_tiles.resize(size.area()); - if (m_pixels.size() < 4u * m_mapSize.area()) - m_pixels.resize(m_mapSize.area() * 4); + m_lightData.mapSize = size; + m_lightData.tileSize = tileSize; + m_lightData.tiles.resize(size.area()); + if (m_pixels.size() < 4u * m_lightData.mapSize.area()) + m_pixels.resize(m_lightData.mapSize.area() * 4); if (m_texture) - m_texture->setupSize(m_mapSize); - - m_tileColors.clear(); - m_tileColors.reserve(m_tiles.size()); - for (int x = -1; ++x < m_mapSize.width();) { - for (int y = -1; ++y < m_mapSize.height();) { - const int index = (y * m_mapSize.width() + x); - const int colorIndex = index * 4; - Point pos(x * m_tileSize + m_tileSize / 2, y * m_tileSize + m_tileSize / 2); - - m_tileColors.emplace_back(pos, m_tiles[index], m_pixels[colorIndex], m_pixels[colorIndex + 1], - m_pixels[colorIndex + 2], m_pixels[colorIndex + 3]); - } - } + m_texture->setupSize(m_lightData.mapSize); + g_drawPool.use(DrawPoolType::LIGHT); - g_drawPool.addAction([&] { + g_drawPool.addAction([this] { m_texture->updatePixels(m_pixels.data()); g_painter->resetColor(); g_painter->resetTransformMatrix(); @@ -86,14 +72,14 @@ void LightView::addLightSource(const Point& pos, const Light& light, float brigh if (light.intensity == 0) return; - if (!m_lights.empty()) { - auto& prevLight = m_lights.back(); + if (!m_lightData.lights.empty()) { + auto& prevLight = m_lightData.lights.back(); if (prevLight.pos == pos && prevLight.color == light.color) { prevLight.intensity = std::max(prevLight.intensity, light.intensity); return; } } - m_lights.emplace_back(pos, light.intensity, light.color, std::min(brightness, g_drawPool.getOpacity())); + m_lightData.lights.emplace_back(pos, light.intensity, light.color, std::min(brightness, g_drawPool.getOpacity())); stdext::hash_union(m_updatedHash, pos.hash()); stdext::hash_combine(m_updatedHash, light.intensity); @@ -105,15 +91,28 @@ void LightView::addLightSource(const Point& pos, const Light& light, float brigh void LightView::resetShade(const Point& pos) { - size_t index = (pos.y / m_tileSize) * m_mapSize.width() + (pos.x / m_tileSize); - if (index >= m_tiles.size()) return; - m_tiles[index] = m_lights.size(); + size_t index = (pos.y / m_lightData.tileSize) * m_lightData.mapSize.width() + (pos.x / m_lightData.tileSize); + if (index >= m_lightData.tiles.size()) return; + m_lightData.tiles[index] = m_lightData.lights.size(); } void LightView::draw(const Rect& dest, const Rect& src) { updateCoords(dest, src); - m_condition.notify_one(); + + if (m_updatedHash != m_hash) { + m_hash = m_updatedHash; + m_updatedHash = 0; + + { + //std::scoped_lock l(m_mutex); + m_threadLightData = m_lightData; + } + m_condition.notify_one(); + } + + m_lightData.lights.clear(); + m_lightData.tiles.assign(m_lightData.mapSize.area(), {}); } void LightView::updateCoords(const Rect& dest, const Rect& src) { @@ -128,30 +127,35 @@ void LightView::updateCoords(const Rect& dest, const Rect& src) { m_coords.clear(); m_coords.addRect(RectF(m_dest.left(), m_dest.top(), m_dest.width(), m_dest.height()), - RectF(static_cast(offset.x) / m_tileSize, static_cast(offset.y) / m_tileSize, - static_cast(size.width()) / m_tileSize, static_cast(size.height()) / m_tileSize)); + RectF(static_cast(offset.x) / m_lightData.tileSize, static_cast(offset.y) / m_lightData.tileSize, + static_cast(size.width()) / m_lightData.tileSize, static_cast(size.height()) / m_lightData.tileSize)); } void LightView::updatePixels() { - if (m_updatedHash == m_hash) - return; - - const size_t lightSize = m_lights.size(); - for (auto& tile : m_tileColors) { - tile.setLight(m_globalLightColor, 255); - for (size_t i = tile.shadeIndex; i < lightSize; ++i) { - const auto& light = m_lights[i]; - float distance = std::sqrt((tile.pos.x - light.pos.x) * (tile.pos.x - light.pos.x) + - (tile.pos.y - light.pos.y) * (tile.pos.y - light.pos.y)); - distance /= m_tileSize; - - float intensity = (-distance + (light.intensity * light.brightness)) * .2f; - if (intensity < .01f) continue; - if (intensity > 1.f) intensity = 1.f; - tile.setLight(Color::from8bit(light.color, intensity)); + const size_t lightSize = m_threadLightData.lights.size(); + + for (int x = 0; x < m_threadLightData.mapSize.width(); ++x) { + for (int y = 0; y < m_threadLightData.mapSize.height(); ++y) { + Point pos(x * m_threadLightData.tileSize + m_threadLightData.tileSize / 2, y * m_threadLightData.tileSize + m_threadLightData.tileSize / 2); + int index = (y * m_threadLightData.mapSize.width() + x); + int colorIndex = index * 4; + m_pixels[colorIndex] = m_threadLightData.globalLightColor.r(); + m_pixels[colorIndex + 1] = m_threadLightData.globalLightColor.g(); + m_pixels[colorIndex + 2] = m_threadLightData.globalLightColor.b(); + m_pixels[colorIndex + 3] = 255; // alpha channel + for (size_t i = m_threadLightData.tiles[index]; i < lightSize; ++i) { + const auto& light = m_threadLightData.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 /= m_threadLightData.tileSize; + 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; + 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_updatedHash; - m_updatedHash = 0; } \ No newline at end of file diff --git a/src/client/lightview.h b/src/client/lightview.h index 43f8075ee1..544f2e26b5 100644 --- a/src/client/lightview.h +++ b/src/client/lightview.h @@ -43,7 +43,7 @@ class LightView : public LuaObject void setGlobalLight(const Light& light) { m_isDark = light.intensity < 250; - m_globalLightColor = Color::from8bit(light.color, light.intensity / static_cast(UINT8_MAX)); + m_lightData.globalLightColor = Color::from8bit(light.color, light.intensity / static_cast(UINT8_MAX)); } bool isDark() const { return m_isDark; } @@ -59,32 +59,13 @@ class LightView : public LuaObject TileLight(const Point& pos, uint8_t intensity, uint8_t color, float brightness) : Light(intensity, color), pos(pos), brightness(brightness) {} }; - struct TileColor + struct LightData { - TileColor(Point& pos, size_t& shadeIndex, uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a) : - pos(std::move(pos)), shadeIndex(shadeIndex), r(r), g(g), b(b), a(a) {} - - Point pos; - size_t& shadeIndex; - - void setLight(const Color& color, uint8_t alpha) { - r = color.r(); - g = color.g(); - b = color.b(); - a = alpha; - } - - void setLight(const Color& color) { - r = std::max(r, color.r()); - g = std::max(g, color.g()); - b = std::max(b, color.b()); - } - - private: - uint8_t& r; - uint8_t& g; - uint8_t& b; - uint8_t& a; + Size mapSize; + uint16_t tileSize{ 0 }; + std::vector tiles; + std::vector lights; + Color globalLightColor{ Color::white }; }; void updateCoords(const Rect& dest, const Rect& src); @@ -92,23 +73,17 @@ class LightView : public LuaObject bool m_isDark{ false }; - uint16_t m_tileSize{ 0 }; size_t m_hash{ 0 }, m_updatedHash{ 0 }; DrawPool* m_pool{ nullptr }; - Size m_mapSize; Rect m_dest, m_src; - Color m_globalLightColor{ Color::white }; - CoordsBuffer m_coords; TexturePtr m_texture; + LightData m_lightData, m_threadLightData; - std::vector m_tiles; - std::vector m_pixels; - std::vector m_lights; - std::vector m_tileColors; - - std::condition_variable m_condition; std::thread m_thread; + std::condition_variable m_condition; + + std::vector m_pixels; }; diff --git a/src/client/mapview.cpp b/src/client/mapview.cpp index 8b1a04fedb..a3adb23aa3 100644 --- a/src/client/mapview.cpp +++ b/src/client/mapview.cpp @@ -112,9 +112,6 @@ void MapView::draw() } } - if (isDrawingLights()) - m_lightView->draw(m_posInfo.rect, m_posInfo.srcRect); - drawFloor(); // this could happen if the player position is not known yet @@ -122,7 +119,8 @@ void MapView::draw() return; } - + if (isDrawingLights()) + m_lightView->draw(m_posInfo.rect, m_posInfo.srcRect); } void MapView::drawFloor() From 16d6c77f8cb7ab40a7d938ce1db2c3a06b2a7e6b Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Tue, 18 Jul 2023 21:55:00 -0300 Subject: [PATCH 3/6] update --- data/setup.otml | 2 +- src/client/lightview.cpp | 5 ++++- src/framework/graphics/drawpoolmanager.cpp | 6 +----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/data/setup.otml b/data/setup.otml index edd10256b5..9732949b4e 100644 --- a/data/setup.otml +++ b/data/setup.otml @@ -3,7 +3,7 @@ game last-supported-version: 1316 map - viewport: 32 24 + viewport: 8 6 max-z: 15 sea-floor: 7 underground-floor: 8 diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index 48325c4839..09feda30b0 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -58,7 +58,10 @@ void LightView::resize(const Size& size, const uint16_t tileSize) { g_drawPool.use(DrawPoolType::LIGHT); g_drawPool.addAction([this] { - m_texture->updatePixels(m_pixels.data()); + { + std::scoped_lock l(m_pool->getMutex()); + m_texture->updatePixels(m_pixels.data()); + } g_painter->resetColor(); g_painter->resetTransformMatrix(); g_painter->setTexture(m_texture.get()); diff --git a/src/framework/graphics/drawpoolmanager.cpp b/src/framework/graphics/drawpoolmanager.cpp index e375343329..7bb91f41d1 100644 --- a/src/framework/graphics/drawpoolmanager.cpp +++ b/src/framework/graphics/drawpoolmanager.cpp @@ -63,14 +63,10 @@ void DrawPoolManager::draw() std::scoped_lock l(map->m_mutex); if (drawPool(map)) { drawPool(get(DrawPoolType::CREATURE_INFORMATION)); + drawPool(get(DrawPoolType::LIGHT)); } } - const auto& light = get(DrawPoolType::LIGHT); { - std::scoped_lock l(light->m_mutex); - drawPool(light); - } - const auto& text = get(DrawPoolType::TEXT); { std::scoped_lock l(text->m_mutex); drawPool(text); From 821114e0b1e8dac0b8c0891004da5cd94d12a0d4 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Tue, 18 Jul 2023 22:04:27 -0300 Subject: [PATCH 4/6] Update lightview.cpp --- src/client/lightview.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index 09feda30b0..afe05eb66e 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -26,7 +26,6 @@ #include "spritemanager.h" #include -#include #include LightView::LightView(const Size& size, const uint16_t tileSize) : m_pool(g_drawPool.get(DrawPoolType::LIGHT)) { From fa54b0a1a1d40978fa7d8815f768ecb043f425d7 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Tue, 18 Jul 2023 22:05:16 -0300 Subject: [PATCH 5/6] Update lightview.cpp --- src/client/lightview.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index afe05eb66e..f92a125e70 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -105,11 +105,7 @@ void LightView::draw(const Rect& dest, const Rect& src) if (m_updatedHash != m_hash) { m_hash = m_updatedHash; m_updatedHash = 0; - - { - //std::scoped_lock l(m_mutex); - m_threadLightData = m_lightData; - } + m_threadLightData = m_lightData; m_condition.notify_one(); } From ebdf005c2b7db9bc933d6859e24a59bf5a4059c5 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Tue, 18 Jul 2023 22:13:18 -0300 Subject: [PATCH 6/6] update --- src/client/lightview.cpp | 1 - src/client/mapview.cpp | 1 - src/framework/graphics/drawpoolmanager.cpp | 8 ++++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index f92a125e70..b305e87f2d 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -54,7 +54,6 @@ void LightView::resize(const Size& size, const uint16_t tileSize) { if (m_texture) m_texture->setupSize(m_lightData.mapSize); - g_drawPool.use(DrawPoolType::LIGHT); g_drawPool.addAction([this] { { diff --git a/src/client/mapview.cpp b/src/client/mapview.cpp index a3adb23aa3..ca60014682 100644 --- a/src/client/mapview.cpp +++ b/src/client/mapview.cpp @@ -125,7 +125,6 @@ void MapView::draw() void MapView::drawFloor() { - std::scoped_lock l(g_drawPool.get(DrawPoolType::LIGHT)->getMutex()); g_drawPool.use(DrawPoolType::MAP, m_posInfo.rect, m_posInfo.srcRect, Color::black); { const auto& cameraPosition = m_posInfo.camera; diff --git a/src/framework/graphics/drawpoolmanager.cpp b/src/framework/graphics/drawpoolmanager.cpp index 7bb91f41d1..48e389ac5c 100644 --- a/src/framework/graphics/drawpoolmanager.cpp +++ b/src/framework/graphics/drawpoolmanager.cpp @@ -143,7 +143,7 @@ void DrawPoolManager::addTexturedRect(const Rect& dest, const TexturePtr& textur DrawPool::DrawMethod method{ .type = DrawPool::DrawMethodType::RECT, - .dest = dest, .src = src + .dest = dest, .src = src }; getCurrentPool()->add(color, texture, method, DrawMode::TRIANGLE_STRIP, condutor); @@ -184,7 +184,7 @@ void DrawPoolManager::addFilledTriangle(const Point& a, const Point& b, const Po if (a == b || a == c || b == c) return; - DrawPool::DrawMethod method{.type = DrawPool::DrawMethodType::TRIANGLE, .a = a, .b = b, .c = c }; + DrawPool::DrawMethod method{ .type = DrawPool::DrawMethodType::TRIANGLE, .a = a, .b = b, .c = c }; getCurrentPool()->add(color, nullptr, method); } @@ -196,8 +196,8 @@ void DrawPoolManager::addBoundingRect(const Rect& dest, const Color& color, uint DrawPool::DrawMethod method{ .type = DrawPool::DrawMethodType::BOUNDING_RECT, - .dest = dest, - .intValue = innerLineWidth + .dest = dest, + .intValue = innerLineWidth }; getCurrentPool()->add(color, nullptr, method);