Async lighting improvements
This commit is contained in:
parent
17ea975970
commit
983bb82a96
@ -30,11 +30,6 @@
|
|||||||
"textureSizeUniform" : "lightMapSize",
|
"textureSizeUniform" : "lightMapSize",
|
||||||
"textureAddressing" : "clamp",
|
"textureAddressing" : "clamp",
|
||||||
"textureFiltering" : "linear"
|
"textureFiltering" : "linear"
|
||||||
},
|
|
||||||
"tileLightMap" : {
|
|
||||||
"textureUniform" : "tileLightMap",
|
|
||||||
"textureAddressing" : "clamp",
|
|
||||||
"textureFiltering" : "linear"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -6,9 +6,7 @@ uniform sampler2D texture2;
|
|||||||
uniform sampler2D texture3;
|
uniform sampler2D texture3;
|
||||||
uniform bool lightMapEnabled;
|
uniform bool lightMapEnabled;
|
||||||
uniform vec2 lightMapSize;
|
uniform vec2 lightMapSize;
|
||||||
uniform vec2 tileLightMapSize;
|
|
||||||
uniform sampler2D lightMap;
|
uniform sampler2D lightMap;
|
||||||
uniform sampler2D tileLightMap;
|
|
||||||
uniform float lightMapMultiplier;
|
uniform float lightMapMultiplier;
|
||||||
|
|
||||||
varying vec2 fragmentTextureCoordinate;
|
varying vec2 fragmentTextureCoordinate;
|
||||||
@ -55,16 +53,6 @@ vec4 bicubicSample(sampler2D texture, vec2 texcoord, vec2 texscale) {
|
|||||||
mix(sample1, sample0, sx), sy);
|
mix(sample1, sample0, sx), sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 sampleLightMap(vec2 texcoord, vec2 texscale) {
|
|
||||||
vec4 b = bicubicSample(tileLightMap, texcoord, texscale);
|
|
||||||
vec4 a = bicubicSample(lightMap, texcoord, texscale);
|
|
||||||
|
|
||||||
if (b.z <= 0.0)
|
|
||||||
return a.rgb;
|
|
||||||
|
|
||||||
return mix(a.rgb, b.rgb / b.z, b.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 texColor;
|
vec4 texColor;
|
||||||
if (fragmentTextureIndex > 2.9) {
|
if (fragmentTextureIndex > 2.9) {
|
||||||
@ -84,6 +72,6 @@ void main() {
|
|||||||
if (texColor.a == 0.99607843137)
|
if (texColor.a == 0.99607843137)
|
||||||
finalColor.a = fragmentColor.a;
|
finalColor.a = fragmentColor.a;
|
||||||
else if (lightMapEnabled && finalLightMapMultiplier > 0.0)
|
else if (lightMapEnabled && finalLightMapMultiplier > 0.0)
|
||||||
finalColor.rgb *= sampleLightMap(fragmentLightMapCoordinate, 1.0 / lightMapSize) * finalLightMapMultiplier;
|
finalColor.rgb *= bicubicSample(lightMap, fragmentLightMapCoordinate, 1.0 / lightMapSize).rgb * finalLightMapMultiplier;
|
||||||
gl_FragColor = finalColor;
|
gl_FragColor = finalColor;
|
||||||
}
|
}
|
@ -89,15 +89,20 @@ void CellularLightingCalculator::calculate(Image& output) {
|
|||||||
|
|
||||||
output.reset(arrayMax[0] - arrayMin[0], arrayMax[1] - arrayMin[1], PixelFormat::RGB24);
|
output.reset(arrayMax[0] - arrayMin[0], arrayMax[1] - arrayMin[1], PixelFormat::RGB24);
|
||||||
|
|
||||||
|
if (m_monochrome) {
|
||||||
for (size_t x = arrayMin[0]; x < arrayMax[0]; ++x) {
|
for (size_t x = arrayMin[0]; x < arrayMax[0]; ++x) {
|
||||||
for (size_t y = arrayMin[1]; y < arrayMax[1]; ++y) {
|
for (size_t y = arrayMin[1]; y < arrayMax[1]; ++y) {
|
||||||
if (m_monochrome)
|
|
||||||
output.set24(x - arrayMin[0], y - arrayMin[1], Color::grayf(m_lightArray.right().getLight(x, y)).toRgb());
|
output.set24(x - arrayMin[0], y - arrayMin[1], Color::grayf(m_lightArray.right().getLight(x, y)).toRgb());
|
||||||
else
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (size_t x = arrayMin[0]; x < arrayMax[0]; ++x) {
|
||||||
|
for (size_t y = arrayMin[1]; y < arrayMax[1]; ++y) {
|
||||||
output.set24(x - arrayMin[0], y - arrayMin[1], Color::v3fToByte(m_lightArray.left().getLight(x, y)));
|
output.set24(x - arrayMin[0], y - arrayMin[1], Color::v3fToByte(m_lightArray.left().getLight(x, y)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CellularLightingCalculator::setupImage(Image& image, PixelFormat format) const {
|
void CellularLightingCalculator::setupImage(Image& image, PixelFormat format) const {
|
||||||
Vec2S arrayMin = Vec2S(m_queryRegion.min() - m_calculationRegion.min());
|
Vec2S arrayMin = Vec2S(m_queryRegion.min() - m_calculationRegion.min());
|
||||||
|
@ -426,7 +426,14 @@ void ClientApplication::render() {
|
|||||||
LogMap::set("client_render_world_client", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - clientStart));
|
LogMap::set("client_render_world_client", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - clientStart));
|
||||||
|
|
||||||
auto paintStart = Time::monotonicMicroseconds();
|
auto paintStart = Time::monotonicMicroseconds();
|
||||||
m_worldPainter->render(m_renderData, [&]() { worldClient->waitForLighting(&m_renderData.lightMap); });
|
m_worldPainter->render(m_renderData, [&]() -> bool {
|
||||||
|
if (auto newMinPosition = worldClient->waitForLighting(&m_renderData.lightMap)) {
|
||||||
|
m_renderData.lightMinPosition = *newMinPosition;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
LogMap::set("client_render_world_painter", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - paintStart));
|
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));
|
LogMap::set("client_render_world_total", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - totalStart));
|
||||||
}
|
}
|
||||||
|
@ -428,7 +428,7 @@ void WorldClient::render(WorldRenderData& renderData, unsigned bufferTiles) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<LightSource> renderLightSources;
|
List<LightSource> renderLightSources;
|
||||||
List<PreviewTile> previewTiles;
|
m_previewTiles.clear();
|
||||||
|
|
||||||
renderData.geometry = m_geometry;
|
renderData.geometry = m_geometry;
|
||||||
|
|
||||||
@ -444,43 +444,20 @@ void WorldClient::render(WorldRenderData& renderData, unsigned bufferTiles) {
|
|||||||
|
|
||||||
RectI window = m_clientState.window();
|
RectI window = m_clientState.window();
|
||||||
RectI tileRange = window.padded(bufferTiles);
|
RectI tileRange = window.padded(bufferTiles);
|
||||||
RectI lightRange = window.padded(1);
|
|
||||||
//Kae: Padded by one to fix light spread issues at the edges of the frame.
|
|
||||||
|
|
||||||
renderData.tileMinPosition = tileRange.min();
|
renderData.tileMinPosition = tileRange.min();
|
||||||
renderData.lightMinPosition = lightRange.min();
|
|
||||||
|
|
||||||
Vec2U lightSize(lightRange.size());
|
if (!m_fullBright) {
|
||||||
|
{
|
||||||
renderData.tileLightMap.reset(lightSize, PixelFormat::RGBA32);
|
MutexLocker m_prepLocker(m_lightMapPrepMutex);
|
||||||
renderData.tileLightMap.fill(Vec4B::filled(0));
|
m_pendingLights = std::move(renderLightSources);
|
||||||
|
m_pendingParticleLights = std::move(m_particles->lightSources());
|
||||||
if (m_fullBright) {
|
m_pendingLightRange = window.padded(1);
|
||||||
renderData.lightMap.reset(lightSize, PixelFormat::RGB24);
|
} //Kae: Padded by one to fix light spread issues at the edges of the frame.
|
||||||
renderData.lightMap.fill(Vec3B(255, 255, 255));
|
|
||||||
} else {
|
|
||||||
m_lightingCalculator.begin(lightRange);
|
|
||||||
|
|
||||||
if (!m_asyncLighting)
|
|
||||||
lightingTileGather();
|
|
||||||
|
|
||||||
for (auto const& light : renderLightSources) {
|
|
||||||
Vec2F position = m_geometry.nearestTo(Vec2F(m_lightingCalculator.calculationRegion().min()), light.position);
|
|
||||||
if (light.pointLight)
|
|
||||||
m_lightingCalculator.addPointLight(position, Color::v3bToFloat(light.color), light.pointBeam, light.beamAngle, light.beamAmbience);
|
|
||||||
else
|
|
||||||
m_lightingCalculator.addSpreadLight(position, Color::v3bToFloat(light.color));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const& lightPair : m_particles->lightSources()) {
|
|
||||||
Vec2F position = m_geometry.nearestTo(Vec2F(m_lightingCalculator.calculationRegion().min()), lightPair.first);
|
|
||||||
m_lightingCalculator.addSpreadLight(position, Color::v3bToFloat(lightPair.second));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_asyncLighting)
|
if (m_asyncLighting)
|
||||||
m_lightingCond.signal();
|
m_lightingCond.signal();
|
||||||
else
|
else
|
||||||
m_lightingCalculator.calculate(m_lightMap);
|
lightingCalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
float pulseAmount = Root::singleton().assets()->json("/highlights.config:interactivePulseAmount").toFloat();
|
float pulseAmount = Root::singleton().assets()->json("/highlights.config:interactivePulseAmount").toFloat();
|
||||||
@ -545,7 +522,7 @@ void WorldClient::render(WorldRenderData& renderData, unsigned bufferTiles) {
|
|||||||
|
|
||||||
m_particles->addParticles(std::move(renderCallback.particles));
|
m_particles->addParticles(std::move(renderCallback.particles));
|
||||||
m_samples.appendAll(std::move(renderCallback.audios));
|
m_samples.appendAll(std::move(renderCallback.audios));
|
||||||
previewTiles.appendAll(std::move(renderCallback.previewTiles));
|
m_previewTiles.appendAll(std::move(renderCallback.previewTiles));
|
||||||
renderData.overheadBars.appendAll(std::move(renderCallback.overheadBars));
|
renderData.overheadBars.appendAll(std::move(renderCallback.overheadBars));
|
||||||
|
|
||||||
}, [](EntityPtr const& a, EntityPtr const& b) {
|
}, [](EntityPtr const& a, EntityPtr const& b) {
|
||||||
@ -596,7 +573,7 @@ void WorldClient::render(WorldRenderData& renderData, unsigned bufferTiles) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& previewTile : previewTiles) {
|
for (auto const& previewTile : m_previewTiles) {
|
||||||
Vec2I tileArrayPos = m_geometry.diff(previewTile.position, renderData.tileMinPosition);
|
Vec2I tileArrayPos = m_geometry.diff(previewTile.position, renderData.tileMinPosition);
|
||||||
if (tileArrayPos[0] >= 0 && tileArrayPos[0] < (int)renderData.tiles.size(0) && tileArrayPos[1] >= 0 && tileArrayPos[1] < (int)renderData.tiles.size(1)) {
|
if (tileArrayPos[0] >= 0 && tileArrayPos[0] < (int)renderData.tiles.size(0) && tileArrayPos[1] >= 0 && tileArrayPos[1] < (int)renderData.tiles.size(1)) {
|
||||||
RenderTile& renderTile = renderData.tiles(tileArrayPos[0], tileArrayPos[1]);
|
RenderTile& renderTile = renderData.tiles(tileArrayPos[0], tileArrayPos[1]);
|
||||||
@ -621,12 +598,6 @@ void WorldClient::render(WorldRenderData& renderData, unsigned bufferTiles) {
|
|||||||
renderTile.liquidLevel = 255;
|
renderTile.liquidLevel = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previewTile.updateLight) {
|
|
||||||
Vec2I lightArrayPos = m_geometry.diff(previewTile.position, renderData.lightMinPosition);
|
|
||||||
if (lightArrayPos[0] >= 0 && lightArrayPos[0] < (int)renderData.tileLightMap.width() && lightArrayPos[1] >= 0 && lightArrayPos[1] < (int)renderData.tileLightMap.height())
|
|
||||||
renderData.tileLightMap.set(Vec2U(lightArrayPos), previewTile.light);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderData.particles = &m_particles->particles();
|
renderData.particles = &m_particles->particles();
|
||||||
@ -1090,8 +1061,6 @@ void WorldClient::update(float dt) {
|
|||||||
|
|
||||||
auto assets = Root::singleton().assets();
|
auto assets = Root::singleton().assets();
|
||||||
|
|
||||||
m_lightingCalculator.setMonochrome(Root::singleton().configuration()->get("monochromeLighting").toBool());
|
|
||||||
|
|
||||||
float expireTime = min(float(m_latency + 800), 2000.f);
|
float expireTime = min(float(m_latency + 800), 2000.f);
|
||||||
auto now = Time::monotonicMilliseconds();
|
auto now = Time::monotonicMilliseconds();
|
||||||
eraseWhere(m_predictedTiles, [&](auto& pair) {
|
eraseWhere(m_predictedTiles, [&](auto& pair) {
|
||||||
@ -1406,10 +1375,21 @@ void WorldClient::collectLiquid(List<Vec2I> const& tilePositions, LiquidId liqui
|
|||||||
m_outgoingPackets.append(make_shared<CollectLiquidPacket>(tilePositions, liquidId));
|
m_outgoingPackets.append(make_shared<CollectLiquidPacket>(tilePositions, liquidId));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldClient::waitForLighting(Image* out) {
|
Maybe<Vec2I> WorldClient::waitForLighting(Image* out) {
|
||||||
MutexLocker lock(m_lightMapMutex);
|
MutexLocker prepLocker(m_lightMapPrepMutex);
|
||||||
if (out)
|
MutexLocker lightMapLocker(m_lightMapMutex);
|
||||||
|
if (out && !m_lightMap.empty()) {
|
||||||
|
for (auto& previewTile : m_previewTiles) {
|
||||||
|
if (previewTile.updateLight) {
|
||||||
|
Vec2I lightArrayPos = m_geometry.diff(previewTile.position, m_lightMinPosition);
|
||||||
|
if (lightArrayPos[0] >= 0 && lightArrayPos[0] < (int)m_lightMap.width() && lightArrayPos[1] >= 0 && lightArrayPos[1] < (int)m_lightMap.height())
|
||||||
|
m_lightMap.set(Vec2U(lightArrayPos), previewTile.light);
|
||||||
|
}
|
||||||
|
}
|
||||||
*out = std::move(m_lightMap);
|
*out = std::move(m_lightMap);
|
||||||
|
return m_lightMinPosition;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldClient::BroadcastCallback& WorldClient::broadcastCallback() {
|
WorldClient::BroadcastCallback& WorldClient::broadcastCallback() {
|
||||||
@ -1629,11 +1609,11 @@ void WorldClient::lightingTileGather() {
|
|||||||
|
|
||||||
// Each column in tileEvalColumns is guaranteed to be no larger than the sector size.
|
// Each column in tileEvalColumns is guaranteed to be no larger than the sector size.
|
||||||
|
|
||||||
|
size_t lights = 0;
|
||||||
m_tileArray->tileEvalColumns(m_lightingCalculator.calculationRegion(), [&](Vec2I const& pos, ClientTile const* column, size_t ySize) {
|
m_tileArray->tileEvalColumns(m_lightingCalculator.calculationRegion(), [&](Vec2I const& pos, ClientTile const* column, size_t ySize) {
|
||||||
size_t baseIndex = m_lightingCalculator.baseIndexFor(pos);
|
size_t baseIndex = m_lightingCalculator.baseIndexFor(pos);
|
||||||
for (size_t y = 0; y < ySize; ++y) {
|
for (size_t y = 0; y < ySize; ++y) {
|
||||||
auto& tile = column[y];
|
auto& tile = column[y];
|
||||||
|
|
||||||
Vec3F light;
|
Vec3F light;
|
||||||
if (tile.foreground != EmptyMaterialId || tile.foregroundMod != NoModId)
|
if (tile.foreground != EmptyMaterialId || tile.foregroundMod != NoModId)
|
||||||
light += materialDatabase->radiantLight(tile.foreground, tile.foregroundMod);
|
light += materialDatabase->radiantLight(tile.foreground, tile.foregroundMod);
|
||||||
@ -1646,9 +1626,43 @@ void WorldClient::lightingTileGather() {
|
|||||||
if (tile.backgroundLightTransparent && pos[1] + y > undergroundLevel)
|
if (tile.backgroundLightTransparent && pos[1] + y > undergroundLevel)
|
||||||
light += environmentLight;
|
light += environmentLight;
|
||||||
}
|
}
|
||||||
m_lightingCalculator.setCellIndex(baseIndex + y, std::move(light), !tile.foregroundLightTransparent);
|
if (light.max() > 0.0f)
|
||||||
|
++lights;
|
||||||
|
m_lightingCalculator.setCellIndex(baseIndex + y, light, !tile.foregroundLightTransparent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
LogMap::set("client_render_world_async_light_tiles", toString(lights));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldClient::lightingCalc() {
|
||||||
|
MutexLocker prepLocker(m_lightMapPrepMutex);
|
||||||
|
RectI lightRange = m_pendingLightRange;
|
||||||
|
List<LightSource> lights = std::move(m_pendingLights);
|
||||||
|
List<std::pair<Vec2F, Vec3B>> particleLights = std::move(m_pendingParticleLights);
|
||||||
|
m_lightingCalculator.setMonochrome(Root::singleton().configuration()->get("monochromeLighting").toBool());
|
||||||
|
m_lightingCalculator.begin(lightRange);
|
||||||
|
lightingTileGather();
|
||||||
|
prepLocker.unlock();
|
||||||
|
|
||||||
|
for (auto const& light : lights) {
|
||||||
|
Vec2F position = m_geometry.nearestTo(Vec2F(m_lightingCalculator.calculationRegion().min()), light.position);
|
||||||
|
if (light.pointLight)
|
||||||
|
m_lightingCalculator.addPointLight(position, Color::v3bToFloat(light.color), light.pointBeam, light.beamAngle, light.beamAmbience);
|
||||||
|
else
|
||||||
|
m_lightingCalculator.addSpreadLight(position, Color::v3bToFloat(light.color));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& lightPair : particleLights) {
|
||||||
|
Vec2F position = m_geometry.nearestTo(Vec2F(m_lightingCalculator.calculationRegion().min()), lightPair.first);
|
||||||
|
m_lightingCalculator.addSpreadLight(position, Color::v3bToFloat(lightPair.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lightingCalculator.calculate(m_pendingLightMap);
|
||||||
|
{
|
||||||
|
MutexLocker mapLocker(m_lightMapMutex);
|
||||||
|
m_lightMinPosition = lightRange.min();
|
||||||
|
m_lightMap = std::move(m_pendingLightMap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldClient::lightingMain() {
|
void WorldClient::lightingMain() {
|
||||||
@ -1658,11 +1672,8 @@ void WorldClient::lightingMain() {
|
|||||||
if (m_stopLightingThread)
|
if (m_stopLightingThread)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MutexLocker mapLocker(m_lightMapMutex);
|
|
||||||
int64_t start = Time::monotonicMicroseconds();
|
int64_t start = Time::monotonicMicroseconds();
|
||||||
lightingTileGather();
|
lightingCalc();
|
||||||
m_lightingCalculator.calculate(m_lightMap);
|
|
||||||
mapLocker.unlock();
|
|
||||||
LogMap::set("client_render_world_async_light_calc", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - start));
|
LogMap::set("client_render_world_async_light_calc", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - start));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ public:
|
|||||||
|
|
||||||
void collectLiquid(List<Vec2I> const& tilePositions, LiquidId liquidId);
|
void collectLiquid(List<Vec2I> const& tilePositions, LiquidId liquidId);
|
||||||
|
|
||||||
void waitForLighting(Image* out = nullptr);
|
Maybe<Vec2I> waitForLighting(Image* out = nullptr);
|
||||||
|
|
||||||
typedef std::function<bool(PlayerPtr, StringView)> BroadcastCallback;
|
typedef std::function<bool(PlayerPtr, StringView)> BroadcastCallback;
|
||||||
BroadcastCallback& broadcastCallback();
|
BroadcastCallback& broadcastCallback();
|
||||||
@ -210,6 +210,7 @@ private:
|
|||||||
typedef function<ClientTile const& (Vec2I)> ClientTileGetter;
|
typedef function<ClientTile const& (Vec2I)> ClientTileGetter;
|
||||||
|
|
||||||
void lightingTileGather();
|
void lightingTileGather();
|
||||||
|
void lightingCalc();
|
||||||
void lightingMain();
|
void lightingMain();
|
||||||
|
|
||||||
void initWorld(WorldStartPacket const& packet);
|
void initWorld(WorldStartPacket const& packet);
|
||||||
@ -272,10 +273,19 @@ private:
|
|||||||
|
|
||||||
Mutex m_lightingMutex;
|
Mutex m_lightingMutex;
|
||||||
ConditionVariable m_lightingCond;
|
ConditionVariable m_lightingCond;
|
||||||
Mutex m_lightMapMutex;
|
|
||||||
Image m_lightMap;
|
|
||||||
atomic<bool> m_stopLightingThread;
|
atomic<bool> m_stopLightingThread;
|
||||||
|
|
||||||
|
Mutex m_lightMapPrepMutex;
|
||||||
|
Mutex m_lightMapMutex;
|
||||||
|
|
||||||
|
Image m_pendingLightMap;
|
||||||
|
Image m_lightMap;
|
||||||
|
List<LightSource> m_pendingLights;
|
||||||
|
List<std::pair<Vec2F, Vec3B>> m_pendingParticleLights;
|
||||||
|
RectI m_pendingLightRange;
|
||||||
|
Vec2I m_lightMinPosition;
|
||||||
|
List<PreviewTile> m_previewTiles;
|
||||||
|
|
||||||
SkyPtr m_sky;
|
SkyPtr m_sky;
|
||||||
|
|
||||||
CollisionGenerator m_collisionGenerator;
|
CollisionGenerator m_collisionGenerator;
|
||||||
|
@ -26,7 +26,6 @@ struct WorldRenderData {
|
|||||||
RenderTileArray tiles;
|
RenderTileArray tiles;
|
||||||
Vec2I lightMinPosition;
|
Vec2I lightMinPosition;
|
||||||
Image lightMap;
|
Image lightMap;
|
||||||
Image tileLightMap;
|
|
||||||
|
|
||||||
List<EntityDrawables> entityDrawables;
|
List<EntityDrawables> entityDrawables;
|
||||||
List<Particle> const* particles;
|
List<Particle> const* particles;
|
||||||
|
@ -49,7 +49,7 @@ void WorldPainter::update(float dt) {
|
|||||||
m_environmentPainter->update(dt);
|
m_environmentPainter->update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPainter::render(WorldRenderData& renderData, function<void()> lightWaiter) {
|
void WorldPainter::render(WorldRenderData& renderData, function<bool()> lightWaiter) {
|
||||||
m_camera.setScreenSize(m_renderer->screenSize());
|
m_camera.setScreenSize(m_renderer->screenSize());
|
||||||
m_camera.setTargetPixelRatio(Root::singleton().configuration()->get("zoomLevel").toFloat());
|
m_camera.setTargetPixelRatio(Root::singleton().configuration()->get("zoomLevel").toFloat());
|
||||||
|
|
||||||
@ -76,23 +76,24 @@ void WorldPainter::render(WorldRenderData& renderData, function<void()> lightWai
|
|||||||
|
|
||||||
m_renderer->flush();
|
m_renderer->flush();
|
||||||
|
|
||||||
|
bool lightMapUpdated = false;
|
||||||
if (lightWaiter) {
|
if (lightWaiter) {
|
||||||
auto start = Time::monotonicMicroseconds();
|
auto start = Time::monotonicMicroseconds();
|
||||||
lightWaiter();
|
lightMapUpdated = lightWaiter();
|
||||||
LogMap::set("client_render_world_async_light_wait", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - start));
|
LogMap::set("client_render_world_async_light_wait", strf(u8"{:05d}\u00b5s", Time::monotonicMicroseconds() - start));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderData.isFullbright) {
|
if (renderData.isFullbright) {
|
||||||
m_renderer->setEffectTexture("lightMap", Image::filled(Vec2U(1, 1), { 255, 255, 255, 255 }, PixelFormat::RGB24));
|
m_renderer->setEffectTexture("lightMap", Image::filled(Vec2U(1, 1), { 255, 255, 255, 255 }, PixelFormat::RGB24));
|
||||||
m_renderer->setEffectTexture("tileLightMap", Image::filled(Vec2U(1, 1), { 0, 0, 0, 0 }, PixelFormat::RGBA32));
|
|
||||||
m_renderer->setEffectParameter("lightMapMultiplier", 1.0f);
|
m_renderer->setEffectParameter("lightMapMultiplier", 1.0f);
|
||||||
} else {
|
} else {
|
||||||
|
if (lightMapUpdated) {
|
||||||
adjustLighting(renderData);
|
adjustLighting(renderData);
|
||||||
|
m_renderer->setEffectTexture("lightMap", renderData.lightMap);
|
||||||
|
}
|
||||||
m_renderer->setEffectParameter("lightMapMultiplier", m_assets->json("/rendering.config:lightMapMultiplier").toFloat());
|
m_renderer->setEffectParameter("lightMapMultiplier", m_assets->json("/rendering.config:lightMapMultiplier").toFloat());
|
||||||
m_renderer->setEffectParameter("lightMapScale", Vec2F::filled(TilePixels * m_camera.pixelRatio()));
|
m_renderer->setEffectParameter("lightMapScale", Vec2F::filled(TilePixels * m_camera.pixelRatio()));
|
||||||
m_renderer->setEffectParameter("lightMapOffset", m_camera.worldToScreen(Vec2F(renderData.lightMinPosition)));
|
m_renderer->setEffectParameter("lightMapOffset", m_camera.worldToScreen(Vec2F(renderData.lightMinPosition)));
|
||||||
m_renderer->setEffectTexture("lightMap", renderData.lightMap);
|
|
||||||
m_renderer->setEffectTexture("tileLightMap", renderData.tileLightMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parallax layers
|
// Parallax layers
|
||||||
|
@ -23,7 +23,7 @@ public:
|
|||||||
WorldCamera& camera();
|
WorldCamera& camera();
|
||||||
|
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
void render(WorldRenderData& renderData, function<void()> lightWaiter);
|
void render(WorldRenderData& renderData, function<bool()> lightWaiter);
|
||||||
void adjustLighting(WorldRenderData& renderData);
|
void adjustLighting(WorldRenderData& renderData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user