Attempting to propogate light downwards
parent
0bfe269308
commit
aa624464e0
|
@ -95,7 +95,7 @@ void main() {
|
|||
float sunlightIntensity = 1;
|
||||
// float sunlightIntensity = aLight.w * clamp(sin(time / 2.5) + 0.25, 0, 1) / MAX_SUNLIGHT;
|
||||
vec3 blockLightColor = (aLight.xyz / MAX_BLOCKLIGHT) * vec3(1 + sunlightIntensity / 4);
|
||||
vec3 sunlightColor = clamp(sunlightIntensity * 1.25 * vec3(1, 0.9, 0.75) * (aLight.w / 16.0), 0, 1);
|
||||
vec3 sunlightColor = clamp(sunlightIntensity * 1.25 * vec3(1, 1, 1) * (aLight.w / 15.0), 0, 1);
|
||||
vec3 resultantLight = vec3(max(sunlightColor.x, blockLightColor.x), max(sunlightColor.y, blockLightColor.y), max(sunlightColor.z, blockLightColor.z));
|
||||
|
||||
vec4 worldPos = model * pos;
|
||||
|
|
|
@ -245,8 +245,8 @@ void MapGen::generateSunlight(MapGen::chunk_partials_map &chunks, glm::ivec3 mbP
|
|||
if (b.y < 0) {
|
||||
b.y = 15;
|
||||
c.y = c.y ? c.y - 1 : 3;
|
||||
if (c.y == 3) break;
|
||||
chunk = chunks[mbPos * 4 + c].second;
|
||||
if (c.y == 3) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -268,8 +268,7 @@ void MapGen::propogateSunlightNodes(MapGen::chunk_partials_map &chunks, std::que
|
|||
unsigned char lightLevel = node.chunk->getSunlight(node.index);
|
||||
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
|
||||
|
||||
const static std::array<glm::ivec3, 6> checks = { glm::ivec3 {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1} };
|
||||
for (const auto& i : checks) {
|
||||
for (const auto& i : Vec::adj) {
|
||||
glm::ivec3 check = worldPos + i;
|
||||
|
||||
BlockChunk* chunk;
|
||||
|
@ -283,9 +282,7 @@ void MapGen::propogateSunlightNodes(MapGen::chunk_partials_map &chunks, std::que
|
|||
|
||||
auto ind = Space::Block::index(check);
|
||||
if (defs.blockFromId(chunk->getBlock(ind)).lightPropagates && chunk->getSunlight(ind) + 2 <= lightLevel) {
|
||||
int subtract = 1;
|
||||
if (lightLevel == 15 && i == checks[2]) subtract = 0;
|
||||
chunk->setSunlight(ind, lightLevel - subtract);
|
||||
chunk->setSunlight(ind, lightLevel - static_cast<int>(!(lightLevel == 15 && i.y == -1)));
|
||||
queue.emplace(ind, chunk);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,31 +4,161 @@
|
|||
|
||||
#include "Dimension.h"
|
||||
|
||||
bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) {
|
||||
if (!DimensionBase::setBlock(pos, block)) return false;
|
||||
|
||||
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||
auto &def = defs.blockFromId(block);
|
||||
|
||||
// Remove light when placing solid blocks.
|
||||
glm::ivec4 oldLight = chunk->getLight(Space::Block::index(pos));
|
||||
if (!def.lightPropagates && oldLight.x + oldLight.y + oldLight.z != 0) removeBlockLight(pos);
|
||||
|
||||
// Add light when placing light emitting blocks.
|
||||
glm::ivec3 newLight = def.lightSource;
|
||||
if (newLight.x > oldLight.x || newLight.y > oldLight.y || newLight.z > oldLight.z) addBlockLight(pos, newLight);
|
||||
|
||||
// Reflow light when a transparent block is placed.
|
||||
if (def.lightPropagates) reflowLightAroundTransparent(pos);
|
||||
|
||||
// Block sunlight when a solid block is placed.
|
||||
if (!def.lightPropagates && getLight(pos, chunk.get()).w != 0) reflowSunlightAroundSolid(pos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Dimension::calculateEdgeLight(glm::ivec3 mbPos) {
|
||||
for (auto i = 0; i < 64; i++) {
|
||||
glm::ivec3 l = Space::Chunk::fromIndex(i);
|
||||
glm::ivec3 chunkPos = mbPos * 4 + l;
|
||||
|
||||
auto edges = std::array<bool, 6> { l.x == 0, l.y == 0, l.z == 0,
|
||||
l.x == Space::MAPBLOCK_SIZE, l.y == Space::MAPBLOCK_SIZE, l.z == Space::MAPBLOCK_SIZE};
|
||||
l.x == Space::MAPBLOCK_SIZE - 1, l.y == Space::MAPBLOCK_SIZE - 1, l.z == Space::MAPBLOCK_SIZE - 1};
|
||||
|
||||
// Pull light from above
|
||||
if (edges[4]) {
|
||||
if (!getChunk(chunkPos + glm::ivec3 {0, 1, 0})) continue;
|
||||
auto chunk = getChunk(chunkPos).get();
|
||||
|
||||
for (unsigned int j = 0; j < 16; j++) {
|
||||
for (unsigned int k = 0; k < 16; k++) {
|
||||
glm::ivec3 belowPos = chunkPos * 16 + glm::ivec3 {j, 15, k};
|
||||
glm::ivec3 abovePos = belowPos + glm::ivec3 {0, 1, 0};
|
||||
|
||||
unsigned int lightAbove = getLight(abovePos).w;
|
||||
unsigned int lightBelow = getLight(belowPos).w;
|
||||
if (lightBelow > lightAbove) {
|
||||
unsigned int ind = Space::Block::index(belowPos);
|
||||
lightRemoveQueue[SUNLIGHT_CHANNEL].emplace(ind, lightBelow, chunk);
|
||||
chunk->setSunlight(ind, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push light below
|
||||
if (edges[1]) {
|
||||
for (unsigned int j = 0; j < 64; j++) {
|
||||
for (unsigned int k = 0; k < 64; k++) {
|
||||
auto belowChunk = getChunk(chunkPos + glm::ivec3 {0, -1, 0}).get();
|
||||
if (!belowChunk) continue;
|
||||
|
||||
for (unsigned int j = 0; j < 16; j++) {
|
||||
for (unsigned int k = 0; k < 16; k++) {
|
||||
glm::ivec3 abovePos = chunkPos * 16 + glm::ivec3 {j, 0, k};
|
||||
glm::ivec3 belowPos = abovePos + glm::ivec3 {0, -1, 0};
|
||||
|
||||
unsigned int lightAbove = getLight(abovePos).w;
|
||||
unsigned int lightBelow = getLight(belowPos).w;
|
||||
if (lightBelow > lightAbove) {
|
||||
unsigned int ind = Space::Block::index(belowPos);
|
||||
lightRemoveQueue[SUNLIGHT_CHANNEL].emplace(ind, lightBelow, belowChunk);
|
||||
belowChunk->setSunlight(ind, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
propogateRemoveNodes();
|
||||
}
|
||||
|
||||
void Dimension::reflowSunlightAroundSolid(glm::ivec3 pos) {
|
||||
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||
auto ind = Space::Block::index(pos);
|
||||
unsigned int light = startChunk->getSunlight(ind);
|
||||
startChunk->setSunlight(ind, 0);
|
||||
lightRemoveQueue[SUNLIGHT_CHANNEL].emplace(ind, light, startChunk.get());
|
||||
propogateRemoveNodes();
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
|
||||
|
||||
for (unsigned int channel = 0; channel < lightAddQueue.size(); channel++) {
|
||||
while (!lightAddQueue[channel].empty()) {
|
||||
LightAddNode& node = lightAddQueue[channel].front();
|
||||
unsigned char lightLevel = node.chunk->getLight(node.index, channel);
|
||||
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
|
||||
|
||||
for (const auto& i : Vec::adj) {
|
||||
glm::ivec3 check = worldPos + i;
|
||||
unsigned int ind = Space::Block::index(check);
|
||||
BlockChunk* chunk;
|
||||
if (containsWorldPos(node.chunk, check)) chunk = node.chunk;
|
||||
else {
|
||||
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
chunksUpdated.insert(chunk->pos);
|
||||
chunk->dirty = true;
|
||||
}
|
||||
|
||||
bool sunDown = channel == SUNLIGHT_CHANNEL && lightLevel == 15 && i.y == -1;
|
||||
if (defs.blockFromId(chunk->getBlock(ind)).lightPropagates && (sunDown || chunk->getLight(ind, channel) + 2 <= lightLevel)) {
|
||||
int subtract = sunDown ? 0 : 1;
|
||||
chunk->setLight(ind, channel, lightLevel - subtract);
|
||||
lightAddQueue[channel].emplace(ind, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
lightAddQueue[channel].pop();
|
||||
}
|
||||
}
|
||||
|
||||
return chunksUpdated;
|
||||
}
|
||||
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
|
||||
|
||||
for (unsigned int channel = 0; channel < lightRemoveQueue.size(); channel++) {
|
||||
while (!lightRemoveQueue[channel].empty()) {
|
||||
LightRemoveNode& node = lightRemoveQueue[channel].front();
|
||||
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
|
||||
|
||||
for (const auto& i : Vec::adj) {
|
||||
glm::ivec3 check = worldPos + i;
|
||||
unsigned int ind = Space::Block::index(check);
|
||||
BlockChunk* chunk;
|
||||
if (containsWorldPos(node.chunk, check)) chunk = node.chunk;
|
||||
else {
|
||||
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
chunksUpdated.insert(chunk->pos);
|
||||
chunk->dirty = true;
|
||||
}
|
||||
|
||||
unsigned char checkLight = chunk->getLight(ind, channel);
|
||||
if (checkLight != 0 && (checkLight < node.value || (i.y == -1 && node.value == 15))) {
|
||||
unsigned int replaceLight = channel == SUNLIGHT_CHANNEL ? 0 :
|
||||
defs.blockFromId(chunk->getBlock(Space::Block::index(check))).lightSource[channel];
|
||||
chunk->setLight(ind, channel, replaceLight);
|
||||
|
||||
if (replaceLight) lightAddQueue[channel].emplace(ind, chunk);
|
||||
lightRemoveQueue[channel].emplace(ind, checkLight, chunk);
|
||||
}
|
||||
else if (checkLight >= node.value) {
|
||||
auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
lightAddQueue[channel].emplace(ind, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
lightRemoveQueue[channel].pop();
|
||||
}
|
||||
}
|
||||
|
||||
propogateAddNodes(); //TODO: Merge returned chunks with our list
|
||||
return chunksUpdated;
|
||||
}
|
||||
|
||||
bool Dimension::containsWorldPos(BlockChunk *chunk, glm::ivec3 pos) {
|
||||
|
@ -93,103 +223,11 @@ void Dimension::reflowLightAroundTransparent(glm::ivec3 pos) {
|
|||
propogateAddNodes();
|
||||
}
|
||||
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
|
||||
|
||||
for (unsigned int channel = 0; channel < lightAddQueue.size(); channel++) {
|
||||
while (!lightAddQueue[channel].empty()) {
|
||||
LightAddNode& node = lightAddQueue[channel].front();
|
||||
unsigned char lightLevel = node.chunk->getLight(node.index, channel);
|
||||
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
|
||||
|
||||
for (const auto& i : Vec::adj) {
|
||||
glm::ivec3 check = worldPos + i;
|
||||
unsigned int ind = Space::Block::index(check);
|
||||
BlockChunk* chunk;
|
||||
if (containsWorldPos(node.chunk, check)) chunk = node.chunk;
|
||||
else {
|
||||
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
chunksUpdated.insert(chunk->pos);
|
||||
chunk->dirty = true;
|
||||
}
|
||||
|
||||
bool sunDown = channel == SUNLIGHT_CHANNEL && lightLevel == 15 && i.y == -1;
|
||||
if (defs.blockFromId(chunk->getBlock(ind)).lightPropagates && (sunDown || chunk->getLight(ind, channel) + 2 <= lightLevel)) {
|
||||
int subtract = sunDown ? 0 : 1;
|
||||
chunk->setLight(ind, channel, lightLevel - subtract);
|
||||
lightAddQueue[channel].emplace(ind, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
lightAddQueue[channel].pop();
|
||||
}
|
||||
}
|
||||
|
||||
return chunksUpdated;
|
||||
}
|
||||
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
|
||||
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
|
||||
|
||||
for (unsigned int channel = 0; channel < lightRemoveQueue.size(); channel++) {
|
||||
while (!lightRemoveQueue[channel].empty()) {
|
||||
LightRemoveNode& node = lightRemoveQueue[channel].front();
|
||||
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
|
||||
|
||||
for (const auto& i : Vec::adj) {
|
||||
glm::ivec3 check = worldPos + i;
|
||||
unsigned int ind = Space::Block::index(check);
|
||||
BlockChunk* chunk;
|
||||
if (containsWorldPos(node.chunk, check)) chunk = node.chunk;
|
||||
else {
|
||||
chunk = getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
chunksUpdated.insert(chunk->pos);
|
||||
chunk->dirty = true;
|
||||
}
|
||||
|
||||
unsigned char checkLight = chunk->getLight(ind, channel);
|
||||
if (checkLight != 0 && (checkLight < node.value || (i.y == -1 && node.value == 15))) {
|
||||
auto blockLight = defs.blockFromId(chunk->getBlock(Space::Block::index(check))).lightSource[channel];
|
||||
chunk->setLight(Space::Block::index(check), channel, blockLight);
|
||||
if (blockLight) lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
|
||||
lightRemoveQueue[channel].emplace(Space::Block::index(check), checkLight, chunk);
|
||||
}
|
||||
else if (checkLight >= node.value) {
|
||||
auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get();
|
||||
if (!chunk) continue;
|
||||
lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
|
||||
}
|
||||
}
|
||||
|
||||
lightRemoveQueue[channel].pop();
|
||||
}
|
||||
}
|
||||
|
||||
propogateAddNodes(); //TODO: Merge returned chunks with our list
|
||||
return chunksUpdated;
|
||||
}
|
||||
|
||||
bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) {
|
||||
if (!DimensionBase::setBlock(pos, block)) return false;
|
||||
|
||||
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||
auto &def = defs.blockFromId(block);
|
||||
|
||||
// Remove light when placing solid blocks.
|
||||
glm::ivec4 oldLight = chunk->getLight(Space::Block::index(pos));
|
||||
if (!def.lightPropagates && oldLight.x + oldLight.y + oldLight.z != 0) removeBlockLight(pos);
|
||||
|
||||
// Add light when placing light emitting blocks.
|
||||
glm::ivec3 newLight = def.lightSource;
|
||||
if (newLight.x > oldLight.x || newLight.y > oldLight.y || newLight.z > oldLight.z) addBlockLight(pos, newLight);
|
||||
|
||||
// Reflow light when a transparent block is placed.
|
||||
if (def.lightPropagates) reflowLightAroundTransparent(pos);
|
||||
|
||||
// Block sunlight when a solid block is placed.
|
||||
if (!def.lightPropagates && getLight(pos, chunk.get()).w != 0) reflowSunlightAroundSolid(pos);
|
||||
|
||||
return true;
|
||||
}
|
||||
void Dimension::reflowSunlightAroundSolid(glm::ivec3 pos) {
|
||||
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||
auto ind = Space::Block::index(pos);
|
||||
unsigned int light = startChunk->getSunlight(ind);
|
||||
startChunk->setSunlight(ind, 0);
|
||||
lightRemoveQueue[SUNLIGHT_CHANNEL].emplace(ind, light, startChunk.get());
|
||||
propogateRemoveNodes();
|
||||
}
|
Loading…
Reference in New Issue