From bef0e11e19b20600e1a76840ba0a30b20af4200d Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Thu, 2 Mar 2023 19:22:30 -0300 Subject: [PATCH] cleanup: drawpool / lighting system --- src/client/lightview.cpp | 25 ++++--- src/client/lightview.h | 4 +- src/client/mapview.cpp | 12 ++-- src/client/mapview.h | 2 +- src/client/spritemanager.cpp | 51 +------------ src/client/spritemanager.h | 9 --- src/framework/core/graphicalapplication.cpp | 12 ++-- src/framework/graphics/declarations.h | 1 - src/framework/graphics/drawpool.cpp | 17 +++-- src/framework/graphics/drawpool.h | 44 ++++-------- src/framework/graphics/drawpoolmanager.cpp | 79 ++++++++++++--------- src/framework/graphics/drawpoolmanager.h | 5 +- src/framework/graphics/framebuffer.cpp | 10 ++- src/framework/graphics/texture.h | 3 +- 14 files changed, 105 insertions(+), 169 deletions(-) diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index c0a24693c9..af2a57c9d7 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -21,20 +21,29 @@ */ #include "lightview.h" -#include #include "map.h" #include "mapview.h" #include "spritemanager.h" -LightView::LightView() : m_pool(g_drawPool.get(DrawPoolType::LIGHT)) {} +#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->setSmooth(true); + }); +} void LightView::resize(const Size& size, const uint16_t tileSize) { - m_lightTexture = nullptr; 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); + if (m_texture) + m_texture->setupSize(m_mapSize); } void LightView::addLightSource(const Point& pos, const Light& light, float brightness) @@ -77,15 +86,9 @@ void LightView::draw(const Rect& dest, const Rect& src) updatePixels(); g_drawPool.addAction([&] { - if (!m_lightTexture) { - m_lightTexture = std::make_shared(m_mapSize); - m_lightTexture->setSmooth(true); - } - - m_lightTexture->updatePixels(m_pixels.data()); - + m_texture->updatePixels(m_pixels.data()); g_painter->resetColor(); - g_painter->setTexture(m_lightTexture.get()); + g_painter->setTexture(m_texture.get()); g_painter->setCompositionMode(CompositionMode::MULTIPLY); g_painter->drawCoords(m_coords); }); diff --git a/src/client/lightview.h b/src/client/lightview.h index 18d42ace1c..f7d7574844 100644 --- a/src/client/lightview.h +++ b/src/client/lightview.h @@ -30,7 +30,7 @@ class LightView : public LuaObject { public: - LightView(); + LightView(const Size& size, const uint16_t tileSize); void resize(const Size& size, uint16_t tileSize); void draw(const Rect& dest, const Rect& src); @@ -70,7 +70,7 @@ class LightView : public LuaObject Color m_globalLightColor{ Color::white }; CoordsBuffer m_coords; - TexturePtr m_lightTexture; + TexturePtr m_texture; std::vector m_tiles; std::vector m_pixels; diff --git a/src/client/mapview.cpp b/src/client/mapview.cpp index 383fff555a..4b82e72e6c 100644 --- a/src/client/mapview.cpp +++ b/src/client/mapview.cpp @@ -42,7 +42,7 @@ #include -MapView::MapView() : m_pool(g_drawPool.get(DrawPoolType::MAP)) +MapView::MapView() : m_pool(g_drawPool.get(DrawPoolType::MAP)) { m_pool->onBeforeDraw([this] { float fadeOpacity = 1.f; @@ -404,7 +404,7 @@ void MapView::updateGeometry(const Size& visibleDimension) if (m_lightView) m_lightView->resize(m_drawDimension, tileSize); g_mainDispatcher.addEvent([=, this]() { - m_pool->resize(bufferSize); + m_pool->getFrameBuffer()->resize(bufferSize); }); const uint8_t left = std::min(g_map.getAwareRange().left, (m_drawDimension.width() / 2) - 1); @@ -547,7 +547,7 @@ void MapView::setAntiAliasingMode(const AntialiasingMode mode) { m_antiAliasingMode = mode; - g_drawPool.get(DrawPoolType::MAP) + g_drawPool.get(DrawPoolType::MAP)->getFrameBuffer() ->setSmooth(mode != ANTIALIASING_DISABLED); updateGeometry(m_visibleDimension); @@ -768,16 +768,14 @@ void MapView::setShader(const std::string_view name, float fadein, float fadeout void MapView::setDrawLights(bool enable) { - if (auto* pool = g_drawPool.get(DrawPoolType::LIGHT)) + if (auto* pool = g_drawPool.get(DrawPoolType::LIGHT)) pool->setEnable(enable); if (enable) { if (m_lightView) return; - m_lightView = std::make_shared(); - g_mainDispatcher.addEvent([this] - () { if (m_lightView) m_lightView->resize(m_drawDimension, m_tileSize); }); + m_lightView = std::make_shared(m_drawDimension, m_tileSize); requestUpdateVisibleTiles(); } else m_lightView = nullptr; diff --git a/src/client/mapview.h b/src/client/mapview.h index 8b0e60e5ad..20c3c1bdb5 100644 --- a/src/client/mapview.h +++ b/src/client/mapview.h @@ -316,5 +316,5 @@ class MapView : public LuaObject TexturePtr m_crosshairTexture; DrawConductor m_shadowConductor{ false, DrawOrder::FIFTH }; - DrawPoolFramed* m_pool; + DrawPool* m_pool; }; diff --git a/src/client/spritemanager.cpp b/src/client/spritemanager.cpp index 9967ace253..a57deb521e 100644 --- a/src/client/spritemanager.cpp +++ b/src/client/spritemanager.cpp @@ -30,13 +30,8 @@ SpriteManager g_sprites; -void SpriteManager::init() { generateLightTexture(); generateShadeTexture(); } -void SpriteManager::terminate() -{ - unload(); - m_shadeTexture = nullptr; - m_lightTexture = nullptr; -} +void SpriteManager::init() { } +void SpriteManager::terminate() { unload(); } void SpriteManager::reload() { if (g_app.isEncrypted()) @@ -246,45 +241,3 @@ ImagePtr SpriteManager::getSpriteImage(int id, const FileStreamPtr& file) { return nullptr; } } - -void SpriteManager::generateLightTexture() -{ - constexpr float brightnessIntensity = 1.5f; - - constexpr int bubbleRadius = 6; - constexpr int bubbleDiameter = bubbleRadius * 2.3; - - const auto& image = std::make_shared(Size(bubbleDiameter)); - for (int_fast16_t x = -1; ++x < bubbleDiameter;) { - for (int_fast16_t y = -1; ++y < bubbleDiameter;) { - const float radius = std::sqrt((bubbleRadius - x) * (bubbleRadius - x) + (bubbleRadius - y) * (bubbleRadius - y)); - const float intensity = std::clamp(((bubbleRadius - radius) / bubbleRadius) * brightnessIntensity, .01f, 1.0f); - - // light intensity varies inversely with the square of the distance - const uint8_t colorByte = intensity * 0xff; - - const uint8_t pixel[4] = { colorByte, colorByte, colorByte, 0xff }; - image->setPixel(x, y, pixel); - } - } - - m_lightTexture = std::make_shared(image); - m_lightTexture->setSmooth(true); -} - -void SpriteManager::generateShadeTexture() -{ - constexpr uint16_t diameter = 4; - - const auto& image = std::make_shared(Size(diameter)); - for (int_fast16_t x = -1; ++x < diameter;) { - for (int_fast16_t y = -1; ++y < diameter;) { - const uint8_t alpha = x == 0 || y == 0 || x == diameter - 1 || y == diameter - 1 ? 0 : 0xff; - const uint8_t pixel[4] = { 0xff, 0xff, 0xff, alpha }; - image->setPixel(x, y, pixel); - } - } - - m_shadeTexture = std::make_shared(image); - m_shadeTexture->setSmooth(true); -} diff --git a/src/client/spritemanager.h b/src/client/spritemanager.h index 984b175a1f..425752e559 100644 --- a/src/client/spritemanager.h +++ b/src/client/spritemanager.h @@ -46,9 +46,6 @@ class SpriteManager ImagePtr getSpriteImage(int id); bool isLoaded() { return m_loaded; } - const TexturePtr& getLightTexture() const { return m_lightTexture; } - const TexturePtr& getShadeTexture() const { return m_shadeTexture; } - private: ImagePtr getSpriteImage(int id, const FileStreamPtr& file); @@ -57,14 +54,8 @@ class SpriteManager SPRITE_DATA_SIZE = SPRITE_SIZE * SPRITE_SIZE * 4 }; - void generateLightTexture(), - generateShadeTexture(); - std::string m_lastFileName; - TexturePtr m_lightTexture; - TexturePtr m_shadeTexture; - bool m_loaded{ false }; uint32_t m_signature{ 0 }; uint32_t m_spritesCount{ 0 }; diff --git a/src/framework/core/graphicalapplication.cpp b/src/framework/core/graphicalapplication.cpp index fff94f6110..f32e834fd2 100644 --- a/src/framework/core/graphicalapplication.cpp +++ b/src/framework/core/graphicalapplication.cpp @@ -133,9 +133,9 @@ void GraphicalApplication::run() g_lua.callGlobalField("g_app", "onRun"); - const auto& foreground = g_drawPool.get(DrawPoolType::FOREGROUND); - const auto& txt = g_drawPool.get(DrawPoolType::TEXT); - const auto& map = g_drawPool.get(DrawPoolType::MAP); + const auto& foreground = g_drawPool.get(DrawPoolType::FOREGROUND); + const auto& txt = g_drawPool.get(DrawPoolType::TEXT); + const auto& map = g_drawPool.get(DrawPoolType::MAP); std::condition_variable foreCondition, txtCondition; @@ -254,7 +254,9 @@ void GraphicalApplication::resize(const Size& size) g_mainDispatcher.addEvent([size] { g_graphics.resize(size); - g_drawPool.get(DrawPoolType::FOREGROUND)->resize(size); + auto* foreGround = g_drawPool.get(DrawPoolType::FOREGROUND); + foreGround->getFrameBuffer()->resize(size); + foreGround->repaint(); }); } @@ -265,7 +267,7 @@ void GraphicalApplication::inputEvent(const InputEvent& event) m_onInputEvent = false; } -void GraphicalApplication::repaint() { g_drawPool.get(DrawPoolType::FOREGROUND)->repaint(); } +void GraphicalApplication::repaint() { g_drawPool.get(DrawPoolType::FOREGROUND)->repaint(); } bool GraphicalApplication::canDrawTexts() const { return m_drawText && (!g_map.getStaticTexts().empty() || !g_map.getAnimatedTexts().empty()); } bool GraphicalApplication::isLoadingAsyncTexture() { return m_loadingAsyncTexture || g_game.isUsingProtobuf(); } diff --git a/src/framework/graphics/declarations.h b/src/framework/graphics/declarations.h index 5fadbd343f..7640578a25 100644 --- a/src/framework/graphics/declarations.h +++ b/src/framework/graphics/declarations.h @@ -47,7 +47,6 @@ class ParticleEffect; class ParticleEffectType; class SpriteSheet; class DrawPool; -class DrawPoolFramed; class DrawPoolManager; class CoordsBuffer; diff --git a/src/framework/graphics/drawpool.cpp b/src/framework/graphics/drawpool.cpp index e67602cffb..5720cb422f 100644 --- a/src/framework/graphics/drawpool.cpp +++ b/src/framework/graphics/drawpool.cpp @@ -30,24 +30,23 @@ FPS60 = 1000 / 60; DrawPool* DrawPool::create(const DrawPoolType type) { - DrawPool* pool; + DrawPool* pool = new DrawPool; if (type == DrawPoolType::MAP || type == DrawPoolType::FOREGROUND) { - pool = new DrawPoolFramed; + pool = new DrawPool; - const auto& frameBuffer = pool->toPoolFramed()->m_framebuffer; - frameBuffer->m_isScene = true; + pool->m_framebuffer = std::make_shared(); + pool->m_framebuffer->m_isScene = true; if (type == DrawPoolType::MAP) { - frameBuffer->m_useAlphaWriting = false; - frameBuffer->disableBlend(); + pool->m_framebuffer->m_useAlphaWriting = false; + pool->m_framebuffer->disableBlend(); } else if (type == DrawPoolType::FOREGROUND) { pool->setFPS(FPS10); } else if (type == DrawPoolType::LIGHT) { pool->m_alwaysGroupDrawings = true; - frameBuffer->setCompositionMode(CompositionMode::LIGHT); + pool->m_framebuffer->setCompositionMode(CompositionMode::LIGHT); } } else { - pool = new DrawPool; pool->m_alwaysGroupDrawings = true; // CREATURE_INFORMATION & TEXT pool->disableUpdateHash(); @@ -61,7 +60,7 @@ DrawPool* DrawPool::create(const DrawPoolType type) } void DrawPool::add(const Color& color, const TexturePtr& texture, DrawPool::DrawMethod& method, - DrawMode drawMode, const DrawConductor& conductor, const CoordsBufferPtr& coordsBuffer) + DrawMode drawMode, const DrawConductor& conductor, const CoordsBufferPtr& coordsBuffer) { auto state = getState(method, texture, color); diff --git a/src/framework/graphics/drawpool.h b/src/framework/graphics/drawpool.h index b65ea2e26d..bbd03c938a 100644 --- a/src/framework/graphics/drawpool.h +++ b/src/framework/graphics/drawpool.h @@ -72,16 +72,21 @@ class DrawPool bool isEnabled() const { return m_enabled; } bool isType(DrawPoolType type) const { return m_type == type; } + bool isValid() const { return !m_framebuffer || m_framebuffer->isValid(); } + bool hasFrameBuffer() const { return m_framebuffer != nullptr; } + FrameBufferPtr getFrameBuffer() const { return m_framebuffer; } + bool canRepaint() { return canRepaint(false); } void repaint() { m_status.first = 1; } - virtual bool isValid() const { return true; }; - void optimize(int size); void setScaleFactor(float scale) { m_scaleFactor = scale; } inline float getScaleFactor() const { return m_scaleFactor; } + void onBeforeDraw(std::function f) { m_beforeDraw = std::move(f); } + void onAfterDraw(std::function f) { m_afterDraw = std::move(f); } + std::mutex& getMutex() { return m_mutex; } protected: @@ -151,6 +156,7 @@ class DrawPool }; private: + static DrawPool* create(const DrawPoolType type); static void addCoords(CoordsBuffer* buffer, const DrawPool::DrawMethod& method, DrawMode drawMode); enum STATE_TYPE : uint32_t @@ -162,8 +168,6 @@ class DrawPool STATE_BLEND_EQUATION = 1 << 4, }; - static DrawPool* create(const DrawPoolType type); - void add(const Color& color, const TexturePtr& texture, DrawPool::DrawMethod& method, DrawMode drawMode = DrawMode::TRIANGLES, const DrawConductor& conductor = DEFAULT_DRAW_CONDUCTOR, const CoordsBufferPtr& coordsBuffer = nullptr); @@ -211,9 +215,6 @@ class DrawPool m_updateHash = false; } - virtual bool hasFrameBuffer() const { return false; }; - virtual DrawPoolFramed* toPoolFramed() { return nullptr; } - bool canRepaint(bool autoUpdateStatus); bool m_enabled{ true }; @@ -240,35 +241,14 @@ class DrawPool float m_scaleFactor{ 1.f }; - std::mutex m_mutex; - - friend DrawPoolManager; -}; - -class DrawPoolFramed : public DrawPool -{ -public: - void onBeforeDraw(std::function f) { m_beforeDraw = std::move(f); } - void onAfterDraw(std::function f) { m_afterDraw = std::move(f); } - void setSmooth(bool enabled) const { m_framebuffer->setSmooth(enabled); } - void resize(const Size& size) { if (m_framebuffer->resize(size)) repaint(); } - Size getSize() const { return m_framebuffer->getSize(); } - bool isValid() const override { return m_framebuffer->isValid(); } - -protected: - DrawPoolFramed() : m_framebuffer(std::make_shared()) {}; - - friend DrawPoolManager; - friend DrawPool; - -private: - bool hasFrameBuffer() const override { return m_framebuffer->isValid(); } - DrawPoolFramed* toPoolFramed() override { return this; } - FrameBufferPtr m_framebuffer; std::function m_beforeDraw; std::function m_afterDraw; + + std::mutex m_mutex; + + friend DrawPoolManager; }; extern DrawPoolManager g_drawPool; diff --git a/src/framework/graphics/drawpoolmanager.cpp b/src/framework/graphics/drawpoolmanager.cpp index a58511d6dc..d928a58eb0 100644 --- a/src/framework/graphics/drawpoolmanager.cpp +++ b/src/framework/graphics/drawpoolmanager.cpp @@ -56,46 +56,60 @@ void DrawPoolManager::draw() if (m_size != g_graphics.getViewportSize()) { m_size = g_graphics.getViewportSize(); m_transformMatrix = g_painter->getTransformMatrix(m_size); + g_painter->setResolution(m_size, m_transformMatrix); } - auto& mapMutex = get(DrawPoolType::MAP)->getMutex(); - - // Pre Draw - for (auto* pool : m_pools) { - if (!pool->isEnabled()) continue; - - // Light and Creature Info, are in the same thread as the MAP - auto& mutex = pool->getType() == DrawPoolType::CREATURE_INFORMATION || - pool->getType() == DrawPoolType::LIGHT ? mapMutex : pool->getMutex(); + const auto& map = get(DrawPoolType::MAP); { + std::scoped_lock l(map->m_mutex); + if (drawPool(map)) { + drawPool(get(DrawPoolType::CREATURE_INFORMATION)); + drawPool(get(DrawPoolType::LIGHT)); + } + } - std::scoped_lock l(mutex); + const auto& text = get(DrawPoolType::TEXT); { + std::scoped_lock l(text->m_mutex); + drawPool(text); + } - if (pool->hasFrameBuffer()) { - const auto* pf = pool->toPoolFramed(); - if (!pf->m_framebuffer->canDraw()) - continue; + const auto& foreground = get(DrawPoolType::FOREGROUND); { + std::scoped_lock l(foreground->m_mutex); + drawPool(foreground); + } +} - if (pool->canRepaint(true)) { - pf->m_framebuffer->bind(); - for (int_fast8_t i = -1; ++i <= pool->m_depthLevel;) { - for (const auto& order : pool->m_objects[i]) - for (const auto& obj : order) - drawObject(obj); - } +bool DrawPoolManager::drawPool(const auto& pool) { + if (!pool->isEnabled()) + return false; - pf->m_framebuffer->release(); - } + if (!pool->hasFrameBuffer()) { + for (const auto& obj : pool->m_objects[0][DrawOrder::FIRST]) { + drawObject(obj); + } + return true; + } - g_painter->resetState(); - g_painter->setResolution(m_size, m_transformMatrix); + if (!pool->m_framebuffer->canDraw()) + return false; - if (pf->m_beforeDraw) pf->m_beforeDraw(); - pf->m_framebuffer->draw(); - if (pf->m_afterDraw) pf->m_afterDraw(); - } else for (const auto& obj : pool->m_objects[0][DrawOrder::FIRST]) { - drawObject(obj); + if (pool->canRepaint(true)) { + pool->m_framebuffer->bind(); + for (int_fast8_t i = -1; ++i <= pool->m_depthLevel;) { + for (const auto& order : pool->m_objects[i]) + for (const auto& obj : order) + drawObject(obj); } + + pool->m_framebuffer->release(); } + + g_painter->resetState(); + + if (pool->m_beforeDraw) pool->m_beforeDraw(); + pool->m_framebuffer->draw(); + if (pool->m_afterDraw) pool->m_afterDraw(); + + return true; } void DrawPoolManager::drawObject(const DrawPool::DrawObject& obj) @@ -227,12 +241,11 @@ void DrawPoolManager::use(const DrawPoolType type, const Rect& dest, const Rect& currentPoll->resetState(); if (currentPoll->hasFrameBuffer()) { - currentPoll->toPoolFramed() - ->m_framebuffer->prepare(dest, src, colorClear); + currentPoll->m_framebuffer->prepare(dest, src, colorClear); // when the selected pool is MAP, reset the creature information state. if (type == DrawPoolType::MAP) { - get(DrawPoolType::CREATURE_INFORMATION)->resetState(); + get(DrawPoolType::CREATURE_INFORMATION)->resetState(); } } } diff --git a/src/framework/graphics/drawpoolmanager.h b/src/framework/graphics/drawpoolmanager.h index c85a7033ea..e7c51dfdd6 100644 --- a/src/framework/graphics/drawpoolmanager.h +++ b/src/framework/graphics/drawpoolmanager.h @@ -30,8 +30,7 @@ class DrawPoolManager { public: - template - T* get(const DrawPoolType type) const { return static_cast(m_pools[static_cast(type)]); } + DrawPool* get(const DrawPoolType type) const { return m_pools[static_cast(type)]; } void select(DrawPoolType type); void use(const DrawPoolType type) { use(type, {}, {}); } @@ -99,6 +98,8 @@ class DrawPoolManager void terminate() const; void drawObject(const DrawPool::DrawObject& obj); + bool drawPool(const auto& pool); + CoordsBuffer m_coordsBuffer; std::array(DrawPoolType::UNKNOW) + 1> m_pools{}; diff --git a/src/framework/graphics/framebuffer.cpp b/src/framework/graphics/framebuffer.cpp index a22eef890f..c98904b6d5 100644 --- a/src/framework/graphics/framebuffer.cpp +++ b/src/framework/graphics/framebuffer.cpp @@ -80,11 +80,11 @@ void FrameBuffer::bind() if (m_isScene) { g_painter->resetState(); - } else { - m_oldSize = g_painter->getResolution(); - m_oldTextureMatrix = g_painter->getProjectionMatrix(); } + m_oldSize = std::move(g_painter->getResolution()); + m_oldTextureMatrix = std::move(g_painter->getProjectionMatrix()); + g_painter->setResolution(getSize(), m_textureMatrix); g_painter->setAlphaWriting(m_useAlphaWriting); @@ -100,9 +100,7 @@ void FrameBuffer::bind() void FrameBuffer::release() const { internalRelease(); - if (!m_isScene) { - g_painter->setResolution(m_oldSize, m_oldTextureMatrix); - } + g_painter->setResolution(m_oldSize, m_oldTextureMatrix); } void FrameBuffer::draw() diff --git a/src/framework/graphics/texture.h b/src/framework/graphics/texture.h index d89194ab9a..3c2bae3f59 100644 --- a/src/framework/graphics/texture.h +++ b/src/framework/graphics/texture.h @@ -59,6 +59,7 @@ class Texture bool hasRepeat() const { return getProp(Prop::repeat); } bool hasMipmaps() const { return getProp(Prop::hasMipMaps); } virtual bool isAnimatedTexture() const { return false; } + bool setupSize(const Size& size); protected: void bind(); @@ -69,8 +70,6 @@ class Texture void setupPixels(int level, const Size& size, uint8_t* pixels, int channels = 4, bool compress = false) const; void generateHash() { m_hash = stdext::hash_int(m_id > 0 ? m_id : m_uniqueId); } - bool setupSize(const Size& size); - const uint32_t m_uniqueId; uint32_t m_id{ 0 };