light: support _minlightMottle on worldspawn

This commit is contained in:
Eric Wasylishen 2022-12-06 00:55:15 -07:00
parent 82fff17ac4
commit eae434736a
5 changed files with 111 additions and 9 deletions

View File

@ -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;

View File

@ -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},

View File

@ -624,8 +624,7 @@ static std::unique_ptr<lightsurf_t> 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_t> 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

View File

@ -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"
}

View File

@ -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 <class L>
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));
});
}