]> git.localhorst.tv Git - blank.git/commitdiff
light entities according to block light level
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Fri, 30 Oct 2015 10:37:03 +0000 (11:37 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Fri, 30 Oct 2015 10:37:03 +0000 (11:37 +0100)
it's not that nice, but a start

doc/todo
src/graphics/DirectionalLighting.hpp
src/graphics/shader.cpp
src/ui/ui.cpp
src/world/World.hpp
src/world/world.cpp

index c6a3808160d9b05ce0e95cff091760c58716bc04..ed9fdce79353570197d9cd9e5d498117b0a29516 100644 (file)
--- a/doc/todo
+++ b/doc/todo
@@ -45,17 +45,12 @@ entity ai
 
        pathfinding, obstacle avoidance, better turning behaviour
 
-(block) lighting
+lighting
 
        occlusion/neighbor light mixing is implemented, but still linear
        this could be solved by using a pre-interpolated light texture and
        mapping light levels to coordinates on that
 
-       also: how could block light affect entity lighting?
-       maybe get the interpolated light level at the entity's center and use
-       that as the light power for the directional lighting shader and use a
-       direction that's fixed relative to the camera?
-
        there's a bug where a chunk's model is not updated if its neighbor
        changes border light levels
        I kinda mitigated it a little for direct neighbors during linking, but
@@ -65,6 +60,10 @@ entity ai
        having the light propagate into solid blocks, but feels like this
        could cause some weird behaviours
 
+       entity lighting is now derived from block light levels
+       it's not interpolated and the calculation is very basic, so it
+       has some unexpected effects
+
 gravity
 
        maybe like light levels? should also store a direction with it in
index 70492efc865f42f4597c3365717aacb3cd3b8ff9..42554014c51707b3dbd4d218cf68f001e8fb39f9 100644 (file)
@@ -20,6 +20,7 @@ public:
 
        void SetLightDirection(const glm::vec3 &) noexcept;
        void SetLightColor(const glm::vec3 &) noexcept;
+       void SetAmbientColor(const glm::vec3 &) noexcept;
 
        void SetTexture(ArrayTexture &) noexcept;
        void SetFogDensity(float) noexcept;
@@ -47,6 +48,7 @@ private:
        GLuint sampler_handle;
        GLuint light_direction_handle;
        GLuint light_color_handle;
+       GLuint ambient_color_handle;
        GLuint fog_density_handle;
 
 };
index 0c161f17d7b1308aca1c3ab15c5380b420c1711c..85f0184684eb791ba0f24c79a63c661a39378f1f 100644 (file)
@@ -180,6 +180,7 @@ DirectionalLighting::DirectionalLighting()
 , mvp_handle(0)
 , light_direction_handle(0)
 , light_color_handle(0)
+, ambient_color_handle(0)
 , fog_density_handle(0) {
        program.LoadShader(
                GL_VERTEX_SHADER,
@@ -217,6 +218,7 @@ DirectionalLighting::DirectionalLighting()
                "uniform sampler2DArray tex_sampler;\n"
                "uniform vec3 light_direction;\n"
                "uniform vec3 light_color;\n"
+               "uniform vec3 ambient_color;\n"
                "uniform float fog_density;\n"
                "out vec3 color;\n"
                "vec3 rgb2hsl(vec3 c) {\n"
@@ -239,7 +241,7 @@ DirectionalLighting::DirectionalLighting()
                        "hsl_color.y *= frag_hsl_mod.y;\n"
                        "hsl_color.z *= frag_hsl_mod.z;\n"
                        "vec3 base_color = hsl2rgb(hsl_color) * frag_rgb_mod;\n"
-                       "vec3 ambient = vec3(0.1, 0.1, 0.1) * base_color;\n"
+                       "vec3 ambient = ambient_color * base_color;\n"
                        // this should be the same as the clear color, otherwise looks really weird
                        "vec3 fog_color = vec3(0, 0, 0);\n"
                        "float e = 2.718281828;\n"
@@ -263,11 +265,13 @@ DirectionalLighting::DirectionalLighting()
        sampler_handle = program.UniformLocation("tex_sampler");
        light_direction_handle = program.UniformLocation("light_direction");
        light_color_handle = program.UniformLocation("light_color");
+       ambient_color_handle = program.UniformLocation("ambient_color");
        fog_density_handle = program.UniformLocation("fog_density");
 
        Activate();
        program.Uniform(light_direction_handle, glm::vec3(1.0f, 3.0f, 2.0f));
        program.Uniform(light_color_handle, glm::vec3(1.0f));
+       program.Uniform(ambient_color_handle, glm::vec3(0.1f));
        program.Uniform(fog_density_handle, 0.0f);
 }
 
@@ -290,6 +294,10 @@ void DirectionalLighting::SetLightColor(const glm::vec3 &col) noexcept {
        program.Uniform(light_color_handle, col);
 }
 
+void DirectionalLighting::SetAmbientColor(const glm::vec3 &col) noexcept {
+       program.Uniform(ambient_color_handle, col);
+}
+
 void DirectionalLighting::SetTexture(ArrayTexture &tex) noexcept {
        glActiveTexture(GL_TEXTURE0);
        tex.Bind();
index 8768095559cdf6335cf24be4043984c6cd0a7632..8563f7ded08409344be3957f7620640268ca7e3f 100644 (file)
@@ -433,6 +433,8 @@ void HUD::Render(Viewport &viewport) noexcept {
                if (block_visible) {
                        DirectionalLighting &world_prog = viewport.HUDProgram();
                        world_prog.SetLightDirection({ 1.0f, 3.0f, 5.0f });
+                       world_prog.SetLightColor({ 1.0f, 1.0f, 1.0f });
+                       world_prog.SetAmbientColor({ 0.1f, 0.1f, 0.1f });
                        // disable distance fog
                        world_prog.SetFogDensity(0.0f);
 
index 7ee5f4306a228260f172d594c8776056020fcb6d..273bfa63abc3809a507f77889015f044515b254c 100644 (file)
@@ -130,6 +130,14 @@ private:
                const EntityState &
        );
 
+       /// calculate light direction and intensity at entity's location
+       void GetLight(
+               const Entity &entity,
+               glm::vec3 &direction,
+               glm::vec3 &color,
+               glm::vec3 &ambient
+       );
+
 private:
        Config config;
 
index 4ac765c325635cddfe112a7efaee014ca526454f..46afc1b2a1525a325273cb776dd4ba64d97891ae 100644 (file)
@@ -656,17 +656,63 @@ World::EntityHandle World::RemoveEntity(EntityHandle &eh) {
 
 void World::Render(Viewport &viewport) {
        DirectionalLighting &entity_prog = viewport.EntityProgram();
-       entity_prog.SetLightDirection(light_direction);
        entity_prog.SetFogDensity(fog_density);
 
+       glm::vec3 light_dir;
+       glm::vec3 light_col;
+       glm::vec3 ambient_col;
        for (Entity &entity : entities) {
                glm::mat4 M(entity.Transform(players.front().GetEntity().ChunkCoords()));
                if (!CullTest(entity.Bounds(), entity_prog.GetVP() * M)) {
+                       GetLight(entity, light_dir, light_col, ambient_col);
+                       entity_prog.SetLightDirection(light_dir);
+                       entity_prog.SetLightColor(light_col);
+                       entity_prog.SetAmbientColor(ambient_col);
                        entity.Render(M, entity_prog);
                }
        }
 }
 
+// this should interpolate based on the fractional part of entity's block position
+void World::GetLight(
+       const Entity &e,
+       glm::vec3 &dir,
+       glm::vec3 &col,
+       glm::vec3 &amb
+) {
+       Chunk *chunk = chunks.Get(e.ChunkCoords());
+       if (!chunk) {
+               // chunk unavailable, so make it really dark and from
+               // some arbitrary direction
+               dir = glm::vec3(1.0f, 2.0f, 3.0f);
+               col = glm::vec3(0.025f); // ~0.8^15
+               return;
+       }
+       glm::ivec3 base(e.Position());
+       int base_light = chunk->GetLight(base);
+       int max_light = 0;
+       int min_light = 15;
+       glm::ivec3 acc(0, 0, 0);
+       for (glm::ivec3 offset(-1, -1, -1); offset.z < 2; ++offset.z) {
+               for (offset.y = -1; offset.y < 2; ++offset.y) {
+                       for (offset.x = -1; offset.x < 2; ++offset.x) {
+                               BlockLookup block(chunk, base + offset);
+                               if (!block) {
+                                       // missing, just ignore it
+                                       continue;
+                               }
+                               // otherwise, accumulate the difference times direction
+                               acc += offset * (base_light - block.GetLight());
+                               max_light = std::max(max_light, block.GetLight());
+                               min_light = std::min(min_light, block.GetLight());
+                       }
+               }
+       }
+       dir = acc;
+       col = glm::vec3(std::pow(0.8f, 15 - max_light));
+       amb = glm::vec3(std::pow(0.8f, 15 - min_light));
+}
+
 namespace {
 
 PrimitiveMesh::Buffer debug_buf;