diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2026-03-26 20:46:58 +0000 |
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2026-03-26 20:46:58 +0000 |
| commit | 947319e25e49027d77543ae5c6f6c01d451a8926 (patch) | |
| tree | 4e941967521d0b96e3c2ad32eb1545ecb6ed32f7 | |
| parent | Fix warnings in Environment:getSunPos (diff) | |
| download | ilt-947319e25e49027d77543ae5c6f6c01d451a8926.tar.bz2 ilt-947319e25e49027d77543ae5c6f6c01d451a8926.tar.xz ilt-947319e25e49027d77543ae5c6f6c01d451a8926.zip | |
Improve light approximations in LightDirection
Twilight replaces astronomical twilight to give a longer fade. Astronomical
twilight is only the darkest part of twilight, which we had skipped right to.
Fixes directional light amount to only be affected by the sun's passing
below th horizon, not it's whole height above it.
Adds a rough approximation of the amount of atmosphere scattering of
directional light (I made this calculation up)
| -rw-r--r-- | gfx/lightDirection.cpp | 19 | ||||
| -rw-r--r-- | gfx/lightDirection.h | 7 | ||||
| -rw-r--r-- | test/test-environment.cpp | 53 |
3 files changed, 65 insertions, 14 deletions
diff --git a/gfx/lightDirection.cpp b/gfx/lightDirection.cpp index 3932872..5198bdf 100644 --- a/gfx/lightDirection.cpp +++ b/gfx/lightDirection.cpp @@ -1,12 +1,25 @@ #include "lightDirection.h" #include "maths.h" -constexpr auto ASTRONOMICAL_TWILIGHT = 18.0_degrees; +constexpr auto TWILIGHT_START = .0_degrees; +constexpr auto TWILIGHT_END = -18.0_degrees; +constexpr auto TWILIGHT_RANGE = TWILIGHT_START - TWILIGHT_END; + constexpr auto SUN_ANGLUAR_SIZE = 0.5_degrees; +constexpr auto SUN_ANGLUAR_RADIUS = SUN_ANGLUAR_SIZE / 2; +constexpr auto SUN_ELEVATION_REFRACTION_OFFSET = 0.5_degrees; +constexpr auto SUN_ANGLUAR_OFFSET = SUN_ANGLUAR_RADIUS + SUN_ELEVATION_REFRACTION_OFFSET; + +constexpr auto ATMOSPHERE_SCATTER_MIN = .4F; +constexpr auto ATMOSPHERE_SCATTER_MAX = .7F; +constexpr auto ATMOSPHERE_SCATTER_RANGE = ATMOSPHERE_SCATTER_MAX - ATMOSPHERE_SCATTER_MIN; + +constexpr auto NORM = 0.5F; LightDirection::LightDirection(const Direction2D sunPos) : pos {sunPos}, vec {glm::mat3 {rotate_yp(pi + sunPos.x, -sunPos.y)} * north}, - amb {glm::clamp(sunPos.y + ASTRONOMICAL_TWILIGHT, 0.F, 1.F)}, - dir {glm::clamp(sunPos.y + SUN_ANGLUAR_SIZE, 0.F, 1.F)} + amb {glm::clamp((sunPos.y - TWILIGHT_END) / TWILIGHT_RANGE, 0.F, 1.F)}, + dir {(-std::cos(std::clamp((sunPos.y + SUN_ANGLUAR_OFFSET) / SUN_ANGLUAR_SIZE, 0.F, 1.F) * pi) * NORM) + NORM}, + atmosScatter {((half_pi - sunPos.y) / half_pi * ATMOSPHERE_SCATTER_RANGE) + ATMOSPHERE_SCATTER_MIN} { } diff --git a/gfx/lightDirection.h b/gfx/lightDirection.h index 789830b..296f497 100644 --- a/gfx/lightDirection.h +++ b/gfx/lightDirection.h @@ -31,9 +31,16 @@ public: return dir; } + [[nodiscard]] float + atmosphericScattering() const noexcept + { + return atmosScatter; + } + private: Direction2D pos; Direction3D vec; float amb; float dir; + float atmosScatter; }; diff --git a/test/test-environment.cpp b/test/test-environment.cpp index a249192..4fb5d13 100644 --- a/test/test-environment.cpp +++ b/test/test-environment.cpp @@ -12,7 +12,8 @@ namespace { using SunPosTestData = std::tuple<Direction2D, time_t, Direction2D>; - using SunDirTestData = std::tuple<Direction2D, Direction3D, float, float>; + using SunDirTestData = std::tuple<Direction2D, Direction3D>; + using SunAmtTestData = std::tuple<float, float>; constexpr Direction2D DONCASTER = {-1.1, 53.5}; constexpr Direction2D NEW_YORK = {74.0, 40.7}; constexpr Direction2D SYNDEY = {-151.2, -33.9}; @@ -41,24 +42,54 @@ BOOST_DATA_TEST_CASE(SunPosition, BOOST_DATA_TEST_CASE(SunDirection, boost::unit_test::data::make<SunDirTestData>({ - {{0.F, 0.F}, south, 0.314F, 0.0087F}, - {{90.F, 0.F}, west, 0.314F, 0.0087F}, - {{-90.F, 0.F}, east, 0.314F, 0.0087F}, + {{0.F, 0.F}, south}, + {{90.F, 0.F}, west}, + {{-90.F, 0.F}, east}, // From above // EqGM midnight, sun below horizon, shining upwards - {{181.52F, -66.86F}, {-0.01F, 0.39F, 0.919F}, 0, 0.F}, + {{181.52F, -66.86F}, {-0.01F, 0.39F, 0.919F}}, // EqGM just before sunrise, mostly west, north a bit, up a bit - {{113.12F, -0.85F}, {-0.92F, 0.39F, 0.015F}, 0.299F, 0.F}, + {{113.12F, -0.85F}, {-0.92F, 0.39F, 0.015F}}, // EqGM just after sunrise, mostly west, north a bit, down a bit - {{113.12F, 6.05F}, {-0.92F, 0.39F, -0.015F}, 0.42F, 0.114F}, + {{113.12F, 6.05F}, {-0.92F, 0.39F, -0.015F}}, // Doncaster noon, roughly from south to north, high in the sky, downward - {{176.34F, 59.64F}, {-0.03F, 0.5F, -0.86F}, 1, 1}, + {{176.34F, 59.64F}, {-0.03F, 0.5F, -0.86F}}, }), - position, direction, amb, dir) + position, direction) { const LightDirection lightDir {position * degreesToRads}; BOOST_CHECK_CLOSE_VEC(lightDir.vector(), direction); BOOST_CHECK_CLOSE(glm::length(lightDir.vector()), 1.F, 1); - BOOST_CHECK_CLOSE(lightDir.ambient(), amb, 5); - BOOST_CHECK_CLOSE(lightDir.directional(), dir, 5); +} + +BOOST_DATA_TEST_CASE(SunDirectionalAmount, + boost::unit_test::data::make<SunAmtTestData>({ + {5._degrees, 1.F}, + {1._degrees, 1.F}, + {0._degrees, 1.F}, + {-0.25_degrees, 1.F}, + {-0.5_degrees, 0.5F}, + {-0.75_degrees, 0.F}, + {-1._degrees, 0.F}, + {-5._degrees, 0.F}, + }), + elevation, amount) +{ + const LightDirection lightDir {{0, elevation}}; + BOOST_CHECK_CLOSE(lightDir.directional(), amount, 1.F); +} + +BOOST_DATA_TEST_CASE(SunAmbientAmount, + boost::unit_test::data::make<SunAmtTestData>({ + {20._degrees, 1.F}, + {1._degrees, 1.F}, + {-9._degrees, 0.5F}, + {-18._degrees, 0.F}, + {-25._degrees, 0.F}, + {-50._degrees, 0.F}, + }), + elevation, amount) +{ + const LightDirection lightDir {{0, elevation}}; + BOOST_CHECK_CLOSE(lightDir.ambient(), amount, 1.F); } |
