Smooth day-night transitions
authorPerttu Ahola <celeron55@gmail.com>
Sun, 2 Dec 2012 16:02:04 +0000 (18:02 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 2 Dec 2012 16:02:45 +0000 (18:02 +0200)
src/camera.cpp
src/daynightratio.h
src/environment.cpp
src/game.cpp
src/light.h
src/mapnode.h
src/scriptapi.cpp

index ca2a6eb53db8365a503aeb495b12ad7884225bb1..1b9a8c763e6518e176daeeec787b076f28476c76 100644 (file)
@@ -544,7 +544,7 @@ void Camera::wield(const ItemStack &item)
 void Camera::drawWieldedTool()
 {
        // Set vertex colors of wield mesh according to light level
-       u8 li = decode_light(m_wieldlight);
+       u8 li = m_wieldlight;
        video::SColor color(255,li,li,li);
        setMeshColor(m_wieldnode->getMesh(), color);
 
index 9b31ecddd23d776b309d2c28fcc1f530abd0d1e0..96c6729ebf88c1420845016d50af8702e2d47b7c 100644 (file)
@@ -20,23 +20,49 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef DAYNIGHTRATIO_HEADER
 #define DAYNIGHTRATIO_HEADER
 
-inline u32 time_to_daynight_ratio(u32 time_of_day)
+inline u32 time_to_daynight_ratio(float time_of_day, bool smooth)
 {
-       s32 t = time_of_day%24000;
-       if(t < 4500 || t >= 19500)
-               return 150;
-       else if(t < 4750 || t >= 19250)
-               return 250;
-       else if(t < 5000 || t >= 19000)
-               return 350;
-       else if(t < 5250 || t >= 18750)
-               return 500;
-       else if(t < 5500 || t >= 18500)
-               return 675;
-       else if(t < 5750 || t >= 18250)
-               return 875;
-       else
+       float t = time_of_day;
+       if(t < 0)
+               t += ((int)(-t)/24000)*24000;
+       if(t >= 24000)
+               t -= ((int)(t)/24000)*24000;
+       if(t > 12000)
+               t = 24000 - t;
+       float values[][2] = {
+               {4250+125, 150},
+               {4500+125, 150},
+               {4750+125, 250},
+               {5000+125, 350},
+               {5250+125, 500},
+               {5500+125, 675},
+               {5750+125, 875},
+               {6000+125, 1000},
+               {6250+125, 1000},
+       };
+       if(!smooth){
+               float lastt = values[0][0];
+               for(u32 i=1; i<sizeof(values)/sizeof(*values); i++){
+                       float t0 = values[i][0];
+                       float switch_t = (t0 + lastt) / 2;
+                       lastt = t0;
+                       if(switch_t <= t)
+                               continue;
+                       return values[i][1];
+               }
                return 1000;
+       } else {
+               for(u32 i=0; i<sizeof(values)/sizeof(*values); i++){
+                       if(values[i][0] <= t)
+                               continue;
+                       if(i == 0)
+                               return values[i][1];
+                       float td0 = values[i][0] - values[i-1][0];
+                       float f = (t - values[i-1][0]) / td0;
+                       return f * values[i][1] + (1.0 - f) * values[i-1][1];
+               }
+               return 1000;
+       }
 }
 
 #endif
index e70cb39b784d42a38a6e93f118e408a9e3c3e5f9..5bf127a174c658a7c15d4a94705046b08987ae19 100644 (file)
@@ -203,7 +203,8 @@ void Environment::printPlayers(std::ostream &o)
 
 u32 Environment::getDayNightRatio()
 {
-       return time_to_daynight_ratio(m_time_of_day);
+       bool smooth = (g_settings->getS32("enable_shaders") != 0);
+       return time_to_daynight_ratio(m_time_of_day_f*24000, smooth);
 }
 
 void Environment::stepTimeOfDay(float dtime)
@@ -2132,15 +2133,15 @@ void ClientEnvironment::step(float dtime)
                }
                
                // Update lighting on all players on client
-               u8 light = LIGHT_MAX;
+               float light = 1.0;
                try{
                        // Get node at head
                        v3s16 p = player->getLightPosition();
                        MapNode n = m_map->getNode(p);
-                       light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
+                       light = n.getLightBlendF1((float)getDayNightRatio()/1000, m_gamedef->ndef());
                }
                catch(InvalidPositionException &e){
-                       light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
+                       light = blend_light_f1((float)getDayNightRatio()/1000, LIGHT_SUN, 0);
                }
                player->light = light;
        }
index fc780a808519af892f03fb973d400ebba276c20a..5c3805c3b64e15f35bf39bc537c012c64b3d9383 100644 (file)
@@ -2505,8 +2505,7 @@ void the_game(
                        Calculate general brightness
                */
                u32 daynight_ratio = client.getEnv().getDayNightRatio();
-               float time_brightness = (float)decode_light(
-                               (daynight_ratio * LIGHT_SUN) / 1000) / 255.0;
+               float time_brightness = decode_light_f((float)daynight_ratio/1000.0);
                float direct_brightness = 0;
                bool sunlight_seen = false;
                if(g_settings->getBool("free_move")){
index 218af348e1a21419add94aecc622cd9051a4c50d..f1c458ad8bc42bfdadb4386995cfae9ec8980e78 100644 (file)
@@ -85,6 +85,24 @@ inline u8 decode_light(u8 light)
        return light_decode_table[light];
 }
 
+// 0.0 <= light <= 1.0
+// 0.0 <= return value <= 1.0
+inline float decode_light_f(float light_f)
+{
+       s32 i = (u32)(light_f * LIGHT_MAX + 0.5);
+
+       if(i <= 0)
+               return (float)light_decode_table[0] / 255.0;
+       if(i >= LIGHT_MAX)
+               return (float)light_decode_table[LIGHT_MAX] / 255.0;
+
+       float v1 = (float)light_decode_table[i-1] / 255.0;
+       float v2 = (float)light_decode_table[i] / 255.0;
+       float f0 = (float)i - 0.5;
+       float f = light_f * LIGHT_MAX - f0;
+       return f * v2 + (1.0 - f) * v1;
+}
+
 // 0 <= daylight_factor <= 1000
 // 0 <= lightday, lightnight <= LIGHT_SUN
 // 0 <= return value <= LIGHT_SUN
@@ -97,5 +115,15 @@ inline u8 blend_light(u32 daylight_factor, u8 lightday, u8 lightnight)
        return l;
 }
 
+// 0.0 <= daylight_factor <= 1.0
+// 0 <= lightday, lightnight <= LIGHT_SUN
+// 0 <= return value <= 255
+inline u8 blend_light_f1(float daylight_factor, u8 lightday, u8 lightnight)
+{
+       u8 l = ((daylight_factor * decode_light(lightday) +
+                       (1.0-daylight_factor) * decode_light(lightnight)));
+       return l;
+}
+
 #endif
 
index a95497ef5c3c50e3202838299146d46c28e6e89c..de2529e4d12279823752d64756753bf546913670 100644 (file)
@@ -163,6 +163,16 @@ struct MapNode
                return blend_light(daylight_factor, lightday, lightnight);
        }
 
+       // 0.0 <= daylight_factor <= 1.0
+       // 0 <= return value <= LIGHT_SUN
+       u8 getLightBlendF1(float daylight_factor, INodeDefManager *nodemgr) const
+       {
+               u8 lightday = 0;
+               u8 lightnight = 0;
+               getLightBanks(lightday, lightnight, nodemgr);
+               return blend_light_f1(daylight_factor, lightday, lightnight);
+       }
+
        u8 getFaceDir(INodeDefManager *nodemgr) const;
        u8 getWallMounted(INodeDefManager *nodemgr) const;
        v3s16 getWallMountedDir(INodeDefManager *nodemgr) const;
index e5815c4620dd57cd1bcea72c14c88a6d8c40d867..e26e880a99095173c5d5e7b544ff1407f1a57ddf 100644 (file)
@@ -3604,7 +3604,7 @@ private:
                if(lua_isnumber(L, 3))
                        time_of_day = 24000.0 * lua_tonumber(L, 3);
                time_of_day %= 24000;
-               u32 dnr = time_to_daynight_ratio(time_of_day);
+               u32 dnr = time_to_daynight_ratio(time_of_day, true);
                MapNode n = env->getMap().getNodeNoEx(pos);
                try{
                        MapNode n = env->getMap().getNode(pos);