Fixed lighting issues.

master
Quentin Bazin 2021-06-03 19:01:40 +02:00
parent 2bdc999294
commit 5ff8f9b78b
8 changed files with 40 additions and 38 deletions

View File

@ -399,25 +399,6 @@ inline u8 ChunkMeshBuilder::getAmbientOcclusion(s8f x, s8f y, s8f z, const gk::V
}
inline u8 ChunkMeshBuilder::getLightForVertex(Light light, s8f x, s8f y, s8f z, const gk::Vector3i &offset, const gk::Vector3i &normal, const ChunkData &chunk) {
std::function<s8(const ChunkData &chunk, s8, s8, s8)> getLight = [&](const ChunkData &chunk, s8 x, s8 y, s8 z) -> s8 {
// if (x < 0) return chunk->getSurroundingChunk(0) && chunk->getSurroundingChunk(0)->isInitialized() ? getLight(chunk->getSurroundingChunk(0), x + CHUNK_WIDTH, y, z) : -1;
// if (x >= CHUNK_WIDTH) return chunk->getSurroundingChunk(1) && chunk->getSurroundingChunk(1)->isInitialized() ? getLight(chunk->getSurroundingChunk(1), x - CHUNK_WIDTH, y, z) : -1;
// if (y < 0) return chunk->getSurroundingChunk(2) && chunk->getSurroundingChunk(2)->isInitialized() ? getLight(chunk->getSurroundingChunk(2), x, y + CHUNK_DEPTH, z) : -1;
// if (y >= CHUNK_DEPTH) return chunk->getSurroundingChunk(3) && chunk->getSurroundingChunk(3)->isInitialized() ? getLight(chunk->getSurroundingChunk(3), x, y - CHUNK_DEPTH, z) : -1;
// if (z < 0) return chunk->getSurroundingChunk(4) && chunk->getSurroundingChunk(4)->isInitialized() ? getLight(chunk->getSurroundingChunk(4), x, y, z + CHUNK_HEIGHT) : -1;
// if (z >= CHUNK_HEIGHT) return chunk->getSurroundingChunk(5) && chunk->getSurroundingChunk(5)->isInitialized() ? getLight(chunk->getSurroundingChunk(5), x, y, z - CHUNK_HEIGHT) : -1;
//
// if (light == Light::Sun)
// return chunk->isInitialized() ? chunk->lightmap().getSunlight(x, y, z) : -1;
// else
// return chunk->isInitialized() ? chunk->lightmap().getTorchlight(x, y, z) : -1;
// FIXME
return (light == Light::Sun)
? chunk.getSunlight(x, y, z)
: chunk.getTorchlight(x, y, z);
};
gk::Vector3i minOffset{
(normal.x != 0) ? offset.x : 0,
(normal.y != 0) ? offset.y : 0,
@ -431,6 +412,10 @@ inline u8 ChunkMeshBuilder::getLightForVertex(Light light, s8f x, s8f y, s8f z,
{x + offset.x, y + offset.y, z + offset.z}
};
auto getLight = [&](const ChunkData &chunk, s8 x, s8 y, s8 z) -> s8 {
return (light == Light::Sun) ? chunk.getSunlight(x, y, z) : chunk.getTorchlight(x, y, z);
};
// Get light values for surrounding nodes
s8 lightValues[4] = {
getLight(chunk, surroundingBlocks[0].x, surroundingBlocks[0].y, surroundingBlocks[0].z),

View File

@ -38,7 +38,7 @@
struct ChunkData {
s32 x, y, z;
u32 data[CHUNK_HEIGHT + 2][CHUNK_DEPTH + 2][CHUNK_WIDTH + 2];
u8 lightData[CHUNK_HEIGHT + 2][CHUNK_DEPTH + 2][CHUNK_WIDTH + 2];
std::optional<u8> lightData[CHUNK_HEIGHT + 2][CHUNK_DEPTH + 2][CHUNK_WIDTH + 2];
void loadFromChunk(const Chunk &chunk) {
x = chunk.x();
@ -49,7 +49,7 @@ struct ChunkData {
for (s8f y = -1 ; y <= CHUNK_DEPTH ; ++y) {
for (s8f x = -1 ; x <= CHUNK_WIDTH ; ++x) {
data[z + 1][y + 1][x + 1] = chunk.getFullBlock(x, y, z);
lightData[z + 1][y + 1][x + 1] = chunk.lightmap().getLightData(x, y, z);
lightData[z + 1][y + 1][x + 1] = chunk.lightmap().tryGetLightData(x, y, z);
}
}
}
@ -63,12 +63,14 @@ struct ChunkData {
return (data[z + 1][y + 1][x + 1] >> 16) & 0xffff;
}
u8 getTorchlight(s8f x, s8f y, s8f z) const {
return lightData[z + 1][y + 1][x + 1] & 0xf;
s8 getTorchlight(s8f x, s8f y, s8f z) const {
auto torchlight = lightData[z + 1][y + 1][x + 1];
return torchlight ? torchlight.value() & 0xf : -1;
}
u8 getSunlight(s8f x, s8f y, s8f z) const {
return (lightData[z + 1][y + 1][x + 1] >> 4) & 0xf;
s8 getSunlight(s8f x, s8f y, s8f z) const {
auto sunlight = lightData[z + 1][y + 1][x + 1];
return sunlight ? (sunlight.value() >> 4) & 0xf : -1;
}
const BlockState *getBlockState(s8f x, s8f y, s8f z) const {

View File

@ -80,7 +80,7 @@ void ClientWorld::update(bool allowWorldReload) {
void ClientWorld::requestChunkMeshing() {
for (auto it = m_chunksToMesh.begin() ; it != m_chunksToMesh.end() ; ) {
ClientChunk *chunk = (ClientChunk *)getChunk(it->second.x, it->second.y, it->second.z);
if(chunk && !chunk->isReadyForMeshing() && chunk->areAllNeighboursInitialized()) {
if(chunk && !chunk->isReadyForMeshing() && chunk->areAllNeighboursLoaded()) {
chunk->setReadyForMeshing(true);
chunk->setChanged();
addChunkToUpdate(chunk);
@ -133,7 +133,7 @@ void ClientWorld::receiveChunkData(Network::Packet &packet) {
chunk = it.first->second.get();
}
createChunkNeighbours(chunk);
linkChunkNeighbours(chunk);
// Receive chunk data
// bool hasUpdatedChunk = false;
@ -225,7 +225,7 @@ Chunk *ClientWorld::getChunk(int cx, int cy, int cz) const {
return it->second.get();
}
void ClientWorld::createChunkNeighbours(ClientChunk *chunk) {
void ClientWorld::linkChunkNeighbours(ClientChunk *chunk) {
gk::Vector3i surroundingChunks[6] = {
{chunk->x() - 1, chunk->y(), chunk->z()},
{chunk->x() + 1, chunk->y(), chunk->z()},
@ -242,14 +242,6 @@ void ClientWorld::createChunkNeighbours(ClientChunk *chunk) {
const s32 scz = surroundingChunks[i].z;
ClientChunk *neighbour = (ClientChunk *)getChunk(scx, scy, scz);
// if (!neighbour) {
// auto it = m_chunks.emplace(gk::Vector3i{scx, scy, scz}, new ClientChunk(scx, scy, scz, *m_dimension, *this, m_textureAtlas));
// neighbour = it.first->second.get();
// if (m_eventHandler)
// m_eventHandler->emplaceEvent<ChunkCreatedEvent>(gk::Vector3i{scx, scy, scz}, false);
// }
if (neighbour) {
chunk->setSurroundingChunk(i, neighbour);
neighbour->setSurroundingChunk((i % 2 == 0) ? i + 1 : i - 1, chunk);

View File

@ -80,7 +80,7 @@ class ClientWorld : public World, public gk::Drawable {
const Sky *sky() const { return m_sky; }
private:
void createChunkNeighbours(ClientChunk *chunk);
void linkChunkNeighbours(ClientChunk *chunk);
void draw(gk::RenderTarget &target, gk::RenderStates states) const override;

View File

@ -233,6 +233,13 @@ BlockData *Chunk::addBlockData(int x, int y, int z, int inventoryWidth, int inve
return it->second.get();
}
void Chunk::setSurroundingChunk(u8 i, Chunk *chunk) {
if (i < 6) {
m_surroundingChunkPresence.set(i, chunk != nullptr);
m_surroundingChunks[i] = chunk;
}
}
bool Chunk::areAllNeighboursInitialized() const {
return m_surroundingChunks[Chunk::West] && m_surroundingChunks[Chunk::West]->isInitialized()
&& m_surroundingChunks[Chunk::East] && m_surroundingChunks[Chunk::East]->isInitialized()

View File

@ -85,11 +85,13 @@ class Chunk : public gk::NonCopyable {
World &world() { return m_world; }
bool hasSurroundingChunk(u8 i) { return (i > 5) ? false : m_surroundingChunkPresence[i]; }
Chunk *getSurroundingChunk(u8 i) { return (i > 5) ? nullptr : m_surroundingChunks[i]; }
const Chunk *getSurroundingChunk(u8 i) const { return (i > 5) ? nullptr : m_surroundingChunks[i]; }
void setSurroundingChunk(u8 i, Chunk *chunk) { if (i < 6) m_surroundingChunks[i] = chunk; }
void setSurroundingChunk(u8 i, Chunk *chunk);
bool areAllNeighboursInitialized() const;
bool areAllNeighboursLoaded() const { return m_surroundingChunkPresence.all(); }
bool isInitialized() const { return m_isInitialized; }
void setInitialized(bool isInitialized) { m_isInitialized = isInitialized; }
@ -123,6 +125,7 @@ class Chunk : public gk::NonCopyable {
ChunkLightmap m_lightmap{this};
Chunk *m_surroundingChunks[6]{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
std::bitset<6> m_surroundingChunkPresence;
bool m_isInitialized = false;
bool m_hasChanged = false;

View File

@ -219,6 +219,17 @@ void ChunkLightmap::updateSunlight() {
}
}
std::optional<u8> ChunkLightmap::tryGetLightData(int x, int y, int z) const {
if(x < 0) return m_chunk->getSurroundingChunk(0) ? m_chunk->getSurroundingChunk(0)->lightmap().tryGetLightData(x + CHUNK_WIDTH, y, z) : std::nullopt;
if(x >= CHUNK_WIDTH) return m_chunk->getSurroundingChunk(1) ? m_chunk->getSurroundingChunk(1)->lightmap().tryGetLightData(x - CHUNK_WIDTH, y, z) : std::nullopt;
if(y < 0) return m_chunk->getSurroundingChunk(2) ? m_chunk->getSurroundingChunk(2)->lightmap().tryGetLightData(x, y + CHUNK_DEPTH, z) : std::nullopt;
if(y >= CHUNK_DEPTH) return m_chunk->getSurroundingChunk(3) ? m_chunk->getSurroundingChunk(3)->lightmap().tryGetLightData(x, y - CHUNK_DEPTH, z) : std::nullopt;
if(z < 0) return m_chunk->getSurroundingChunk(4) ? m_chunk->getSurroundingChunk(4)->lightmap().tryGetLightData(x, y, z + CHUNK_HEIGHT) : std::nullopt;
if(z >= CHUNK_HEIGHT) return m_chunk->getSurroundingChunk(5) ? m_chunk->getSurroundingChunk(5)->lightmap().tryGetLightData(x, y, z - CHUNK_HEIGHT) : std::nullopt;
return m_lightMap[z][y][x];
}
u8 ChunkLightmap::getLightData(int x, int y, int z) const {
if(x < 0) return m_chunk->getSurroundingChunk(0) ? m_chunk->getSurroundingChunk(0)->lightmap().getLightData(x + CHUNK_WIDTH, y, z) : 15;
if(x >= CHUNK_WIDTH) return m_chunk->getSurroundingChunk(1) ? m_chunk->getSurroundingChunk(1)->lightmap().getLightData(x - CHUNK_WIDTH, y, z) : 15;

View File

@ -27,6 +27,7 @@
#ifndef CHUNKLIGHTMAP_HPP_
#define CHUNKLIGHTMAP_HPP_
#include <optional>
#include <queue>
#include <gk/core/IntTypes.hpp>
@ -63,6 +64,7 @@ class ChunkLightmap {
void updateTorchlight();
void updateSunlight();
std::optional<u8> tryGetLightData(int x, int y, int z) const;
u8 getLightDataRaw(int x, int y, int z) const { return m_lightMap[z][y][x]; }
u8 getLightData(int x, int y, int z) const;
u8 getSunlight(int x, int y, int z) const;