diff options
Diffstat (limited to 'src/World/Generation')
| -rw-r--r-- | src/World/Generation/Lighting.cpp | 54 | ||||
| -rw-r--r-- | src/World/Generation/Lighting.hpp | 30 |
2 files changed, 72 insertions, 12 deletions
diff --git a/src/World/Generation/Lighting.cpp b/src/World/Generation/Lighting.cpp index 8df6e2a..39d8320 100644 --- a/src/World/Generation/Lighting.cpp +++ b/src/World/Generation/Lighting.cpp @@ -1,20 +1,60 @@ #include "Lighting.hpp" -namespace MC::World::Generation::Lighting { +namespace MC::World::Generation { -void light_chunk(Chunk& chunk, ChunkNeighbors& _) { - for (UInt x = 0; x < Chunk::Width; x++) { - for (UInt z = 0; z < Chunk::Width; z++) { - U8 current_light_exposure = LightSun; - for (UInt y = Chunk::Height - 1; y != 0; y--) { +void Lighting::add_chunk(Chunk& chunk) { + for (U8 x = 0; x < Chunk::Width; x++) { + for (U8 z = 0; z < Chunk::Width; z++) { + U8 current_light_exposure = SunBrightness; + for (U8 y = Chunk::Height - 1; y != 0; y--) { auto& block = chunk.at(x, y, z); if (!block.type.is_translucent()) break; current_light_exposure = (Real)current_light_exposure * (1 - block.type.opacity()); - block.light = current_light_exposure; + add_block(chunk, {x, y, z}, current_light_exposure); } } } } +void Lighting::add_block(Chunk& chunk, Position::BlockLocal position, U8 light) { + auto& block = chunk.at(position); + block.light = light; + enqueue(chunk.index(), position, light); +} + +void Lighting::illuminate(ChunkRegistry& chunks) { + while (!m_queue.empty()) { + auto op = m_queue.front(); + m_queue.pop(); + + process(chunks, op); + } +} + +void Lighting::enqueue(ChunkIndex chunk, Position::BlockLocal position, U8 origin) { + m_queue.push({chunk, position, origin}); +} + +void Lighting::process(ChunkRegistry& chunks, Operation op) { + auto& chunk_data = chunks.get(op.chunk); + auto& chunk = chunk_data.chunk.value(); + + for (auto direction : Position::axis_directions) { + auto neighbor_pos = op.position.offset(direction); + if (!neighbor_pos.fits_within_chunk()) continue; + + auto& neighbor = chunk.at(neighbor_pos); + if (!neighbor.type.is_translucent()) continue; + + U8 falloff = (neighbor.type.opacity() + 1) * DefaultFalloff; + U8 target = std::max(op.origin - falloff, 0); + + if (neighbor.light < target) { + neighbor.light = target; + enqueue(op.chunk, neighbor_pos, target); + } + } +} + } diff --git a/src/World/Generation/Lighting.hpp b/src/World/Generation/Lighting.hpp index 7bb8fcc..72af0e1 100644 --- a/src/World/Generation/Lighting.hpp +++ b/src/World/Generation/Lighting.hpp @@ -1,13 +1,33 @@ #pragma once +#include <queue> #include "../Chunk.hpp" -#include "ChunkNeighbors.hpp" +#include "../ChunkIndex.hpp" +#include "../ChunkRegistry.hpp" +#include "../Position.hpp" -namespace MC::World::Generation::Lighting { +namespace MC::World::Generation { -constexpr U8 LightSun = 200; -constexpr U8 LightTorch = 100; +class Lighting { +public: + void add_chunk(Chunk& chunk); + void add_block(Chunk& chunk, Position::BlockLocal position, U8 light); -void light_chunk(Chunk& chunk, ChunkNeighbors& neighbors); + void illuminate(ChunkRegistry& chunks); +private: + static constexpr U8 SunBrightness = 200; + static constexpr U8 DefaultFalloff = 10; + + struct Operation { + ChunkIndex chunk; + Position::BlockLocal position; + U8 origin; + }; + + void enqueue(ChunkIndex chunk, Position::BlockLocal position, U8 origin); + void process(ChunkRegistry& chunks, Operation op); + + std::queue<Operation> m_queue; +}; } |
