From cf647ebf504eb523d822fa79622cb59d009680da Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Tue, 13 Mar 2018 19:30:05 +0500 Subject: Implemented basic lighting --- cwd/shaders/face.fs | 20 +++++--- src/Render.cpp | 14 ++++++ src/RendererSectionData.cpp | 4 +- src/RendererWorld.cpp | 102 +++++++++++++++++++-------------------- src/Section.cpp | 12 ++--- src/Section.hpp | 2 +- src/Vector.hpp | 2 +- src/World.cpp | 113 ++++++++++++++++++++++++++++++++++++++++++++ src/World.hpp | 4 ++ 9 files changed, 206 insertions(+), 67 deletions(-) diff --git a/cwd/shaders/face.fs b/cwd/shaders/face.fs index c4405d4..a4e020c 100644 --- a/cwd/shaders/face.fs +++ b/cwd/shaders/face.fs @@ -9,6 +9,7 @@ in VS_OUT { uniform sampler2D textureAtlas; uniform vec2 windowSize; +uniform float DayTime; vec3 rgb2hsv(vec3 c) { @@ -29,12 +30,19 @@ vec3 hsv2rgb(vec3 c) } void main() { - gl_FragColor = texture(textureAtlas,fs_in.Texture); - if (gl_FragColor.a < 0.3) + vec4 color = texture(textureAtlas,fs_in.Texture); + if (color.a < 0.3) discard; - vec3 hsvColor = rgb2hsv(gl_FragColor.xyz); + + vec3 hsvColor = rgb2hsv(color.xyz); hsvColor+=fs_in.Color; - gl_FragColor = vec4(hsv2rgb(hsvColor),1); - //float faceLight = clamp((fs_in.Light.x + fs_in.Light.y) / 15.0,0.2,1.0); - //gl_FragColor = vec4(gl_FragColor.rgb * faceLight,gl_FragColor.a); + color = vec4(hsv2rgb(hsvColor),1); + + float light = fs_in.Light.x / 15.0; + float skyLight = (fs_in.Light.y / 15.0) * DayTime; + + float faceLight = clamp(light + skyLight,0.2,1.0); + + color = vec4(color.rgb * faceLight, color.a); + gl_FragColor = color; } \ No newline at end of file diff --git a/src/Render.cpp b/src/Render.cpp index b5d24b6..ba8d0ed 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -343,6 +343,16 @@ void Render::RenderGui() { world->GameStatePtr()->player->pos.z, world->GameStatePtr()->player->onGround); + ImGui::Text( + "Player block pos: %d %d %d in %d %d %d", + (int)(world->GameStatePtr()->player->pos.x - std::floor(world->GameStatePtr()->player->pos.x / 16.0) * 16), + (int)(world->GameStatePtr()->player->pos.y - std::floor(world->GameStatePtr()->player->pos.y / 16.0) * 16), + (int)(world->GameStatePtr()->player->pos.z - std::floor(world->GameStatePtr()->player->pos.z / 16.0) * 16), + + (int)std::floor(world->GameStatePtr()->player->pos.x / 16.0), + (int)std::floor(world->GameStatePtr()->player->pos.y / 16.0), + (int)std::floor(world->GameStatePtr()->player->pos.z / 16.0)); + ImGui::Text( "Player vel: %.1f %.1f %.1f", world->GameStatePtr()->player->vel.x, @@ -359,6 +369,10 @@ void Render::RenderGui() { world->GameStatePtr()->selectedBlock.y, world->GameStatePtr()->selectedBlock.z, world->GameStatePtr()->distanceToSelectedBlock); + + ImGui::Text("Selected block light: %d (%d)", + world->GameStatePtr()->world.GetBlockLight(world->GameStatePtr()->selectedBlock), + world->GameStatePtr()->world.GetBlockSkyLight(world->GameStatePtr()->selectedBlock)); } ImGui::End(); diff --git a/src/RendererSectionData.cpp b/src/RendererSectionData.cpp index 1ed1099..067728f 100644 --- a/src/RendererSectionData.cpp +++ b/src/RendererSectionData.cpp @@ -289,7 +289,7 @@ RendererSectionData ParseSection(World * world, Vector sectionPosition) const BlockModel* model = GetInternalBlockModel(block, idModels); if (model) { - AddFacesByBlockModel(sectionsList, world, Vector(x, y, z), *model, transform, section.GetBlockLight(Vector(x, y, z)), section.GetBlockSkyLight(Vector(x, y, z)), blockVisibility, textureName, data); + AddFacesByBlockModel(sectionsList, world, Vector(x, y, z), *model, transform, world->GetBlockLight(Vector(x, y, z) + sectionPosition * 16), world->GetBlockSkyLight(Vector(x, y, z) + sectionPosition * 16), blockVisibility, textureName, data); } else { transform = glm::translate(transform, glm::vec3(0, 1, 0)); @@ -304,7 +304,7 @@ RendererSectionData ParseSection(World * world, Vector sectionPosition) data.models.push_back(transform); data.colors.push_back(glm::vec3(0, 0, 0)); - data.lights.push_back(glm::vec2(16, 16)); + data.lights.push_back(glm::vec2(world->GetBlockLight(Vector(x, y, z) + sectionPosition * 16), world->GetBlockSkyLight(Vector(x, y, z) + sectionPosition * 16))); } } diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index 7354c7c..64cdffc 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -317,6 +317,55 @@ void RendererWorld::Render(RenderState & renderState) { glCheckError(); } + //Render sky + renderState.TimeOfDay = gs->TimeOfDay; + renderState.SetActiveShader(skyShader->Program); + projectionLoc = glGetUniformLocation(skyShader->Program, "projection"); + viewLoc = glGetUniformLocation(skyShader->Program, "view"); + glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection)); + glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); + glm::mat4 model = glm::mat4(); + model = glm::translate(model, gs->player->pos.glm()); + const float scale = 1000000.0f; + model = glm::scale(model, glm::vec3(scale, scale, scale)); + float shift = gs->TimeOfDay / 24000.0f; + if (shift < 0) + shift *= -1.0f; + model = glm::rotate(model, glm::radians(90.0f), glm::vec3(0, 1.0f, 0.0f)); + model = glm::rotate(model, glm::radians(360.0f * shift), glm::vec3(-1.0f, 0.0f, 0.0f)); + modelLoc = glGetUniformLocation(skyShader->Program, "model"); + glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); + + glCheckError(); + + const int sunriseMin = 22000; + const int sunriseMax = 23500; + const int moonriseMin = 12000; + const int moonriseMax = 13500; + const float sunriseLength = sunriseMax - sunriseMin; + const float moonriseLength = moonriseMax - moonriseMin; + + float mixLevel = 0; + int dayTime = gs->TimeOfDay; + if (dayTime < 0) + dayTime *= -1; + while (dayTime > 24000) + dayTime -= 24000; + if (dayTime > 0 && dayTime < moonriseMin || dayTime > sunriseMax) //day + mixLevel = 1.0; + if (dayTime > moonriseMax && dayTime < sunriseMin) //night + mixLevel = 0.0; + if (dayTime >= sunriseMin && dayTime <= sunriseMax) //sunrise + mixLevel = (dayTime - sunriseMin) / sunriseLength; + if (dayTime >= moonriseMin && dayTime <= moonriseMax) { //moonrise + float timePassed = (dayTime - moonriseMin); + mixLevel = 1.0 - (timePassed / moonriseLength); + } + + glUniform1f(glGetUniformLocation(skyShader->Program, "DayTime"), mixLevel); + + rendererSky.Render(renderState); + glCheckError(); //Render sections renderState.SetActiveShader(blockShader->Program); @@ -324,7 +373,8 @@ void RendererWorld::Render(RenderState & renderState) { viewLoc = glGetUniformLocation(blockShader->Program, "view"); windowSizeLoc = glGetUniformLocation(blockShader->Program, "windowSize"); pvLoc = glGetUniformLocation(blockShader->Program, "projView"); - + + glUniform1f(glGetUniformLocation(blockShader->Program, "DayTime"), mixLevel); glUniformMatrix4fv(pvLoc, 1, GL_FALSE, glm::value_ptr(projView)); glUniform2f(windowSizeLoc, renderState.WindowWidth, renderState.WindowHeight); glCheckError(); @@ -373,56 +423,6 @@ void RendererWorld::Render(RenderState & renderState) { this->culledSections = culledSections; sectionsMutex.unlock(); glCheckError(); - - //Render sky - renderState.TimeOfDay = gs->TimeOfDay; - renderState.SetActiveShader(skyShader->Program); - projectionLoc = glGetUniformLocation(skyShader->Program, "projection"); - viewLoc = glGetUniformLocation(skyShader->Program, "view"); - glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection)); - glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); - glm::mat4 model = glm::mat4(); - model = glm::translate(model, gs->player->pos.glm()); - const float scale = 1000000.0f; - model = glm::scale(model, glm::vec3(scale, scale, scale)); - float shift = gs->TimeOfDay / 24000.0f; - if (shift < 0) - shift *= -1.0f; - model = glm::rotate(model, glm::radians(90.0f), glm::vec3(0, 1.0f, 0.0f)); - model = glm::rotate(model, glm::radians(360.0f * shift), glm::vec3(-1.0f, 0.0f, 0.0f)); - modelLoc = glGetUniformLocation(skyShader->Program, "model"); - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); - - glCheckError(); - - const int sunriseMin = 22000; - const int sunriseMax = 23500; - const int moonriseMin = 12000; - const int moonriseMax = 13500; - const float sunriseLength = sunriseMax - sunriseMin; - const float moonriseLength = moonriseMax - moonriseMin; - - float mixLevel = 0; - int dayTime = gs->TimeOfDay; - if (dayTime < 0) - dayTime *= -1; - while (dayTime > 24000) - dayTime -= 24000; - if (dayTime > 0 && dayTime < moonriseMin || dayTime > sunriseMax) //day - mixLevel = 1.0; - if (dayTime > moonriseMax && dayTime < sunriseMin) //night - mixLevel = 0.0; - if (dayTime >= sunriseMin && dayTime <= sunriseMax) //sunrise - mixLevel = (dayTime - sunriseMin) / sunriseLength; - if (dayTime >= moonriseMin && dayTime <= moonriseMax) { //moonrise - float timePassed = (dayTime - moonriseMin); - mixLevel = 1.0 - (timePassed / moonriseLength); - } - - glUniform1f(glGetUniformLocation(skyShader->Program, "DayTime"), mixLevel); - - rendererSky.Render(renderState); - glCheckError(); } void RendererWorld::PrepareRender() { diff --git a/src/Section.cpp b/src/Section.cpp index 71937e2..1f60471 100644 --- a/src/Section.cpp +++ b/src/Section.cpp @@ -46,7 +46,7 @@ Section::Section(Vector pos, unsigned char bitsPerBlock, std::vectorworldPosition = pos; this->block = std::move(blockData); this->palette = std::move(palette); - this->light = std::move(lightData); + this->light = std::move(lightData); this->sky = std::move(skyData); hash = -1; @@ -99,12 +99,12 @@ BlockId Section::GetBlockId(Vector pos) const { unsigned char Section::GetBlockLight(Vector pos) const { - if (light.empty()) - return 0; + if (light.empty()) + return 0; - int blockNumber = pos.y * 256 + pos.z * 16 + pos.x; - unsigned char lightValue = this->light[blockNumber / 2]; - return (blockNumber % 2 == 0) ? (lightValue & 0xF) : (lightValue >> 4); + int blockNumber = pos.y * 256 + pos.z * 16 + pos.x; + unsigned char lightValue = this->light[blockNumber / 2]; + return (blockNumber % 2 == 0) ? (lightValue & 0xF) : (lightValue >> 4); } unsigned char Section::GetBlockSkyLight(Vector pos) const diff --git a/src/Section.hpp b/src/Section.hpp index 7617c24..bc8b70b 100644 --- a/src/Section.hpp +++ b/src/Section.hpp @@ -25,7 +25,7 @@ public: Section() = default; BlockId GetBlockId(Vector pos) const; - + unsigned char GetBlockLight(Vector pos) const; unsigned char GetBlockSkyLight(Vector pos) const; diff --git a/src/Vector.hpp b/src/Vector.hpp index 03b1ec4..a067ea0 100644 --- a/src/Vector.hpp +++ b/src/Vector.hpp @@ -132,7 +132,7 @@ struct Vector3 { friend std::ostream &operator<<(std::ostream &os, const Vector3 &vector3) { - os << vector3.x << ", " << vector3.y << ", " << vector3.z; + os << vector3.x << " " << vector3.y << " " << vector3.z; return os; } }; diff --git a/src/World.cpp b/src/World.cpp index 67abc02..75e0b3f 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -395,4 +395,117 @@ Entity* World::GetEntityPtr(unsigned int EntityId) { } entitiesMutex.unlock(); return nullptr; +} + +unsigned char World::GetBlockLight(Vector pos) +{ + Vector sectionPos(std::floor(pos.x / 16.0), + std::floor(pos.y / 16.0), + std::floor(pos.z / 16.0)); + + Vector blockPos = pos - (sectionPos * 16); + + Section* section = GetSectionPtr(sectionPos); + Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0)); + Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0)); + Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0)); + Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0)); + Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1)); + Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1)); + + if (!section) + return 0; + + Vector directions[] = { + Vector(0,0,0), + 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 value = 0; + + for (const Vector &dir : directions) { + Vector vec = blockPos + 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 && xn) + dirValue = xn->GetBlockLight(Vector(15, vec.y, vec.z)); + if (vec.x > 15 && xp) + dirValue = xp->GetBlockLight(Vector(0, vec.y, vec.z)); + if (vec.y < 0 && yn) + dirValue = yn->GetBlockLight(Vector(vec.x, 15, vec.z)); + if (vec.y > 15 && yp) + dirValue = yp->GetBlockLight(Vector(vec.x, 0, vec.z)); + if (vec.z < 0 && zn) + dirValue = zn->GetBlockLight(Vector(vec.x, vec.y, 15)); + if (vec.z > 15 && zp) + dirValue = zp->GetBlockLight(Vector(vec.x, vec.y, 0)); + } else + dirValue = section->GetBlockLight(vec); + + value = _max(value, dirValue); + } + return value; +} + +unsigned char World::GetBlockSkyLight(Vector pos) +{ + Vector sectionPos( std::floor(pos.x / 16.0), + std::floor(pos.y / 16.0), + std::floor(pos.z / 16.0)); + + Vector blockPos = pos - (sectionPos * 16); + + Section* section = GetSectionPtr(sectionPos); + Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0)); + Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0)); + Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0)); + Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0)); + Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1)); + Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1)); + + if (!section) + return 0; + + Vector directions[] = { + Vector(0,0,0), + 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 value = 0; + + for (const Vector &dir : directions) { + Vector vec = blockPos + 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 && xn) + dirValue = xn->GetBlockSkyLight(Vector(15, vec.y, vec.z)); + if (vec.x > 15 && xp) + dirValue = xp->GetBlockSkyLight(Vector(0, vec.y, vec.z)); + if (vec.y < 0 && yn) + dirValue = yn->GetBlockSkyLight(Vector(vec.x, 15, vec.z)); + if (vec.y > 15 && yp) + dirValue = yp->GetBlockSkyLight(Vector(vec.x, 0, vec.z)); + if (vec.z < 0 && zn) + dirValue = zn->GetBlockSkyLight(Vector(vec.x, vec.y, 15)); + if (vec.z > 15 && zp) + dirValue = zp->GetBlockSkyLight(Vector(vec.x, vec.y, 0)); + } + else + dirValue = section->GetBlockSkyLight(vec); + + value = _max(value, dirValue); + } + return value; } \ No newline at end of file diff --git a/src/World.hpp b/src/World.hpp index 2c80b31..6800e46 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -84,4 +84,8 @@ public: void SetBlockSkyLight(Vector pos, unsigned char light); Section *GetSectionPtr(Vector position); + + unsigned char GetBlockLight(Vector pos); + + unsigned char GetBlockSkyLight(Vector pos); }; \ No newline at end of file -- cgit v1.2.3