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
This commit is contained in:
Eric Wasylishen 2022-12-30 23:06:28 -07:00
parent 710e70d74b
commit a9a11159f4
7 changed files with 70 additions and 21 deletions

View File

@ -99,6 +99,7 @@ public:
settings::setting_string suntexture; settings::setting_string suntexture;
settings::setting_bool nostaticlight; settings::setting_bool nostaticlight;
settings::setting_int32 surflight_group; settings::setting_int32 surflight_group;
settings::setting_scalar surface_minlight_scale;
settings::setting_int32 light_channel_mask; settings::setting_int32 light_channel_mask;
settings::setting_int32 shadow_channel_mask; settings::setting_int32 shadow_channel_mask;
settings::setting_bool nonudge; settings::setting_bool nonudge;

View File

@ -49,8 +49,10 @@ struct surfacelight_t
bool rescale; bool rescale;
}; };
class light_t;
void ResetSurflight(); void ResetSurflight();
std::vector<surfacelight_t> &GetSurfaceLights(); std::vector<surfacelight_t> &GetSurfaceLights();
std::optional<std::tuple<int32_t, int32_t, qvec3d>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face); std::optional<std::tuple<int32_t, int32_t, qvec3d, light_t *>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face);
const std::vector<int> &SurfaceLightsForFaceNum(int facenum); const std::vector<int> &SurfaceLightsForFaceNum(int facenum);
void MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp); void MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp);

View File

@ -106,6 +106,7 @@ light_t::light_t() :
suntexture{this, "suntexture", ""}, suntexture{this, "suntexture", ""},
nostaticlight{this, "nostaticlight", false}, nostaticlight{this, "nostaticlight", false},
surflight_group{this, "surflight_group", 0}, surflight_group{this, "surflight_group", 0},
surface_minlight_scale{this, "surface_minlight_scale", 64},
light_channel_mask{this, "light_channel_mask", CHANNEL_MASK_DEFAULT}, light_channel_mask{this, "light_channel_mask", CHANNEL_MASK_DEFAULT},
shadow_channel_mask{this, "shadow_channel_mask", CHANNEL_MASK_DEFAULT}, shadow_channel_mask{this, "shadow_channel_mask", CHANNEL_MASK_DEFAULT},
nonudge{this, "nonudge", false} 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) if (entity->light.value() == 0.0f)
entity->light.setValue(DEFAULTLIGHTLEVEL, settings::source::MAP); 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(), entity->shadow_channel_mask.setValue(entity->light_channel_mask.value(),
settings::source::DEFAULT); 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); entity->projfov.value(), entity->projectionmatrix);
} }
CheckEntityFields(cfg, entity.get()); CheckEntityFields(bsp, cfg, entity.get());
} }
} }

View File

@ -3015,7 +3015,9 @@ void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::
} }
if (auto value = IsSurfaceLitFace(bsp, face)) { 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()); minlight_color = std::get<2>(value.value());
LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps, std::get<1>(value.value())); LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps, std::get<1>(value.value()));
} }

View File

@ -147,20 +147,20 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys
surfacelightsByFacenum[Face_GetNum(bsp, face)].push_back(index); surfacelightsByFacenum[Face_GetNum(bsp, face)].push_back(index);
} }
std::optional<std::tuple<int32_t, int32_t, qvec3d>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face) std::optional<std::tuple<int32_t, int32_t, qvec3d, light_t *>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face)
{ {
if (bsp->loadversion->game->id == GAME_QUAKE_II) { if (bsp->loadversion->game->id == GAME_QUAKE_II) {
// first, check if it's a Q2 surface // first, check if it's a Q2 surface
const mtexinfo_t *info = Face_Texinfo(bsp, face); const mtexinfo_t *info = Face_Texinfo(bsp, face);
if (info != nullptr && (info->flags.native & Q2_SURF_LIGHT) && info->value > 0) { 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()) { for (const auto &surflight : GetSurfaceLightTemplates()) {
if (FaceMatchesSurfaceLightTemplate(bsp, face, ModelInfoForFace(bsp, face - bsp->dfaces.data()), *surflight, SURFLIGHT_RAD)) { 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());
} }
} }

View File

@ -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 ) ( -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 ( -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 // 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" "classname" "info_player_start"
"origin" "-3504 -1680 -568" "origin" "-3504 -1680 -568"
} }
// entity 3 // entity 2
{ {
"classname" "info_null" "classname" "info_null"
"origin" "-3376 -1640 -488" "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"
}

View File

@ -454,7 +454,24 @@ TEST_CASE("surface lights minlight" * doctest::may_fail()) {
auto *surflight = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {-3264, -1664, -560}); auto *surflight = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {-3264, -1664, -560});
REQUIRE(surflight); REQUIRE(surflight);
CheckFaceLuxels(bsp, *surflight, [](qvec3b sample) { const auto l = [](qvec3b sample) {
CHECK(sample == qvec3b(255, 224, 214)); // "light" key is 100, color is (1, 0.5, 0), but values get halved due to overbright
}, &lit);
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);
} }