Handle day-night transition in shader and make light sources brighter when shaders...
authorPerttu Ahola <celeron55@gmail.com>
Sun, 2 Dec 2012 12:24:58 +0000 (14:24 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 2 Dec 2012 12:24:58 +0000 (14:24 +0200)
client/shaders/test_shader_1/opengl_vertex.glsl
client/shaders/test_shader_2/opengl_vertex.glsl
src/content_mapblock.cpp
src/game.cpp
src/itemdef.cpp
src/mapblock_mesh.cpp
src/mapblock_mesh.h

index 4980850535f569f6a2c9aac316d46bbd05195db5..e24f58c099b254098aa80e25e1510bbdd7203783 100644 (file)
@@ -2,6 +2,7 @@
 uniform mat4 mWorldViewProj;\r
 uniform mat4 mInvWorld;\r
 uniform mat4 mTransWorld;\r
+uniform float dayNightRatio;\r
 \r
 varying vec3 vPosition;\r
 \r
@@ -11,15 +12,43 @@ void main(void)
 \r
        vPosition = (mWorldViewProj * gl_Vertex).xyz;\r
 \r
-       if(gl_Normal.y > 0.5)\r
-               gl_FrontColor = gl_BackColor = gl_Color;\r
-       else\r
-               gl_FrontColor = gl_BackColor = gl_Color * 0.7;\r
+       vec4 color;\r
+       //color = vec4(1.0, 1.0, 1.0, 1.0);\r
 \r
-       /*if(gl_Normal.y > 0.5)\r
-               gl_FrontColor = gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0);\r
-       else\r
-               gl_FrontColor = gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0) * 0.7;*/\r
+       float day = gl_Color.r;\r
+       float night = gl_Color.g;\r
+       float light_source = gl_Color.b;\r
+\r
+       /*color.r = mix(night, day, dayNightRatio);\r
+       color.g = color.r;\r
+       color.b = color.r;*/\r
+\r
+       float rg = mix(night, day, dayNightRatio);\r
+       rg += light_source * 1.0; // Make light sources brighter\r
+       float b = rg;\r
+\r
+       // Moonlight is blue\r
+       b += (day - night) / 13.0;\r
+       rg -= (day - night) / 13.0;\r
+\r
+       // Emphase blue a bit in darker places\r
+       // See C++ implementation in mapblock_mesh.cpp finalColorBlend()\r
+       b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);\r
+\r
+       // Artificial light is yellow-ish\r
+       // See C++ implementation in mapblock_mesh.cpp finalColorBlend()\r
+       rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);\r
+\r
+       color.r = rg;\r
+       color.g = rg;\r
+       color.b = b;\r
+\r
+       if(gl_Normal.y <= 0.5)\r
+               color *= 0.7;\r
+\r
+       color.a = gl_Color.a;\r
+\r
+       gl_FrontColor = gl_BackColor = color;\r
 \r
        gl_TexCoord[0] = gl_MultiTexCoord0;\r
 }\r
index 6286fc0d716d67e4425af1822e28ad9854db3e0a..80fd6d4275086f117f1a60fbd5df02ba7f44d8ec 100644 (file)
@@ -2,6 +2,7 @@
 uniform mat4 mWorldViewProj;\r
 uniform mat4 mInvWorld;\r
 uniform mat4 mTransWorld;\r
+uniform float dayNightRatio;\r
 \r
 varying vec3 vPosition;\r
 \r
@@ -13,8 +14,40 @@ void main(void)
 \r
        vPosition = (mWorldViewProj * gl_Vertex).xyz;\r
 \r
-       gl_FrontColor = gl_BackColor = gl_Color;\r
-       //gl_FrontColor = gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0);\r
+       vec4 color;\r
+       //color = vec4(1.0, 1.0, 1.0, 1.0);\r
+\r
+       float day = gl_Color.r;\r
+       float night = gl_Color.g;\r
+       float light_source = gl_Color.b;\r
+\r
+       /*color.r = mix(night, day, dayNightRatio);\r
+       color.g = color.r;\r
+       color.b = color.r;*/\r
+\r
+       float rg = mix(night, day, dayNightRatio);\r
+       rg += light_source * 1.0; // Make light sources brighter\r
+       float b = rg;\r
+\r
+       // Moonlight is blue\r
+       b += (day - night) / 13.0;\r
+       rg -= (day - night) / 13.0;\r
+\r
+       // Emphase blue a bit in darker places\r
+       // See C++ implementation in mapblock_mesh.cpp finalColorBlend()\r
+       b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);\r
+\r
+       // Artificial light is yellow-ish\r
+       // See C++ implementation in mapblock_mesh.cpp finalColorBlend()\r
+       rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);\r
+\r
+       color.r = rg;\r
+       color.g = rg;\r
+       color.b = b;\r
+\r
+       color.a = gl_Color.a;\r
+\r
+       gl_FrontColor = gl_BackColor = color;\r
 \r
        gl_TexCoord[0] = gl_MultiTexCoord0;\r
 }\r
index 68895c396d4553ef971acb8c104e504ebdeb222b..aa3c061d6c6d7afe1df2ff0f5517c9872f312188 100644 (file)
@@ -171,7 +171,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                continue;
 
                        u16 l = getInteriorLight(n, 0, data);
-                       video::SColor c = MapBlock_LightColor(f.alpha, l);
+                       video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
                        
                        video::S3DVertex vertices[4] =
                        {
@@ -226,7 +226,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        // Otherwise use the light of this node (the liquid)
                        else
                                l = getInteriorLight(n, 0, data);
-                       video::SColor c = MapBlock_LightColor(f.alpha, l);
+                       video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
                        
                        // Neighbor liquid levels (key = relative position)
                        // Includes current node
@@ -544,7 +544,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        AtlasPointer ap = tile.texture;
 
                        u16 l = getInteriorLight(n, 1, data);
-                       video::SColor c = MapBlock_LightColor(255, l);
+                       video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
 
                        for(u32 j=0; j<6; j++)
                        {
@@ -604,7 +604,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        AtlasPointer pa_leaves = tile_leaves.texture;
 
                        u16 l = getInteriorLight(n, 1, data);
-                       video::SColor c = MapBlock_LightColor(255, l);
+                       video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
 
                        v3f pos = intToFloat(p, BS);
                        aabb3f box(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2);
@@ -638,7 +638,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 
                        AtlasPointer ap = tile.texture;
 
-                       video::SColor c(255,255,255,255);
+                       u16 l = getInteriorLight(n, 1, data);
+                       video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
 
                        // Wall at X+ of node
                        video::S3DVertex vertices[4] =
@@ -683,7 +684,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        AtlasPointer ap = tile.texture;
 
                        u16 l = getInteriorLight(n, 0, data);
-                       video::SColor c = MapBlock_LightColor(255, l);
+                       video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
                                
                        float d = (float)BS/16;
                        // Wall at X+ of node
@@ -730,7 +731,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        AtlasPointer ap = tile.texture;
                        
                        u16 l = getInteriorLight(n, 1, data);
-                       video::SColor c = MapBlock_LightColor(255, l);
+                       video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
 
                        for(u32 j=0; j<4; j++)
                        {
@@ -793,7 +794,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                        tile.texture.id) + "^[transformR90");
                                        
                        u16 l = getInteriorLight(n, 1, data);
-                       video::SColor c = MapBlock_LightColor(255, l);
+                       video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
 
                        const f32 post_rad=(f32)BS/8;
                        const f32 bar_rad=(f32)BS/16;
@@ -996,7 +997,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        AtlasPointer ap = tile.texture;
                        
                        u16 l = getInteriorLight(n, 0, data);
-                       video::SColor c = MapBlock_LightColor(255, l);
+                       video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
 
                        float d = (float)BS/64;
                        
@@ -1045,7 +1046,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        }
 
                        u16 l = getInteriorLight(n, 0, data);
-                       video::SColor c = MapBlock_LightColor(255, l);
+                       video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
 
                        v3f pos = intToFloat(p, BS);
 
index 0c1a2137008bdcec0b3265ffe37a93db5219085c..fc780a808519af892f03fb973d400ebba276c20a 100644 (file)
@@ -841,13 +841,15 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
        Sky *m_sky;
        bool *m_force_fog_off;
        f32 *m_fog_range;
+       Client *m_client;
 
 public:
        GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
-                       f32 *fog_range):
+                       f32 *fog_range, Client *client):
                m_sky(sky),
                m_force_fog_off(force_fog_off),
-               m_fog_range(fog_range)
+               m_fog_range(fog_range),
+               m_client(client)
        {}
        ~GameGlobalShaderConstantSetter() {}
 
@@ -873,10 +875,12 @@ public:
                if(*m_force_fog_off)
                        fog_distance = 10000*BS;
                services->setPixelShaderConstant("fogDistance", &fog_distance, 1);
-       }
 
-private:
-       IrrlichtDevice *m_device;
+               // Day-night ratio
+               u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
+               float daynight_ratio_f = (float)daynight_ratio / 1000.0;
+               services->setPixelShaderConstant("dayNightRatio", &daynight_ratio_f, 1);
+       }
 };
 
 void the_game(
@@ -1307,8 +1311,8 @@ void the_game(
        /*
                Shader constants
        */
-       shsrc->addGlobalConstantSetter(
-                       new GameGlobalShaderConstantSetter(sky, &force_fog_off, &fog_range));
+       shsrc->addGlobalConstantSetter(new GameGlobalShaderConstantSetter(
+                       sky, &force_fog_off, &fog_range, &client));
 
        /*
                Main loop
index 9ce064ea4e480df75184288f43a275d898d9c9ab..260baadc0ff67bdabd35cec29ebf528b5431bdee 100644 (file)
@@ -30,6 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "tile.h"
 #endif
 #include "log.h"
+#include "main.h" // g_settings
+#include "settings.h"
 #include "util/serialize.h"
 #include "util/container.h"
 #include "util/thread.h"
@@ -356,7 +358,10 @@ public:
 
                        scene::IMesh *node_mesh = mapblock_mesh.getMesh();
                        assert(node_mesh);
-                       setMeshColor(node_mesh, video::SColor(255, 255, 255, 255));
+                       video::SColor c(255, 255, 255, 255);
+                       if(g_settings->getS32("enable_shaders") != 0)
+                               c = MapBlock_LightColor(255, 0xffff, decode_light(f.light_source));
+                       setMeshColor(node_mesh, c);
 
                        /*
                                Scale and translate the mesh so it's a unit cube
index a9f14f8f06cbd2d73c86cfc9d524c77ac7d09bc8..b2870509b52685843d1e41f2356d0184beaf0490 100644 (file)
@@ -435,7 +435,7 @@ struct FastFace
 };
 
 static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
-               v3f p, v3s16 dir, v3f scale, core::array<FastFace> &dest)
+               v3f p, v3s16 dir, v3f scale, u8 light_source, core::array<FastFace> &dest)
 {
        FastFace face;
        
@@ -477,16 +477,16 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
        float h = tile.texture.size.Y;
 
        face.vertices[0] = video::S3DVertex(vertex_pos[0], normal,
-                       MapBlock_LightColor(alpha, li0),
+                       MapBlock_LightColor(alpha, li0, light_source),
                        core::vector2d<f32>(x0+w*abs_scale, y0+h));
        face.vertices[1] = video::S3DVertex(vertex_pos[1], normal,
-                       MapBlock_LightColor(alpha, li1),
+                       MapBlock_LightColor(alpha, li1, light_source),
                        core::vector2d<f32>(x0, y0+h));
        face.vertices[2] = video::S3DVertex(vertex_pos[2], normal,
-                       MapBlock_LightColor(alpha, li2),
+                       MapBlock_LightColor(alpha, li2, light_source),
                        core::vector2d<f32>(x0, y0));
        face.vertices[3] = video::S3DVertex(vertex_pos[3], normal,
-                       MapBlock_LightColor(alpha, li3),
+                       MapBlock_LightColor(alpha, li3, light_source),
                        core::vector2d<f32>(x0+w*abs_scale, y0));
 
        face.tile = tile;
@@ -658,7 +658,8 @@ static void getTileInfo(
                v3s16 &p_corrected,
                v3s16 &face_dir_corrected,
                u16 *lights,
-               TileSpec &tile
+               TileSpec &tile,
+               u8 &light_source
        )
 {
        VoxelManipulator &vmanip = data->m_vmanip;
@@ -688,18 +689,20 @@ static void getTileInfo(
                tile = tile0;
                p_corrected = p;
                face_dir_corrected = face_dir;
+               light_source = ndef->get(n0).light_source;
        }
        else
        {
                tile = tile1;
                p_corrected = p + face_dir;
                face_dir_corrected = -face_dir;
+               light_source = ndef->get(n1).light_source;
        }
        
        // eg. water and glass
        if(equivalent)
                tile.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
-       
+
        if(data->m_smooth_lighting == false)
        {
                lights[0] = lights[1] = lights[2] = lights[3] =
@@ -743,9 +746,10 @@ static void updateFastFaceRow(
        v3s16 face_dir_corrected;
        u16 lights[4] = {0,0,0,0};
        TileSpec tile;
+       u8 light_source = 0;
        getTileInfo(data, p, face_dir, 
                        makes_face, p_corrected, face_dir_corrected,
-                       lights, tile);
+                       lights, tile, light_source);
 
        for(u16 j=0; j<MAP_BLOCKSIZE; j++)
        {
@@ -759,6 +763,7 @@ static void updateFastFaceRow(
                v3s16 next_face_dir_corrected;
                u16 next_lights[4] = {0,0,0,0};
                TileSpec next_tile;
+               u8 next_light_source = 0;
                
                // If at last position, there is nothing to compare to and
                // the face must be drawn anyway
@@ -769,7 +774,7 @@ static void updateFastFaceRow(
                        getTileInfo(data, p_next, face_dir,
                                        next_makes_face, next_p_corrected,
                                        next_face_dir_corrected, next_lights,
-                                       next_tile);
+                                       next_tile, next_light_source);
                        
                        if(next_makes_face == makes_face
                                        && next_p_corrected == p_corrected + translate_dir
@@ -778,7 +783,8 @@ static void updateFastFaceRow(
                                        && next_lights[1] == lights[1]
                                        && next_lights[2] == lights[2]
                                        && next_lights[3] == lights[3]
-                                       && next_tile == tile)
+                                       && next_tile == tile
+                                       && next_light_source == light_source)
                        {
                                next_is_different = false;
                        }
@@ -854,7 +860,7 @@ static void updateFastFaceRow(
                                }
                                
                                makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
-                                               sp, face_dir_corrected, scale,
+                                               sp, face_dir_corrected, scale, light_source,
                                                dest);
                                
                                g_profiler->avg("Meshgen: faces drawn by tiling", 0);
@@ -873,6 +879,7 @@ static void updateFastFaceRow(
                        lights[2] = next_lights[2];
                        lights[3] = next_lights[3];
                        tile = next_tile;
+                       light_source = next_light_source;
                }
                
                p = p_next;
@@ -1058,18 +1065,20 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
                        os<<"^[verticalframe:"<<(int)p.tile.animation_frame_count<<":0";
                        p.tile.texture = tsrc->getTexture(os.str());
                }
-               // - Lighting
-               for(u32 j = 0; j < p.vertices.size(); j++)
+               // - Classic lighting (shaders handle this by themselves)
+               if(!enable_shaders)
                {
-                       video::SColor &vc = p.vertices[j].Color;
-                       u8 day = vc.getRed();
-                       u8 night = vc.getGreen();
-                       finalColorBlend(vc, day, night, 1000);
-                       if(day != night)
-                               m_daynight_diffs[i][j] = std::make_pair(day, night);
+                       for(u32 j = 0; j < p.vertices.size(); j++)
+                       {
+                               video::SColor &vc = p.vertices[j].Color;
+                               u8 day = vc.getRed();
+                               u8 night = vc.getGreen();
+                               finalColorBlend(vc, day, night, 1000);
+                               if(day != night)
+                                       m_daynight_diffs[i][j] = std::make_pair(day, night);
+                       }
                }
 
-
                // Create material
                video::SMaterial material;
                material.setFlag(video::EMF_LIGHTING, false);
index 82268efd2948ad8e836dca639e34e06b343a6e74..c23b6cc5aab8c679ed9476502870ad11df8371d3 100644 (file)
@@ -160,9 +160,10 @@ struct MeshCollector
 //   alpha in the A channel of the returned SColor
 //   day light (0-255) in the R channel of the returned SColor
 //   night light (0-255) in the G channel of the returned SColor
-inline video::SColor MapBlock_LightColor(u8 alpha, u16 light)
+//   light source (0-255) in the B channel of the returned SColor
+inline video::SColor MapBlock_LightColor(u8 alpha, u16 light, u8 light_source=0)
 {
-       return video::SColor(alpha, (light & 0xff), (light >> 8), 0);
+       return video::SColor(alpha, (light & 0xff), (light >> 8), light_source);
 }
 
 // Compute light at node