From a9a11159f4c1258ece4a94777cadca00e9bba9bc Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Fri, 30 Dec 2022 23:06:28 -0700 Subject: [PATCH] light: add _surface_minlight_scale light key for tweaking minlight given to faces matching surface light templates. minlight = _surface_minlight_scale * light lower default from 64 to 1 in q1 mode --- include/light/entities.hh | 1 + include/light/surflight.hh | 4 ++- light/entities.cc | 12 +++++++-- light/ltface.cc | 4 ++- light/surflight.cc | 6 ++--- testmaps/q1_surflight_minlight.map | 41 ++++++++++++++++++++++-------- tests/test_ltface.cc | 23 ++++++++++++++--- 7 files changed, 70 insertions(+), 21 deletions(-) diff --git a/include/light/entities.hh b/include/light/entities.hh index 65d022d0..6dd3c632 100644 --- a/include/light/entities.hh +++ b/include/light/entities.hh @@ -99,6 +99,7 @@ public: settings::setting_string suntexture; settings::setting_bool nostaticlight; settings::setting_int32 surflight_group; + settings::setting_scalar surface_minlight_scale; settings::setting_int32 light_channel_mask; settings::setting_int32 shadow_channel_mask; settings::setting_bool nonudge; diff --git a/include/light/surflight.hh b/include/light/surflight.hh index 4b0a8be4..a4d35a8c 100644 --- a/include/light/surflight.hh +++ b/include/light/surflight.hh @@ -49,8 +49,10 @@ struct surfacelight_t bool rescale; }; +class light_t; + void ResetSurflight(); std::vector &GetSurfaceLights(); -std::optional> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face); +std::optional> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face); const std::vector &SurfaceLightsForFaceNum(int facenum); void MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp); diff --git a/light/entities.cc b/light/entities.cc index d00ce06b..e90de54b 100644 --- a/light/entities.cc +++ b/light/entities.cc @@ -106,6 +106,7 @@ light_t::light_t() : suntexture{this, "suntexture", ""}, nostaticlight{this, "nostaticlight", false}, surflight_group{this, "surflight_group", 0}, + surface_minlight_scale{this, "surface_minlight_scale", 64}, light_channel_mask{this, "light_channel_mask", CHANNEL_MASK_DEFAULT}, shadow_channel_mask{this, "shadow_channel_mask", CHANNEL_MASK_DEFAULT}, nonudge{this, "nonudge", false} @@ -262,7 +263,7 @@ static void SetupSpotlights(const settings::worldspawn_keys &cfg) } } -static void CheckEntityFields(const settings::worldspawn_keys &cfg, light_t *entity) +static void CheckEntityFields(const mbsp_t *bsp, const settings::worldspawn_keys &cfg, light_t *entity) { if (entity->light.value() == 0.0f) entity->light.setValue(DEFAULTLIGHTLEVEL, settings::source::MAP); @@ -303,6 +304,13 @@ static void CheckEntityFields(const settings::worldspawn_keys &cfg, light_t *ent entity->shadow_channel_mask.setValue(entity->light_channel_mask.value(), settings::source::DEFAULT); } + + if (!entity->surface_minlight_scale.isChanged()) { + if (bsp->loadversion->game->id != GAME_QUAKE_II) { + // TODO: also use 1.0 for Q2? + entity->surface_minlight_scale.setValue(1.0, settings::source::DEFAULT); + } + } } /* @@ -987,7 +995,7 @@ void LoadEntities(const settings::worldspawn_keys &cfg, const mbsp_t *bsp) entity->projfov.value(), entity->projectionmatrix); } - CheckEntityFields(cfg, entity.get()); + CheckEntityFields(bsp, cfg, entity.get()); } } diff --git a/light/ltface.cc b/light/ltface.cc index 49c022d8..fcca12c1 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -3015,7 +3015,9 @@ void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings:: } if (auto value = IsSurfaceLitFace(bsp, face)) { - minlight = std::get<0>(value.value()) * 64.0f; + auto *entity = std::get<3>(value.value()); + const float surface_minlight_scale = entity ? entity->surface_minlight_scale.value() : 64.0f; + minlight = std::get<0>(value.value()) * surface_minlight_scale; minlight_color = std::get<2>(value.value()); LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps, std::get<1>(value.value())); } diff --git a/light/surflight.cc b/light/surflight.cc index efd52fe0..81bec9b3 100644 --- a/light/surflight.cc +++ b/light/surflight.cc @@ -147,20 +147,20 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys surfacelightsByFacenum[Face_GetNum(bsp, face)].push_back(index); } -std::optional> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face) +std::optional> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face) { if (bsp->loadversion->game->id == GAME_QUAKE_II) { // first, check if it's a Q2 surface const mtexinfo_t *info = Face_Texinfo(bsp, face); if (info != nullptr && (info->flags.native & Q2_SURF_LIGHT) && info->value > 0) { - return std::make_tuple(info->value, 0, qvec3d(Face_LookupTextureColor(bsp, face))); + return std::make_tuple(info->value, 0, qvec3d(Face_LookupTextureColor(bsp, face)), nullptr); } } for (const auto &surflight : GetSurfaceLightTemplates()) { if (FaceMatchesSurfaceLightTemplate(bsp, face, ModelInfoForFace(bsp, face - bsp->dfaces.data()), *surflight, SURFLIGHT_RAD)) { - return std::make_tuple(surflight->light.value(), surflight->style.value(), surflight->color.isChanged() ? surflight->color.value() : qvec3d(Face_LookupTextureColor(bsp, face))); + return std::make_tuple(surflight->light.value(), surflight->style.value(), surflight->color.isChanged() ? surflight->color.value() : qvec3d(Face_LookupTextureColor(bsp, face)), surflight.get()); } } diff --git a/testmaps/q1_surflight_minlight.map b/testmaps/q1_surflight_minlight.map index 1efa70d0..badc8650 100644 --- a/testmaps/q1_surflight_minlight.map +++ b/testmaps/q1_surflight_minlight.map @@ -68,24 +68,43 @@ ( -3072 -1360 -576 ) ( -3071 -1360 -576 ) ( -3072 -1360 -575 ) bolt3 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 ( -3072 -1360 -576 ) ( -3072 -1360 -575 ) ( -3072 -1359 -576 ) bolt3 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 } +// brush 7 +{ +( -3264 -1440 -528 ) ( -3264 -1472 -528 ) ( -3264 -1472 -592 ) *zwater1 [ 0 1 0 -32 ] [ 0 0 -1 -16 ] 0 1 1 +( -3264 -1472 -528 ) ( -3256 -1472 -528 ) ( -3256 -1472 -592 ) *zwater1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -3256 -1472 -592 ) ( -3256 -1440 -592 ) ( -3264 -1440 -592 ) *zwater1 [ 1 0 0 0 ] [ 0 -1 0 16 ] 0 1 1 +( -3264 -1440 -528 ) ( -3256 -1440 -528 ) ( -3256 -1472 -528 ) *zwater1 [ 1 0 0 0 ] [ 0 -1 0 16 ] 0 1 1 +( -3256 -1440 -592 ) ( -3256 -1440 -528 ) ( -3264 -1440 -528 ) *zwater1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -3256 -1472 -528 ) ( -3256 -1440 -528 ) ( -3256 -1440 -592 ) *zwater1 [ 0 1 0 -16 ] [ 0 0 -1 0 ] 0 1 1 +} } // entity 1 { -"classname" "light" -"origin" "-3112 -1776 -680" -"_surface" "light" -"light" "300" -"_color" "250 220 210" -"_surface_radiosity " "1" -"_nofill" "1" -} -// entity 2 -{ "classname" "info_player_start" "origin" "-3504 -1680 -568" } -// entity 3 +// entity 2 { "classname" "info_null" "origin" "-3376 -1640 -488" } +// entity 3 +{ +"classname" "light" +"origin" "-3112 -1776 -680" +"_surface" "light" +"light" "100" +"_color" "255 127.5 0" +"_surface_radiosity " "1" +"_nofill" "1" +} +// entity 4 +{ +"classname" "light" +"origin" "-3112 -1680 -680" +"_surface" "*zwater1" +"light" "100" +"_color" "255 127.5 0" +"_surface_radiosity " "1" +"_nofill" "1" +} diff --git a/tests/test_ltface.cc b/tests/test_ltface.cc index e27e90fd..84f9ae15 100644 --- a/tests/test_ltface.cc +++ b/tests/test_ltface.cc @@ -454,7 +454,24 @@ TEST_CASE("surface lights minlight" * doctest::may_fail()) { auto *surflight = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {-3264, -1664, -560}); REQUIRE(surflight); - CheckFaceLuxels(bsp, *surflight, [](qvec3b sample) { - CHECK(sample == qvec3b(255, 224, 214)); - }, &lit); + const auto l = [](qvec3b sample) { + // "light" key is 100, color is (1, 0.5, 0), but values get halved due to overbright + + CHECK(sample[0] <= 75); + CHECK(sample[0] >= 50); + + CHECK(sample[1] <= 35); + CHECK(sample[1] >= 25); + + CHECK(sample[2] == 0); + }; + + CheckFaceLuxels(bsp, *surflight, l, &lit); + + INFO("same but with liquid"); + + auto *liquid_face = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {-3264, -1456, -560}, {-1,0,0}); + REQUIRE(liquid_face); + + CheckFaceLuxels(bsp, *liquid_face, l, &lit); }