light.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "light.h"
  17. #include <cmath>
  18. #include "util/numeric.h"
  19. #include "settings.h"
  20. #ifndef SERVER
  21. static u8 light_LUT[LIGHT_SUN + 1];
  22. // The const ref to light_LUT is what is actually used in the code
  23. const u8 *light_decode_table = light_LUT;
  24. struct LightingParams {
  25. float a, b, c; // polynomial coefficients
  26. float boost, center, sigma; // normal boost parameters
  27. float gamma;
  28. };
  29. static LightingParams params;
  30. float decode_light_f(float x)
  31. {
  32. if (x >= 1.0f) // x is equal to 1.0f half the time
  33. return 1.0f;
  34. x = std::fmax(x, 0.0f);
  35. float brightness = ((params.a * x + params.b) * x + params.c) * x;
  36. brightness += params.boost * std::exp(-0.5f * sqr((x - params.center) / params.sigma));
  37. if (brightness <= 0.0f) // may happen if parameters are insane
  38. return 0.0f;
  39. if (brightness >= 1.0f)
  40. return 1.0f;
  41. return powf(brightness, 1.0f / params.gamma);
  42. }
  43. // Initialize or update the light value tables using the specified gamma
  44. void set_light_table(float gamma)
  45. {
  46. // Lighting curve derivatives
  47. const float alpha = g_settings->getFloat("lighting_alpha");
  48. const float beta = g_settings->getFloat("lighting_beta");
  49. // Lighting curve coefficients
  50. params.a = alpha + beta - 2.0f;
  51. params.b = 3.0f - 2.0f * alpha - beta;
  52. params.c = alpha;
  53. // Mid boost
  54. params.boost = g_settings->getFloat("lighting_boost");
  55. params.center = g_settings->getFloat("lighting_boost_center");
  56. params.sigma = g_settings->getFloat("lighting_boost_spread");
  57. // Gamma correction
  58. params.gamma = rangelim(gamma, 0.5f, 3.0f);
  59. // Boundary values should be fixed
  60. light_LUT[0] = 0;
  61. light_LUT[LIGHT_SUN] = 255;
  62. for (size_t i = 1; i < LIGHT_SUN; i++) {
  63. float brightness = decode_light_f((float)i / LIGHT_SUN);
  64. // Strictly speaking, rangelim is not necessary here—if the implementation
  65. // is conforming. But we don’t want problems in any case.
  66. light_LUT[i] = rangelim((s32)(255.0f * brightness), 0, 255);
  67. // Ensure light brightens with each level
  68. if (i > 1 && light_LUT[i] <= light_LUT[i - 1])
  69. light_LUT[i] = light_LUT[i - 1] + 1;
  70. }
  71. }
  72. #endif