From eae434736a3fa7582d7b85327760a891f191b1af Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Tue, 6 Dec 2022 00:55:15 -0700 Subject: [PATCH] light: support _minlightMottle on worldspawn --- include/light/light.hh | 1 + light/light.cc | 1 + light/ltface.cc | 21 +++++++--- testmaps/q2_minlight_nomottle.map | 70 +++++++++++++++++++++++++++++++ tests/test_ltface.cc | 27 ++++++++++-- 5 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 testmaps/q2_minlight_nomottle.map diff --git a/include/light/light.hh b/include/light/light.hh index 2e098baf..8238355e 100644 --- a/include/light/light.hh +++ b/include/light/light.hh @@ -258,6 +258,7 @@ public: setting_scalar global_anglescale; setting_scalar lightmapgamma; setting_bool addminlight; + setting_scalar minlightMottle; setting_scalar minlight; setting_scalar maxlight; setting_color minlight_color; diff --git a/light/light.cc b/light/light.cc index d16f0f75..118fe3ff 100644 --- a/light/light.cc +++ b/light/light.cc @@ -152,6 +152,7 @@ worldspawn_keys::worldspawn_keys() : addminlight{this, "addmin", false, &worldspawn_group}, minlight{this, {"light", "minlight"}, 0, &worldspawn_group}, maxlight{this, "maxlight", 0, &worldspawn_group}, + minlightMottle{this, "minlightMottle", false}, minlight_color{this, {"minlight_color", "mincolor"}, 255.0, 255.0, 255.0, &worldspawn_group}, spotlightautofalloff{this, "spotlightautofalloff", false, &worldspawn_group}, compilerstyle_start{this, "compilerstyle_start", 32, &worldspawn_group}, diff --git a/light/ltface.cc b/light/ltface.cc index 91aa5734..980f74a9 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -624,8 +624,7 @@ static std::unique_ptr Lightsurf_Init(const modelinfo_t *modelinfo, lightsurf->nodirt = extended_flags.no_dirt; } - lightsurf->minlightMottle = modelinfo->minlightMottle.value(); - + // minlight if (modelinfo->minlight.isChanged()) { lightsurf->minlight = modelinfo->minlight.value(); @@ -633,13 +632,23 @@ static std::unique_ptr Lightsurf_Init(const modelinfo_t *modelinfo, lightsurf->minlight = extended_flags.minlight; } + // minlightMottle + if (modelinfo->minlightMottle.isChanged()) { + lightsurf->minlightMottle = modelinfo->minlightMottle.value(); + } else if (light_options.minlightMottle.isChanged()) { + lightsurf->minlightMottle = light_options.minlightMottle.value(); + } else { + // default value depends on game + if (bsp->loadversion->game->id == GAME_QUAKE_II) { + lightsurf->minlightMottle = true; + } else { + lightsurf->minlightMottle = false; + } + } + // Q2 uses a 0-1 range for minlight if (bsp->loadversion->game->id == GAME_QUAKE_II) { lightsurf->minlight *= 128.f; - - if (!modelinfo->minlightMottle.isChanged()) { - lightsurf->minlightMottle = true; - } } // maxlight diff --git a/testmaps/q2_minlight_nomottle.map b/testmaps/q2_minlight_nomottle.map new file mode 100644 index 00000000..d028c4cf --- /dev/null +++ b/testmaps/q2_minlight_nomottle.map @@ -0,0 +1,70 @@ +// Game: Quake 2 +// Format: Quake2 +// entity 0 +{ +"classname" "worldspawn" +"_tb_textures" "textures/e1u1" +"_minlight" "0.26" +"_minlightMottle" "0" +"_bounce" "0" +// brush 0 +{ +( -160 -256 16 ) ( -160 -255 16 ) ( -160 -256 17 ) e1u1/floor1_1 0 0 0 1 1 +( 80 -384 16 ) ( 80 -384 17 ) ( 81 -384 16 ) e1u1/floor1_1 0 0 0 1 1 +( 80 -256 16 ) ( 81 -256 16 ) ( 80 -255 16 ) e1u1/floor1_1 0 0 0 1 1 +( 496 -32 32 ) ( 496 -31 32 ) ( 497 -32 32 ) e1u1/floor1_1 0 0 0 1 1 +( 496 368 32 ) ( 497 368 32 ) ( 496 368 33 ) e1u1/floor1_1 0 0 0 1 1 +( 496 -32 32 ) ( 496 -32 33 ) ( 496 -31 32 ) e1u1/floor1_1 0 0 0 1 1 +} +// brush 1 +{ +( -160 -384 32 ) ( -160 -383 32 ) ( -160 -384 33 ) e1u1/floor1_1 0 0 0 1 1 +( -160 -384 32 ) ( -160 -384 33 ) ( -159 -384 32 ) e1u1/floor1_1 0 0 0 1 1 +( -160 -384 32 ) ( -159 -384 32 ) ( -160 -383 32 ) e1u1/floor1_1 0 0 0 1 1 +( 256 -320 288 ) ( 256 -319 288 ) ( 257 -320 288 ) e1u1/floor1_1 0 0 0 1 1 +( 256 -320 48 ) ( 257 -320 48 ) ( 256 -320 49 ) e1u1/floor1_1 0 0 0 1 1 +( 496 -320 48 ) ( 496 -320 49 ) ( 496 -319 48 ) e1u1/floor1_1 0 0 0 1 1 +} +// brush 2 +{ +( -160 304 32 ) ( -160 305 32 ) ( -160 304 33 ) e1u1/floor1_1 0 0 0 1 1 +( -160 304 32 ) ( -160 304 33 ) ( -159 304 32 ) e1u1/floor1_1 0 0 0 1 1 +( -160 304 32 ) ( -159 304 32 ) ( -160 305 32 ) e1u1/floor1_1 0 0 0 1 1 +( 256 368 288 ) ( 256 369 288 ) ( 257 368 288 ) e1u1/floor1_1 0 0 0 1 1 +( 256 368 48 ) ( 257 368 48 ) ( 256 368 49 ) e1u1/floor1_1 0 0 0 1 1 +( 496 368 48 ) ( 496 368 49 ) ( 496 369 48 ) e1u1/floor1_1 0 0 0 1 1 +} +// brush 3 +{ +( 496 240 32 ) ( 496 241 32 ) ( 496 240 33 ) e1u1/floor1_1 0 0 0 1 1 +( -128 -320 32 ) ( -128 -320 33 ) ( -127 -320 32 ) e1u1/floor1_1 0 0 0 1 1 +( -128 240 32 ) ( -127 240 32 ) ( -128 241 32 ) e1u1/floor1_1 0 0 0 1 1 +( 288 304 288 ) ( 288 305 288 ) ( 289 304 288 ) e1u1/floor1_1 0 0 0 1 1 +( 288 304 48 ) ( 289 304 48 ) ( 288 304 49 ) e1u1/floor1_1 0 0 0 1 1 +( 528 304 48 ) ( 528 304 49 ) ( 528 305 48 ) e1u1/floor1_1 0 0 0 1 1 +} +// brush 4 +{ +( -160 240 32 ) ( -160 241 32 ) ( -160 240 33 ) e1u1/floor1_1 0 0 0 1 1 +( -784 -320 32 ) ( -784 -320 33 ) ( -783 -320 32 ) e1u1/floor1_1 0 0 0 1 1 +( -784 240 32 ) ( -783 240 32 ) ( -784 241 32 ) e1u1/floor1_1 0 0 0 1 1 +( -368 304 288 ) ( -368 305 288 ) ( -367 304 288 ) e1u1/floor1_1 0 0 0 1 1 +( -368 304 48 ) ( -367 304 48 ) ( -368 304 49 ) e1u1/floor1_1 0 0 0 1 1 +( -128 304 48 ) ( -128 304 49 ) ( -128 305 48 ) e1u1/floor1_1 0 0 0 1 1 +} +// brush 5 +{ +( -160 -256 288 ) ( -160 -255 288 ) ( -160 -256 289 ) e1u1/floor1_1 0 0 0 1 1 +( 80 -320 288 ) ( 80 -320 289 ) ( 81 -320 288 ) e1u1/floor1_1 0 0 0 1 1 +( 80 -256 288 ) ( 81 -256 288 ) ( 80 -255 288 ) e1u1/floor1_1 0 0 0 1 1 +( 496 -32 304 ) ( 496 -31 304 ) ( 497 -32 304 ) e1u1/floor1_1 0 0 0 1 1 +( 496 304 304 ) ( 497 304 304 ) ( 496 304 305 ) e1u1/floor1_1 0 0 0 1 1 +( 496 -32 304 ) ( 496 -32 305 ) ( 496 -31 304 ) e1u1/floor1_1 0 0 0 1 1 +} +} +// entity 1 +{ +"classname" "info_player_start" +"origin" "288 144 56" +"angle" "270" +} diff --git a/tests/test_ltface.cc b/tests/test_ltface.cc index b6b043c4..32daaac1 100644 --- a/tests/test_ltface.cc +++ b/tests/test_ltface.cc @@ -153,19 +153,27 @@ TEST_CASE("-novanilla + -world_units_per_luxel") CHECK(bsp.dlightdata.size() == expected_dlightdata_bytes); } -static void CheckFaceLuxelsNonBlack(const mbsp_t &bsp, const mface_t &face) +template +static void CheckFaceLuxels(const mbsp_t &bsp, const mface_t &face, L&& lambda) { const faceextents_t extents(face, bsp, LMSCALE_DEFAULT); for (int x = 0; x < extents.width(); ++x) { for (int y = 0; y < extents.height(); ++y) { - auto sample = LM_Sample(&bsp, extents, face.lightofs, {x, y}); + const qvec3b sample = LM_Sample(&bsp, extents, face.lightofs, {x, y}); INFO("sample ", x, ", ", y); - CHECK(sample[0] > 0); + lambda(sample); } } } +static void CheckFaceLuxelsNonBlack(const mbsp_t &bsp, const mface_t &face) +{ + CheckFaceLuxels(bsp, face, [](qvec3b sample){ + CHECK(sample[0] > 0); + }); +} + TEST_CASE("emissive lights") { auto [bsp, bspx] = LoadTestmap("q2_light_flush.map", {}); REQUIRE(bspx.empty()); @@ -188,3 +196,16 @@ TEST_CASE("emissive lights") { TEST_CASE("q2_phong_doesnt_cross_contents") { auto [bsp, bspx] = LoadTestmap("q2_phong_doesnt_cross_contents.map", {"-wrnormals"}); } + +TEST_CASE("q2_minlight_nomottle") { + INFO("_minlightMottle 0 works on worldspawn"); + + auto [bsp, bspx] = LoadTestmap("q2_minlight_nomottle.map", {}); + + auto *face = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {276, 84, 32}); + REQUIRE(face); + + CheckFaceLuxels(bsp, *face, [](qvec3b sample){ + CHECK(sample == qvec3b(33, 33, 33)); + }); +}