]> 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
 
 
        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
 
 
        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
        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
 
        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
 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 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;
 
        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 sampler_handle;
        GLuint light_direction_handle;
        GLuint light_color_handle;
+       GLuint ambient_color_handle;
        GLuint fog_density_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)
 , mvp_handle(0)
 , light_direction_handle(0)
 , light_color_handle(0)
+, ambient_color_handle(0)
 , fog_density_handle(0) {
        program.LoadShader(
                GL_VERTEX_SHADER,
 , 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 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"
                "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"
                        "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"
                        // 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");
        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));
        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);
 }
 
        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);
 }
 
        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();
 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 });
                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);
 
                        // disable distance fog
                        world_prog.SetFogDensity(0.0f);
 
index 7ee5f4306a228260f172d594c8776056020fcb6d..273bfa63abc3809a507f77889015f044515b254c 100644 (file)
@@ -130,6 +130,14 @@ private:
                const EntityState &
        );
 
                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;
 
 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();
 
 void World::Render(Viewport &viewport) {
        DirectionalLighting &entity_prog = viewport.EntityProgram();
-       entity_prog.SetLightDirection(light_direction);
        entity_prog.SetFogDensity(fog_density);
 
        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)) {
        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);
                }
        }
 }
 
                        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;
 namespace {
 
 PrimitiveMesh::Buffer debug_buf;