Add display_gamma option for client
authorCraig Robbins <kde.psych@gmail.com>
Sun, 14 Dec 2014 11:28:08 +0000 (21:28 +1000)
committerCraig Robbins <kde.psych@gmail.com>
Tue, 30 Dec 2014 16:44:31 +0000 (02:44 +1000)
minetest.conf.example
src/clientmap.cpp
src/defaultsettings.cpp
src/game.cpp
src/light.cpp
src/light.h
src/mapnode.h

index 95b88c84b8443d4eace480ec41ac7a04b7fbf4a4..8570eb052ab4c19d6a635fa98aff870fea2a901e 100644 (file)
 #    Enable smooth lighting with simple ambient occlusion.
 #    Disable for speed or for different looks.
 #smooth_lighting = true
-#    Path to texture directory. All textures are first searched from here.
+#    Adjust the gamma encoding for the light tables. Valid values are in the range
+#    1.1 to 3.0 (inclusive); lower numbers are brighter.  This setting is for the
+#    client only and is ignored by the server
+#display_gamma = 1.8
+# Path to texture directory. All textures are first searched from here.
 #texture_path =
 #    Video back-end.
 #    Possible values: null, software, burningsvideo, direct3d8, direct3d9, opengl.
index a5d364b73bb21a338c5ac00eee7587b78190c3a7..0e53ab678606b9ca51bc97ea3678bfd99dd92d25 100644 (file)
@@ -854,7 +854,6 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
                        ret = decode_light(n.getLightBlend(daylight_factor, ndef));
                } else {
                        ret = oldvalue;
-                       //ret = blend_light(255, 0, daylight_factor);
                }
        } else {
                /*float pre = (float)brightness_sum / (float)brightness_count;
index b660912f939708bed7a5f32d02696f687e91fb4e..f46260dab9904c6ba3f2ac09737cd8eb257ab07e 100644 (file)
@@ -108,6 +108,7 @@ void set_default_settings(Settings *settings)
        settings->setDefault("new_style_leaves", "true");
        settings->setDefault("connected_glass", "false");
        settings->setDefault("smooth_lighting", "true");
+       settings->setDefault("display_gamma", "1.8");
        settings->setDefault("texture_path", "");
        settings->setDefault("shader_path", "");
        settings->setDefault("video_driver", "opengl");
index 79dec17c6ad9a2fb59c97f2707d1d65bd9c3c87f..5d44a7db5a83e45d29409e3898873f069024a619 100644 (file)
@@ -1747,6 +1747,8 @@ void Game::run()
 
        std::vector<aabb3f> highlight_boxes;
 
+       set_light_table(g_settings->getFloat("display_gamma"));
+
        while (device->run() && !(*kill || g_gamecallback->shutdown_requested)) {
 
                /* Must be called immediately after a device->run() call because it
index 765c6303a97218ff27f31f2bf470bdb1c5f91710..08380a180e495d6edf284d3eb11ec4fdbbbedc76 100644 (file)
@@ -18,31 +18,93 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "light.h"
+#include <math.h>
+#include "util/numeric.h"
+
+#ifndef SERVER
 
-#if 1
-// Middle-raised variation of a_n+1 = a_n * 0.786
 // Length of LIGHT_MAX+1 means LIGHT_MAX is the last value.
 // LIGHT_SUN is read as LIGHT_MAX from here.
-u8 light_decode_table[LIGHT_MAX+1] = 
+
+u8 light_LUT[LIGHT_MAX+1] =
 {
-8,
-11+2,
-14+7,
-18+10,
-22+15,
-29+20,
-37+20,
-47+15,
-60+10,
-76+7,
-97+5,
-123+2,
-157,
-200,
-255,
+       /* Middle-raised variation of a_n+1 = a_n * 0.786
+        * Length of LIGHT_MAX+1 means LIGHT_MAX is the last value.
+        * LIGHT_SUN is read as LIGHT_MAX from here.
+        */
+       8,
+       11+2,
+       14+7,
+       18+10,
+       22+15,
+       29+20,
+       37+20,
+       47+15,
+       60+10,
+       76+7,
+       97+5,
+       123+2,
+       157,
+       200,
+       255,
 };
+
+const u8 *light_decode_table = light_LUT;
+
+/** Initialize or update the light value tables using the specified \p gamma.
+ *  If \p gamma == 1.0 then the light table is linear.  Typically values for
+ *  gamma range between 1.8 and 2.2.
+ *
+ *  @note The value for gamma will be restricted to the range 1.1 <= gamma <= 3.0.
+ *
+ *  @note This function is not, currently, a simple linear to gamma encoding
+ *        because adjustments are made so that a gamma of 1.8 gives the same
+ *        results as those hardcoded for use by the server.
+ */
+void set_light_table(float gamma)
+{
+       static const float brightness_step = 255.0f / (LIGHT_MAX + 1);
+
+       /* These are adjustment values that are added to the calculated light value
+        * after gamma is applied.  Currently they are used so that given a gamma
+        * of 1.8 the light values set by this function are the same as those
+        * hardcoded in the initalizer list for the declaration of light_LUT.
+        */
+       static const int adjustments[LIGHT_MAX + 1] = {
+                7,
+                7,
+                7,
+                5,
+                2,
+                0,
+               -7,
+               -20,
+               -31,
+               -39,
+               -43,
+               -45,
+               -40,
+               -25,
+               0
+       };
+
+       gamma = rangelim(gamma, 1.1, 3.0);
+
+       float brightness = brightness_step;
+
+       for (size_t i = 0; i < LIGHT_MAX; i++) {
+               light_LUT[i] = (u8)(255 * powf(brightness / 255.0f,  gamma));
+               light_LUT[i] = rangelim(light_LUT[i] + adjustments[i], 0, 255);
+               if (i > 1 && light_LUT[i] < light_LUT[i-1])
+                       light_LUT[i] = light_LUT[i-1] + 1;
+               brightness += brightness_step;
+       }
+       light_LUT[LIGHT_MAX] = 255;
+}
 #endif
 
+
+
 #if 0
 /*
 Made using this and:
index 769ca31ce11b4e8c993a60b40d9886353b2a12e0..f49be4518188cc78971c02ccb860dd862a285f99 100644 (file)
@@ -63,7 +63,21 @@ inline u8 undiminish_light(u8 light)
        return light + 1;
 }
 
-extern u8 light_decode_table[LIGHT_MAX+1];
+#ifndef SERVER
+
+/**
+ * \internal
+ *
+ * \warning DO NOT USE this directly; it is here simply so that decode_light()
+ * can be inlined.
+ *
+ * Array size is #LIGHTMAX+1
+ *
+ * The array is a lookup table to convert the internal representation of light
+ * (brightness) to the display brightness.
+ *
+ */
+extern const u8 *light_decode_table;
 
 // 0 <= light <= LIGHT_SUN
 // 0 <= return value <= 255
@@ -93,6 +107,10 @@ inline float decode_light_f(float light_f)
        return f * v2 + (1.0 - f) * v1;
 }
 
+void set_light_table(float gamma);
+
+#endif // ifndef SERVER
+
 // 0 <= daylight_factor <= 1000
 // 0 <= lightday, lightnight <= LIGHT_SUN
 // 0 <= return value <= LIGHT_SUN
@@ -105,15 +123,5 @@ 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 e67724ec1b8af8699cda2bbab3bec8779de5f051..da6e9bdeafadec505f74aec62021e86a67bcd903 100644 (file)
@@ -209,7 +209,7 @@ struct MapNode
        u8 getLightNoChecks(LightBank bank, const ContentFeatures *f);
 
        bool getLightBanks(u8 &lightday, u8 &lightnight, INodeDefManager *nodemgr) const;
-       
+
        // 0 <= daylight_factor <= 1000
        // 0 <= return value <= LIGHT_SUN
        u8 getLightBlend(u32 daylight_factor, INodeDefManager *nodemgr) const
@@ -220,16 +220,6 @@ 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;