diff --git a/source/client/StarClientApplication.cpp b/source/client/StarClientApplication.cpp index 19ea9e0..6c891c2 100644 --- a/source/client/StarClientApplication.cpp +++ b/source/client/StarClientApplication.cpp @@ -418,7 +418,7 @@ void ClientApplication::render() { LogMap::set("client_render_world_client", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - clientStart)); auto paintStart = Time::monotonicMicroseconds(); - m_worldPainter->render(m_renderData, [&]() { worldClient->waitForLighting(); }); + m_worldPainter->render(m_renderData, [&]() { worldClient->waitForLighting(&m_renderData.lightMap); }); LogMap::set("client_render_world_painter", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - paintStart)); LogMap::set("client_render_world_total", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - totalStart)); } diff --git a/source/frontend/StarClientCommandProcessor.cpp b/source/frontend/StarClientCommandProcessor.cpp index 00ec2e5..933d87b 100644 --- a/source/frontend/StarClientCommandProcessor.cpp +++ b/source/frontend/StarClientCommandProcessor.cpp @@ -155,24 +155,27 @@ String ClientCommandProcessor::boxes() { if (!adminCommandAllowed()) return "You must be an admin to use this command."; - return strf("Geometry debug display {}", - m_universeClient->worldClient()->toggleCollisionDebug() - ? "enabled" : "disabled"); + auto worldClient = m_universeClient->worldClient(); + bool state = !worldClient->collisionDebug(); + worldClient->setCollisionDebug(state); + return strf("Geometry debug display {}", state ? "enabled" : "disabled"); } String ClientCommandProcessor::fullbright() { if (!adminCommandAllowed()) return "You must be an admin to use this command."; - return strf("Fullbright render lighting {}", - m_universeClient->worldClient()->toggleFullbright() - ? "enabled" : "disabled"); + auto worldClient = m_universeClient->worldClient(); + bool state = !worldClient->fullBright(); + worldClient->setFullBright(state); + return strf("Fullbright render lighting {}", state ? "enabled" : "disabled"); } String ClientCommandProcessor::asyncLighting() { - return strf("Asynchronous render lighting {}", - m_universeClient->worldClient()->toggleAsyncLighting() - ? "enabled" : "disabled"); + auto worldClient = m_universeClient->worldClient(); + bool state = !worldClient->asyncLighting(); + worldClient->setAsyncLighting(state); + return strf("Asynchronous render lighting {}", state ? "enabled" : "disabled"); } String ClientCommandProcessor::setGravity(String const& argumentsString) { diff --git a/source/game/StarUniverseClient.cpp b/source/game/StarUniverseClient.cpp index c492d89..f355965 100644 --- a/source/game/StarUniverseClient.cpp +++ b/source/game/StarUniverseClient.cpp @@ -123,6 +123,7 @@ Maybe UniverseClient::connect(UniverseConnection connection, bool allowA m_mainPlayer->setClientContext(m_clientContext); m_mainPlayer->setStatistics(m_statistics); m_worldClient = make_shared(m_mainPlayer); + m_worldClient->setAsyncLighting(true); for (auto& pair : m_luaCallbacks) m_worldClient->setLuaCallbacks(pair.first, pair.second); diff --git a/source/game/StarWorldClient.cpp b/source/game/StarWorldClient.cpp index d510920..470ff42 100644 --- a/source/game/StarWorldClient.cpp +++ b/source/game/StarWorldClient.cpp @@ -37,7 +37,7 @@ WorldClient::WorldClient(PlayerPtr mainPlayer) { m_currentStep = 0; m_currentServerStep = 0.0; m_fullBright = false; - m_asyncLighting = true; + m_asyncLighting = false; m_worldDimTimer = GameTimer(m_clientConfig.getFloat("worldDimTime")); m_worldDimTimer.setDone(); m_worldDimLevel = 0.0f; @@ -90,20 +90,20 @@ WorldClient::WorldClient(PlayerPtr mainPlayer) { m_altMusicActive = false; m_stopLightingThread = false; - m_lightingThread = Thread::invoke("WorldClient::lightingMain", mem_fn(&WorldClient::lightingMain), this); - m_renderData = nullptr; clearWorld(); } WorldClient::~WorldClient() { - m_stopLightingThread = true; - { - MutexLocker locker(m_lightingMutex); - m_lightingCond.broadcast(); - } + if (m_lightingThread) { + m_stopLightingThread = true; + { + MutexLocker locker(m_lightingMutex); + m_lightingCond.broadcast(); + } - m_lightingThread.finish(); + m_lightingThread.finish(); + } clearWorld(); } @@ -404,6 +404,9 @@ RectI WorldClient::clientWindow() const { } void WorldClient::render(WorldRenderData& renderData, unsigned bufferTiles) { + if (!m_lightingThread && m_asyncLighting) + m_lightingThread = Thread::invoke("WorldClient::lightingMain", mem_fn(&WorldClient::lightingMain), this); + renderData.clear(); if (!inWorld()) return; @@ -474,13 +477,10 @@ void WorldClient::render(WorldRenderData& renderData, unsigned bufferTiles) { m_lightingCalculator.addSpreadLight(position, Color::v3bToFloat(lightPair.second)); } - if (m_asyncLighting) { - m_renderData = &renderData; + if (m_asyncLighting) m_lightingCond.signal(); - } - else { - m_lightingCalculator.calculate(renderData.lightMap); - } + else + m_lightingCalculator.calculate(m_lightMap); } float pulseAmount = Root::singleton().assets()->json("/highlights.config:interactivePulseAmount").toFloat(); @@ -725,21 +725,30 @@ void WorldClient::resetGravity() { m_overrideGravity = {}; } -bool WorldClient::toggleFullbright() { - m_fullBright = !m_fullBright; +bool WorldClient::fullBright() const { return m_fullBright; } -bool WorldClient::toggleAsyncLighting() { - m_asyncLighting = !m_asyncLighting; +void WorldClient::setFullBright(bool fullBright) { + m_fullBright = fullBright; +} + +bool WorldClient::asyncLighting() const { return m_asyncLighting; } -bool WorldClient::toggleCollisionDebug() { - m_collisionDebug = !m_collisionDebug; +void WorldClient::setAsyncLighting(bool asyncLighting) { + m_asyncLighting = asyncLighting; +} + +bool WorldClient::collisionDebug() const { return m_collisionDebug; } +void WorldClient::setCollisionDebug(bool collisionDebug) { + m_collisionDebug = collisionDebug; +} + void WorldClient::handleIncomingPackets(List const& packets) { auto& root = Root::singleton(); auto materialDatabase = root.materialDatabase(); @@ -1393,8 +1402,10 @@ void WorldClient::collectLiquid(List const& tilePositions, LiquidId liqui m_outgoingPackets.append(make_shared(tilePositions, liquidId)); } -void WorldClient::waitForLighting() { +void WorldClient::waitForLighting(Image* out) { MutexLocker lock(m_lightingMutex); + if (out) + *out = move(m_lightMap); } WorldClient::BroadcastCallback& WorldClient::broadcastCallback() { @@ -1644,15 +1655,10 @@ void WorldClient::lightingMain() { if (m_stopLightingThread) return; - if (WorldRenderData* renderData = m_renderData) { - int64_t start = Time::monotonicMicroseconds(); - - lightingTileGather(); - - m_lightingCalculator.calculate(renderData->lightMap); - m_renderData = nullptr; - LogMap::set("client_render_world_async_light_calc", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - start)); - } + int64_t start = Time::monotonicMicroseconds(); + lightingTileGather(); + m_lightingCalculator.calculate(m_lightMap); + LogMap::set("client_render_world_async_light_calc", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - start)); continue; diff --git a/source/game/StarWorldClient.hpp b/source/game/StarWorldClient.hpp index 7298863..a8080f1 100644 --- a/source/game/StarWorldClient.hpp +++ b/source/game/StarWorldClient.hpp @@ -122,11 +122,14 @@ public: void resetGravity(); // Disable normal client-side lighting algorithm, everything full brightness. - bool toggleFullbright(); + bool fullBright() const; + void setFullBright(bool fullBright); // Disable asynchronous client-side lighting algorithm, run on main thread. - bool toggleAsyncLighting(); + bool asyncLighting() const; + void setAsyncLighting(bool asyncLighting); // Spatial log generated collision geometry. - bool toggleCollisionDebug(); + bool collisionDebug() const; + void setCollisionDebug(bool collisionDebug); void handleIncomingPackets(List const& packets); List getOutgoingPackets(); @@ -167,7 +170,7 @@ public: void collectLiquid(List const& tilePositions, LiquidId liquidId); - void waitForLighting(); + void waitForLighting(Image* out = nullptr); typedef std::function BroadcastCallback; BroadcastCallback& broadcastCallback(); @@ -269,7 +272,7 @@ private: Mutex m_lightingMutex; ConditionVariable m_lightingCond; - atomic m_renderData; + Image m_lightMap; atomic m_stopLightingThread; SkyPtr m_sky; diff --git a/source/game/StarWorldServerThread.cpp b/source/game/StarWorldServerThread.cpp index 1b7d23a..35d6225 100644 --- a/source/game/StarWorldServerThread.cpp +++ b/source/game/StarWorldServerThread.cpp @@ -269,7 +269,7 @@ void WorldServerThread::update(WorldServerFidelity fidelity) { float dt = ServerGlobalTimestep * GlobalTimescale; m_worldServer->setFidelity(fidelity); - if (!m_pause || *m_pause == false) + if (dt > 0.0f && (!m_pause || *m_pause == false)) m_worldServer->update(dt); List messages; diff --git a/source/test/StarTestUniverse.cpp b/source/test/StarTestUniverse.cpp index 4602f34..a7b9dd2 100644 --- a/source/test/StarTestUniverse.cpp +++ b/source/test/StarTestUniverse.cpp @@ -42,7 +42,7 @@ TestUniverse::~TestUniverse() { void TestUniverse::warpPlayer(WorldId worldId) { m_client->warpPlayer(WarpToWorld(worldId), true); while (m_mainPlayer->isTeleporting() || m_client->playerWorld().empty()) { - m_client->update(); + m_client->update(0.016f); Thread::sleep(16); } } @@ -53,7 +53,7 @@ WorldId TestUniverse::currentPlayerWorld() const { void TestUniverse::update(unsigned times) { for (unsigned i = 0; i < times; ++i) { - m_client->update(); + m_client->update(0.016f); Thread::sleep(16); } }