diff --git a/include/light/light.hh b/include/light/light.hh index a86df742..a79ac8c5 100644 --- a/include/light/light.hh +++ b/include/light/light.hh @@ -115,7 +115,7 @@ struct lightsurf_t /* these take precedence the values in modelinfo */ vec_t minlight; qvec3d minlight_color; - bool nodirt; + bool nodirt, minlightMottle; qplane3d plane; qvec3d snormal; @@ -219,6 +219,7 @@ public: qvec3d offset{}; settings::setting_scalar minlight{this, "minlight", 0}; + settings::setting_bool minlightMottle{this, "minlightMottle", false}; settings::setting_scalar shadow{this, "shadow", 0}; settings::setting_scalar shadowself{this, {"shadowself", "selfshadow"}, 0}; settings::setting_scalar shadowworldonly{this, "shadowworldonly", 0}; diff --git a/light/light.cc b/light/light.cc index e18c0124..5d93cc17 100644 --- a/light/light.cc +++ b/light/light.cc @@ -900,6 +900,12 @@ int light_main(int argc, const char **argv) if ((bspdata.loadversion->game->id == GAME_QUAKE_II) && !options.rangescale.isChanged()) { options.rangescale.setValue(1.0f); } + if ((bspdata.loadversion->game->id == GAME_QUAKE_II) && !options.bouncecolorscale.isChanged()) { + options.bouncecolorscale.setValue(1.0f); + } + if ((bspdata.loadversion->game->id == GAME_QUAKE_II) && !options.bouncescale.isChanged()) { + options.bouncescale.setValue(2.0f); + } img::init_palette(bspdata.loadversion->game); img::load_textures(&bsp); diff --git a/light/ltface.cc b/light/ltface.cc index 2a19f571..0dbe4ef0 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -711,9 +711,20 @@ static bool Lightsurf_Init( lightsurf->nodirt = extended_flags.no_dirt; } + lightsurf->minlightMottle = modelinfo->minlightMottle.value(); + // minlight if (modelinfo->minlight.isChanged()) { lightsurf->minlight = modelinfo->minlight.value(); + + // 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; + } + } } else { lightsurf->minlight = extended_flags.minlight; } @@ -1592,6 +1603,9 @@ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d & if (cfg.addminlight.value()) { sample->color += color * (value / 255.0); } else { + if (lightsurf->minlightMottle) { + value += rand() % 48; + } Light_ClampMin(sample, value, color); } @@ -3227,6 +3241,9 @@ void LightFace(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const setti LightFace_Bounce(bsp, face, lightsurf, lightmaps); } + if (cfg.minlight.value()) + __debugbreak(); + /* minlight - Use Q2 surface light, or the greater of global or model minlight. */ const gtexinfo_t *texinfo = Face_Texinfo(bsp, face); // mxd. Surface lights... if (texinfo != nullptr && texinfo->value > 0 && (texinfo->flags.native & Q2_SURF_LIGHT)) { diff --git a/qbsp/csg4.cc b/qbsp/csg4.cc index b1da5002..4323908d 100644 --- a/qbsp/csg4.cc +++ b/qbsp/csg4.cc @@ -52,7 +52,7 @@ std::mutex csgfaces_lock; MakeSkipTexinfo ================== */ -static int MakeSkipTexinfo() +int MakeSkipTexinfo() { // FindMiptex, FindTexinfo not threadsafe std::unique_lock lck{csgfaces_lock}; diff --git a/qbsp/map.cc b/qbsp/map.cc index 5cb61160..0f10a32e 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -1785,6 +1785,8 @@ void ProcessExternalMapEntity(mapentity_t *entity) SetKeyValue(entity, "origin", "0 0 0"); } +int MakeSkipTexinfo(); + void ProcessAreaPortal(mapentity_t *entity) { Q_assert(!options.onlyents.value()); @@ -1805,6 +1807,7 @@ void ProcessAreaPortal(mapentity_t *entity) for (size_t f = map.brushes[i].firstface; f < map.brushes[i].firstface + map.brushes[i].numfaces; f++) { map.faces[f].contents.native = Q2_CONTENTS_AREAPORTAL; + map.faces[f].texinfo = MakeSkipTexinfo(); } } entity->areaportalnum = ++map.numareaportals; diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index 2d661c3c..012351ca 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -614,7 +614,7 @@ static void EmitAreaPortals(node_t *headnode) if (!e.areaportalnum) continue; - dareaportal_t &dp = map.bsp.dareaportals.emplace_back(); + dareaportal_t dp = {}; if (e.portalareas[0] == i) { dp.portalnum = e.areaportalnum; @@ -623,6 +623,17 @@ static void EmitAreaPortals(node_t *headnode) dp.portalnum = e.areaportalnum; dp.otherarea = e.portalareas[0]; } + + size_t j = 0; + + for (; j < map.bsp.dareaportals.size(); j++) + { + if (map.bsp.dareaportals[j] == dp) + break; + } + + if (j == map.bsp.dareaportals.size()) + map.bsp.dareaportals.push_back(dp); } area.numareaportals = map.bsp.dareaportals.size() - area.firstareaportal;