#include "Lighting.hpp" namespace MC::World::Generation { 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()); 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(Chunk& chunk) { while (!m_queue.empty()) { auto op = m_queue.front(); m_queue.pop(); process(chunk, op); } } void Lighting::enqueue(ChunkIndex chunk, Position::BlockLocal position, U8 origin) { m_queue.push({chunk, position, origin}); } void Lighting::process(Chunk& chunk, Operation op) { 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); } } } }