Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: lighting optimization up to 39% #459

Merged
merged 5 commits into from
Mar 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 28 additions & 28 deletions src/client/lightview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ void LightView::resize(const Size& size, const uint16_t tileSize) {
m_pixels.resize(m_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]);
}
}
}

void LightView::addLightSource(const Point& pos, const Light& light, float brightness)
Expand Down Expand Up @@ -77,11 +90,10 @@ void LightView::resetShade(const Point& pos)
void LightView::draw(const Rect& dest, const Rect& src)
{
// draw light, only if there is darkness
m_pool->setEnable(isDark());
if (!isDark() || !m_pool->isValid()) return;
if (!isDark())
return;

g_drawPool.use(DrawPoolType::LIGHT);

updateCoords(dest, src);
updatePixels();

Expand Down Expand Up @@ -117,31 +129,19 @@ void LightView::updatePixels() {
if (m_updatingHash == m_hash)
return;

for (int x = 0; x < m_mapSize.width(); ++x) {
for (int y = 0; y < m_mapSize.height(); ++y) {
const Point pos(x * m_tileSize + m_tileSize / 2, y * m_tileSize + m_tileSize / 2);
const int index = (y * m_mapSize.width() + x);
const int colorIndex = index * 4;

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 = 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));
distance /= m_tileSize;

float intensity = (-distance + (light.intensity * light.brightness)) * .2f;
if (intensity < .01f) continue;
if (intensity > 1.f) intensity = 1.f;

const auto& lightColor = Color::from8bit(light.color) * intensity;
m_pixels[colorIndex] = std::max<int>(m_pixels[colorIndex], lightColor.r());
m_pixels[colorIndex + 1] = std::max<int>(m_pixels[colorIndex + 1], lightColor.g());
m_pixels[colorIndex + 2] = std::max<int>(m_pixels[colorIndex + 2], lightColor.b());
}
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));
}
}

Expand Down
32 changes: 32 additions & 0 deletions src/client/lightview.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class LightView : public LuaObject
{
public:
LightView(const Size& size, const uint16_t tileSize);
~LightView() { m_texture = nullptr; }

void resize(const Size& size, uint16_t tileSize);
void draw(const Rect& dest, const Rect& src);
Expand All @@ -45,6 +46,8 @@ class LightView : public LuaObject
}

bool isDark() const { return m_isDark; }
bool isEnabled() const { return m_pool->isEnabled(); }
void setEnabled(bool v) { m_pool->setEnable(v); }

private:
struct TileLight : public Light
Expand All @@ -55,6 +58,34 @@ 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
{
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<int>(r, color.r());
g = std::max<int>(g, color.g());
b = std::max<int>(b, color.b());
}

private:
uint8_t& r;
uint8_t& g;
uint8_t& b;
uint8_t& a;
};

void updateCoords(const Rect& dest, const Rect& src);
void updatePixels();

Expand All @@ -75,4 +106,5 @@ class LightView : public LuaObject
std::vector<size_t> m_tiles;
std::vector<uint8_t> m_pixels;
std::vector<TileLight> m_lights;
std::vector<TileColor> m_tileColors;
};
32 changes: 12 additions & 20 deletions src/client/mapview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

#include <framework/platform/platformwindow.h>

MapView::MapView() : m_pool(g_drawPool.get(DrawPoolType::MAP))
MapView::MapView() : m_pool(g_drawPool.get(DrawPoolType::MAP)), m_lightView(std::make_shared<LightView>(Size(), SPRITE_SIZE))
{
m_pool->onBeforeDraw([this] {
float fadeOpacity = 1.f;
Expand Down Expand Up @@ -104,9 +104,9 @@ void MapView::draw()

if (canFloorFade()) {
const float fadeLevel = getFadeLevel(m_cachedFirstVisibleFloor);
if (m_lastFadeLevel != fadeLevel && fadeLevel == 1.f) {
if (!m_fadeFinish && fadeLevel == 1.f) {
onFadeInFinished();
m_lastFadeLevel = fadeLevel;
m_fadeFinish = true;
}
}

Expand All @@ -117,7 +117,8 @@ void MapView::draw()
return;
}

if (m_lightView) m_lightView->draw(m_posInfo.rect, m_posInfo.srcRect);
if (isDrawingLights())
m_lightView->draw(m_posInfo.rect, m_posInfo.srcRect);
}

void MapView::drawFloor()
Expand All @@ -144,7 +145,7 @@ void MapView::drawFloor()

const auto& map = m_cachedVisibleTiles[z];

if (m_lightView && (m_fadeType != FadeType::OUT$ || fadeLevel == 1.f)) {
if (m_fadeType != FadeType::OUT$ || fadeLevel == 1.f) {
for (const auto& tile : map.shades) {
if (alwaysTransparent && tile->getPosition().isInRange(_camera, TRANSPARENT_FLOOR_VIEW_RANGE, TRANSPARENT_FLOOR_VIEW_RANGE, true))
continue;
Expand Down Expand Up @@ -295,7 +296,7 @@ void MapView::updateVisibleTiles()
}
} else if (prevFirstVisibleFloor > m_cachedFirstVisibleFloor) { // showing floor
m_fadeType = FadeType::IN$;
m_lastFadeLevel = 0.f;
m_fadeFinish = false;
for (int iz = m_cachedFirstVisibleFloor; iz < prevFirstVisibleFloor; ++iz) {
const int shift = std::max<int>(0, m_floorFading - m_fadingFloorTimers[iz].elapsed_millis());
m_fadingFloorTimers[iz].restart(shift * 1000);
Expand Down Expand Up @@ -402,7 +403,7 @@ 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);
if (m_lightView->isEnabled()) m_lightView->resize(m_drawDimension, tileSize);
g_mainDispatcher.addEvent([=, this]() {
m_pool->getFrameBuffer()->resize(bufferSize);
});
Expand Down Expand Up @@ -441,11 +442,7 @@ void MapView::onGlobalLightChange(const Light&)

void MapView::updateLight()
{
if (!m_lightView) return;

const auto& cameraPosition = getCameraPosition();

Light ambientLight = cameraPosition.z > SEA_FLOOR ? Light() : g_map.getLight();
Light ambientLight = getCameraPosition().z > SEA_FLOOR ? Light() : g_map.getLight();
ambientLight.intensity = std::max<uint8_t >(m_minimumAmbientLight * 255, ambientLight.intensity);
m_lightView->setGlobalLight(ambientLight);
}
Expand Down Expand Up @@ -768,17 +765,12 @@ 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))
pool->setEnable(enable);
m_lightView->setEnabled(enable);

if (enable) {
if (m_lightView)
return;

m_lightView = std::make_shared<LightView>(m_drawDimension, m_tileSize);

m_lightView->resize(m_drawDimension, m_tileSize);
requestUpdateVisibleTiles();
} else m_lightView = nullptr;
}

updateLight();
}
Expand Down
4 changes: 2 additions & 2 deletions src/client/mapview.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class MapView : public LuaObject
bool isDrawingHealthBars() const { return m_drawHealthBars; }

void setDrawLights(bool enable);
bool isDrawingLights() const { return m_lightView && m_lightView->isDark(); }
bool isDrawingLights() const { return m_lightView && m_lightView->isEnabled() && m_lightView->isDark(); }

void setLimitVisibleDimension(bool v) { m_limitVisibleDimension = v; }
bool isLimitedVisibleDimension() const { return m_limitVisibleDimension; }
Expand Down Expand Up @@ -260,7 +260,6 @@ class MapView : public LuaObject
float m_fadeInTime{ 0 };
float m_fadeOutTime{ 0 };
float m_shadowFloorIntensity{ 0 };
float m_lastFadeLevel{ 1.f };

Rect m_rectDimension;

Expand All @@ -287,6 +286,7 @@ class MapView : public LuaObject
bool m_drawNames{ true };
bool m_smooth{ true };
bool m_follow{ true };
bool m_fadeFinish{ false };

bool m_autoViewMode{ false };
bool m_drawViewportEdge{ false };
Expand Down