From 749e24c0ca1ea5d1d3166ce52ca98601135e0bcc Mon Sep 17 00:00:00 2001 From: LaG1924 Date: Sat, 25 Dec 2021 11:20:36 +0500 Subject: Added smooth lighting --- src/RendererSectionData.cpp | 238 ++++++++++++++++++-------------------------- src/RendererSectionData.hpp | 44 ++++++-- src/RendererWorld.cpp | 16 +-- 3 files changed, 143 insertions(+), 155 deletions(-) diff --git a/src/RendererSectionData.cpp b/src/RendererSectionData.cpp index 979858e..b5260f4 100644 --- a/src/RendererSectionData.cpp +++ b/src/RendererSectionData.cpp @@ -25,12 +25,44 @@ glm::vec2 TransformTextureCoord(glm::vec4 TextureAtlasCoords, glm::vec2 UvCoords return transformed; } -void AddFacesByBlockModel(RendererSectionData &data, const BlockFaces &model, const glm::mat4 &transform, bool visibility[FaceDirection::none], BlockLightness light, BlockLightness skyLight) { - for (const auto &face : model.faces) { - glm::vec2 lightness; - lightness.x = _max(light.face[0], light.face[1], light.face[2], light.face[3], light.face[4], light.face[5]); - lightness.y = _max(skyLight.face[0], skyLight.face[1], skyLight.face[2], skyLight.face[3], skyLight.face[4], skyLight.face[5]); - if (face.visibility != FaceDirection::none) { +//Maps [0.0, 0.5] range to [0.0, 1.0] +float MapNeg(float x) { + float y = x * 2.0f; + return glm::clamp(y, 0.0f, 1.0f); +} + +//Maps [0.5, 1.0] range to [0.0, 1.0] +float MapPos(float x) { + float y = (x * 2.0f) - 1.0f; + return glm::clamp(y, 0.0f, 1.0f); +} + +float InterpolateBlockLightness(const BlockLightness& light, const glm::vec3 &point) { + float xNeg = MapNeg(point.x); + float xPos = MapPos(point.x); + float xNegLight = glm::mix(light.face[FaceDirection::east], light.self, xNeg); + float xPosLight = glm::mix(light.self, light.face[FaceDirection::west], xPos); + float xLight = (glm::max)(xNegLight, xPosLight); + + float yNeg = MapNeg(point.y); + float yPos = MapPos(point.y); + float yNegLight = glm::mix(light.face[FaceDirection::down], light.self, yNeg); + float yPosLight = glm::mix(light.self, light.face[FaceDirection::up], yPos); + float yLight = (glm::max)(yNegLight, yPosLight); + + float zNeg = MapNeg(point.z); + float zPos = MapPos(point.z); + float zNegLight = glm::mix(light.face[FaceDirection::south], light.self, zNeg); + float zPosLight = glm::mix(light.self, light.face[FaceDirection::north], zPos); + float zLight = (glm::max)(zNegLight, zPosLight); + + return (glm::max)(xLight, (glm::max)(yLight, zLight)); +} + +void AddFacesByBlockModel(RendererSectionData& data, const BlockFaces& model, const glm::mat4& transform, bool visibility[FaceDirection::none], const Vector &pos, const SectionsData §ions) { + glm::vec3 absPos = (sections.data[1][1][1].GetPosition() * 16).glm(); + for (const auto& face : model.faces) { + if (face.visibility != FaceDirection::none) { FaceDirection direction = face.visibility; Vector directionVec = model.faceDirectionVector[direction]; FaceDirection faceDirection = FaceDirection::none; @@ -45,7 +77,6 @@ void AddFacesByBlockModel(RendererSectionData &data, const BlockFaces &model, co if (visibility[faceDirection]) continue; - lightness = glm::vec2(light.face[faceDirection], skyLight.face[faceDirection]); } data.vertices.emplace_back(); @@ -68,12 +99,37 @@ void AddFacesByBlockModel(RendererSectionData &data, const BlockFaces &model, co vertexData.layerAnimationAo.r = face.layer; vertexData.layerAnimationAo.g = face.frames; vertexData.colors = face.color; - vertexData.lights[0] = lightness; - vertexData.lights[1] = lightness; - vertexData.lights[2] = lightness; - vertexData.lights[3] = lightness; - vertexData.layerAnimationAo.b = model.ambientOcclusion ? 1.0f : 0.0f; - } + + bool useSmoothLighting = true; + if (useSmoothLighting) { + for (size_t i = 0; i < 4; i++) { + glm::vec3 baseLightPos = vertexData.positions[i] - absPos; + glm::vec3 lightPos = baseLightPos + normal * 0.5f; + glm::ivec3 basePos = glm::trunc(lightPos); + BlockLightness light = sections.GetLight(Vector(basePos.x, basePos.y, basePos.z)); + BlockLightness skyLight = sections.GetSkyLight(Vector(basePos.x, basePos.y, basePos.z)); + vertexData.lights[i].x = InterpolateBlockLightness(light, lightPos - glm::vec3(basePos)); + vertexData.lights[i].y = InterpolateBlockLightness(skyLight, lightPos - glm::vec3(basePos)); + } + } else { + BlockLightness light = sections.GetLight(pos); + BlockLightness skyLight = sections.GetSkyLight(pos); + glm::vec2 lightness; + + lightness.x = face.visibility != FaceDirection::none ? light.face[face.visibility] : light.self; + lightness.x = (glm::max)(lightness.x, static_cast(light.self)); + + lightness.y = face.visibility != FaceDirection::none ? skyLight.face[face.visibility] : skyLight.self; + lightness.y = (glm::max)(lightness.y, static_cast(skyLight.self)); + + vertexData.lights[0] = lightness; + vertexData.lights[1] = lightness; + vertexData.lights[2] = lightness; + vertexData.lights[3] = lightness; + } + + vertexData.layerAnimationAo.b = model.ambientOcclusion ? 1.0f : 0.0f; + } } BlockFaces *GetInternalBlockModel(const BlockId& id, std::vector> &idModels) { @@ -125,7 +181,7 @@ std::array SetBlockIdData(const SectionsData §ions) { for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { - blockIdData[y * 256 + z * 16 + x] = sections.section.GetBlockId(Vector(x, y, z)); + blockIdData[y * 256 + z * 16 + x] = sections.data[1][1][1].GetBlockId(Vector(x, y, z)); } } } @@ -141,10 +197,10 @@ RendererSectionData ParseSection(const SectionsData §ions) { std::array blockVisibility = GetBlockVisibilityData(sections, blockIdData, idModels); std::string textureName; - data.hash = sections.section.GetHash(); - data.sectionPos = sections.section.GetPosition(); + data.hash = sections.data[1][1][1].GetHash(); + data.sectionPos = sections.data[1][1][1].GetPosition(); - glm::mat4 baseOffset = glm::translate(glm::mat4(1.0), (sections.section.GetPosition() * 16).glm()), transform; + glm::mat4 baseOffset = glm::translate(glm::mat4(1.0), (sections.data[1][1][1].GetPosition() * 16).glm()), transform; for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { @@ -157,11 +213,8 @@ RendererSectionData ParseSection(const SectionsData §ions) { transform = glm::translate(baseOffset, vec.glm()); - BlockLightness light = sections.GetLight(vec); - BlockLightness skyLight = sections.GetSkyLight(vec); - BlockFaces *model = GetInternalBlockModel(block, idModels); - AddFacesByBlockModel(data, *model, transform, blockVisibility[y * 256 + z * 16 + x], light, skyLight); + AddFacesByBlockModel(data, *model, transform, blockVisibility[y * 256 + z * 16 + x], vec, sections); } } } @@ -171,127 +224,34 @@ RendererSectionData ParseSection(const SectionsData §ions) { } BlockId SectionsData::GetBlockId(const Vector &pos) const { - if (pos.x < 0) - return east.GetBlockId(Vector(15, pos.y, pos.z)); - - if (pos.x > 15) - return west.GetBlockId(Vector(0, pos.y, pos.z)); - - if (pos.y < 0) - return bottom.GetBlockId(Vector(pos.x, 15, pos.z)); - - if (pos.y > 15) - return top.GetBlockId(Vector(pos.x, 0, pos.z)); - - if (pos.z < 0) - return south.GetBlockId(Vector(pos.x, pos.y, 15)); - - if (pos.z > 15) - return north.GetBlockId(Vector(pos.x, pos.y, 0)); - - return section.GetBlockId(pos); + Vector sectionPos = pos; + return GetSection(sectionPos).GetBlockId(sectionPos); } -BlockLightness SectionsData::GetLight(const Vector &pos) const { - BlockLightness lightness; - static const Vector directions[] = { - Vector(1,0,0), - Vector(-1,0,0), - Vector(0,1,0), - Vector(0,-1,0), - Vector(0,0,1), - Vector(0,0,-1), - }; - - unsigned char self = section.GetBlockLight(pos); - - for (const Vector &dir : directions) { - Vector vec = pos + dir; - unsigned char dirValue = 0; - - if (vec.x < 0 || vec.x > 15 || vec.y < 0 || vec.y > 15 || vec.z < 0 || vec.z > 15) { - if (vec.x < 0) - dirValue = east.GetBlockLight(Vector(15, vec.y, vec.z)); - if (vec.x > 15) - dirValue = west.GetBlockLight(Vector(0, vec.y, vec.z)); - if (vec.y < 0) - dirValue = bottom.GetBlockLight(Vector(vec.x, 15, vec.z)); - if (vec.y > 15) - dirValue = top.GetBlockLight(Vector(vec.x, 0, vec.z)); - if (vec.z < 0) - dirValue = south.GetBlockLight(Vector(vec.x, vec.y, 15)); - if (vec.z > 15) - dirValue = north.GetBlockLight(Vector(vec.x, vec.y, 0)); - } - else - dirValue = section.GetBlockLight(vec); - - dirValue = _max(self, dirValue); - - if (dir == directions[0]) - lightness.face[FaceDirection::east] = dirValue; - if (dir == directions[1]) - lightness.face[FaceDirection::west] = dirValue; - if (dir == directions[2]) - lightness.face[FaceDirection::up] = dirValue; - if (dir == directions[3]) - lightness.face[FaceDirection::down] = dirValue; - if (dir == directions[4]) - lightness.face[FaceDirection::south] = dirValue; - if (dir == directions[5]) - lightness.face[FaceDirection::north] = dirValue; - } - return lightness; +BlockLightness SectionsData::GetLight(const Vector& pos) const { + BlockLightness lightness; + for (size_t i = 0; i <= FaceDirection::none; i++) { + Vector vec = pos + FaceDirectionVector[i]; + uint8_t dirValue = GetSection(vec).GetBlockLight(vec); + + if (i == FaceDirection::none) + lightness.self = dirValue; + else + lightness.face[i] = dirValue; + } + return lightness; } BlockLightness SectionsData::GetSkyLight(const Vector &pos) const { - BlockLightness lightness; - static const Vector directions[] = { - Vector(1,0,0), - Vector(-1,0,0), - Vector(0,1,0), - Vector(0,-1,0), - Vector(0,0,1), - Vector(0,0,-1), - }; - - unsigned char self = section.GetBlockSkyLight(pos); - - for (const Vector &dir : directions) { - Vector vec = pos + dir; - unsigned char dirValue = 0; - - if (vec.x < 0 || vec.x > 15 || vec.y < 0 || vec.y > 15 || vec.z < 0 || vec.z > 15) { - if (vec.x < 0) - dirValue = east.GetBlockSkyLight(Vector(15, vec.y, vec.z)); - if (vec.x > 15) - dirValue = west.GetBlockSkyLight(Vector(0, vec.y, vec.z)); - if (vec.y < 0) - dirValue = bottom.GetBlockSkyLight(Vector(vec.x, 15, vec.z)); - if (vec.y > 15) - dirValue = top.GetBlockSkyLight(Vector(vec.x, 0, vec.z)); - if (vec.z < 0) - dirValue = south.GetBlockSkyLight(Vector(vec.x, vec.y, 15)); - if (vec.z > 15) - dirValue = north.GetBlockSkyLight(Vector(vec.x, vec.y, 0)); - } - else - dirValue = section.GetBlockSkyLight(vec); - - dirValue = _max(self, dirValue); - - if (dir == directions[0]) - lightness.face[FaceDirection::east] = dirValue; - if (dir == directions[1]) - lightness.face[FaceDirection::west] = dirValue; - if (dir == directions[2]) - lightness.face[FaceDirection::up] = dirValue; - if (dir == directions[3]) - lightness.face[FaceDirection::down] = dirValue; - if (dir == directions[4]) - lightness.face[FaceDirection::south] = dirValue; - if (dir == directions[5]) - lightness.face[FaceDirection::north] = dirValue; - } - return lightness; + BlockLightness lightness; + for (size_t i = 0; i <= FaceDirection::none; i++) { + Vector vec = pos + FaceDirectionVector[i]; + uint8_t dirValue = GetSection(vec).GetBlockSkyLight(vec); + + if (i == FaceDirection::none) + lightness.self = dirValue; + else + lightness.face[i] = dirValue; + } + return lightness; } diff --git a/src/RendererSectionData.hpp b/src/RendererSectionData.hpp index efc6cad..9eb99ad 100644 --- a/src/RendererSectionData.hpp +++ b/src/RendererSectionData.hpp @@ -11,17 +11,45 @@ class World; struct BlockLightness { - unsigned char face[FaceDirection::none] = { 0,0,0,0,0,0 }; + uint8_t face[FaceDirection::none + 1] = { 0,0,0,0,0,0 }; + uint8_t self = 0; }; struct SectionsData { - Section section; - Section west; - Section east; - Section top; - Section bottom; - Section north; - Section south; + Section data[3][3][3]; + + const Section& GetSection(Vector& pos) const { + size_t x = 1, y = 1, z = 1; + while (true) { + if (pos.x < 0) { + x--; + pos.x += 16; + } + else if (pos.x > 15) { + x++; + pos.x -= 16; + } + else if (pos.y < 0) { + y--; + pos.y += 16; + } + else if (pos.y > 15) { + y++; + pos.y -= 16; + } + else if (pos.z < 0) { + z--; + pos.z += 16; + } + else if (pos.z > 15) { + z++; + pos.z -= 16; + } + else + break; + } + return data[x][y][z]; + } BlockId GetBlockId(const Vector &pos) const; diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index 21f0db2..057cf1e 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -57,13 +57,13 @@ void RendererWorld::ParseQueueUpdate() { vec.y -= 4500; } - parsing[id].data.section = GetGameState()->GetWorld().GetSection(vec); - parsing[id].data.north = GetGameState()->GetWorld().GetSection(vec + Vector(0, 0, 1)); - parsing[id].data.south = GetGameState()->GetWorld().GetSection(vec + Vector(0, 0, -1)); - parsing[id].data.west = GetGameState()->GetWorld().GetSection(vec + Vector(1, 0, 0)); - parsing[id].data.east = GetGameState()->GetWorld().GetSection(vec + Vector(-1, 0, 0)); - parsing[id].data.bottom = GetGameState()->GetWorld().GetSection(vec + Vector(0, -1, 0)); - parsing[id].data.top = GetGameState()->GetWorld().GetSection(vec + Vector(0, 1, 0)); + for (int x = -1; x < 2; x++) { + for (int y = -1; y < 2; y++) { + for (int z = -1; z < 2; z++) { + parsing[id].data.data[x + 1][y + 1][z + 1] = GetGameState()->GetWorld().GetSection(vec + Vector(x, y, z)); + } + } + } parsing[id].parsing = true; @@ -97,7 +97,7 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() { bool skip = false; for (int i = 0; i < RendererWorld::parsingBufferSize; i++) { - if (parsing[i].data.section.GetHash() == section.GetHash()) { + if (parsing[i].data.data[1][1][1].GetHash() == section.GetHash()) { skip = true; break; } -- cgit v1.2.3