diff --git a/include/light/bounce.hh b/include/light/bounce.hh index 23fe7b85..aecf8bd3 100644 --- a/include/light/bounce.hh +++ b/include/light/bounce.hh @@ -27,6 +27,7 @@ #include #include +#include struct bouncelight_t { @@ -47,7 +48,7 @@ struct bouncelight_t // public functions -const std::vector &BounceLights(); -const std::vector &BounceLightsForFaceNum(int facenum); +const std::forward_list &BounceLights(); +const std::vector> &BounceLightsForFaceNum(int facenum); void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp); qvec3b Face_LookupTextureColor(const mbsp_t *bsp, const mface_t *face); // mxd diff --git a/include/light/surflight.hh b/include/light/surflight.hh index 2646ef66..dbd42453 100644 --- a/include/light/surflight.hh +++ b/include/light/surflight.hh @@ -21,6 +21,7 @@ See file, 'COPYING', for details. #pragma once #include +#include struct surfacelight_t { @@ -46,6 +47,6 @@ struct surfacelight_t }; 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/bounce.cc b/light/bounce.cc index c5942416..5723da28 100644 --- a/light/bounce.cc +++ b/light/bounce.cc @@ -47,8 +47,9 @@ using namespace std; using namespace polylib; mutex bouncelights_lock; -static std::vector bouncelights; -std::unordered_map> bouncelightsByFacenum; +static std::forward_list bouncelights; +static size_t lastBounceLightIndex; +static std::unordered_map>> bouncelightsByFacenum; static bool Face_ShouldBounce(const mbsp_t *bsp, const mface_t *face) { @@ -94,15 +95,14 @@ qvec3b Face_LookupTextureColor(const mbsp_t *bsp, const mface_t *face) inline bouncelight_t &CreateBounceLight(const mface_t *face, const mbsp_t *bsp) { unique_lock lck{bouncelights_lock}; - bouncelight_t &l = bouncelights.emplace_back(); + bouncelight_t &l = bouncelights.emplace_front(); - const int lastBounceLightIndex = static_cast(bouncelights.size()) - 1; - bouncelightsByFacenum[Face_GetNum(bsp, face)].push_back(lastBounceLightIndex); + bouncelightsByFacenum[Face_GetNum(bsp, face)].push_back(l); return l; } -static void AddBounceLight(const qvec3d &pos, const std::unordered_map &colorByStyle, +static void AddBounceLight(const qvec3d &pos, std::unordered_map &&colorByStyle, const qvec3d &surfnormal, vec_t area, const mface_t *face, const mbsp_t *bsp) { for (const auto &styleColor : colorByStyle) { @@ -118,15 +118,11 @@ static void AddBounceLight(const qvec3d &pos, const std::unordered_map componentwiseMaxColor[i]) { - componentwiseMaxColor[i] = styleColor.second[i]; - } + l.componentwiseMaxColor[i] = max(l.componentwiseMaxColor[i], styleColor.second[i]); } } - l.componentwiseMaxColor = componentwiseMaxColor; l.surfnormal = surfnormal; l.area = area; @@ -137,19 +133,19 @@ static void AddBounceLight(const qvec3d &pos, const std::unordered_map &BounceLights() +const std::forward_list &BounceLights() { return bouncelights; } -const std::vector &BounceLightsForFaceNum(int facenum) +const std::vector> &BounceLightsForFaceNum(int facenum) { const auto &vec = bouncelightsByFacenum.find(facenum); if (vec != bouncelightsByFacenum.end()) { return vec->second; } - static std::vector empty; + static std::vector> empty; return empty; } @@ -215,7 +211,7 @@ static void MakeBounceLightsThread(const settings::worldspawn_keys &cfg, const m emitcolors[styleColor.first] = styleColor.second * blendedcolor; } - AddBounceLight(facemidpoint, emitcolors, faceplane.normal, area, &face, bsp); + AddBounceLight(facemidpoint, std::move(emitcolors), faceplane.normal, area, &face, bsp); } void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp) @@ -224,5 +220,5 @@ void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp) logging::parallel_for_each(bsp->dfaces, [&](const mface_t &face) { MakeBounceLightsThread(cfg, bsp, face); }); - logging::print("{} bounce lights created\n", bouncelights.size()); + logging::print("{} bounce lights created\n", lastBounceLightIndex); } diff --git a/light/ltface.cc b/light/ltface.cc index bde5bae9..6c547464 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -1389,7 +1389,7 @@ static void LightFace_Sky(const sun_t *sun, lightsurf_t *lightsurf, lightmapdict * ============ */ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d &color, vec_t light, - lightsurf_t *lightsurf, lightmapdict_t *lightmaps) + lightsurf_t *lightsurf, lightmapdict_t *lightmaps, int32_t style) { const settings::worldspawn_keys &cfg = *lightsurf->cfg; const modelinfo_t *modelinfo = lightsurf->modelinfo; @@ -1399,8 +1399,8 @@ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d & return; /* this face is excluded from minlight */ } - /* Find a style 0 lightmap */ - lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, 0, lightsurf); + /* Find the lightmap */ + lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, style, lightsurf); bool hit = false; for (int i = 0; i < lightsurf->points.size(); i++) { @@ -1423,7 +1423,19 @@ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d & } if (hit) { - Lightmap_Save(lightmaps, lightsurf, lightmap, 0); + Lightmap_Save(lightmaps, lightsurf, lightmap, style); + } +} + +static void LightFace_LocalMin(const mbsp_t *bsp, const mface_t *face, + lightsurf_t *lightsurf, lightmapdict_t *lightmaps) +{ + const settings::worldspawn_keys &cfg = *lightsurf->cfg; + const modelinfo_t *modelinfo = lightsurf->modelinfo; + + const surfflags_t &extended_flags = extended_texinfo_flags[face->texinfo]; + if (extended_flags.no_minlight) { + return; /* this face is excluded from minlight */ } // FIXME: Refactor this? @@ -1446,9 +1458,9 @@ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d & raystream_occlusion_t &rs = lightsurf->occlusion_stream; rs.clearPushedRays(); - lightmap = Lightmap_ForStyle(lightmaps, entity->style.value(), lightsurf); + lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, entity->style.value(), lightsurf); - hit = false; + bool hit = false; for (int i = 0; i < lightsurf->points.size(); i++) { if (lightsurf->occluded[i]) continue; @@ -1547,16 +1559,15 @@ static void LightFace_BounceLightsDebug(const lightsurf_t *lightsurf, lightmapdi // reset all lightmaps to black (lazily) Lightmap_ClearAll(lightmaps); - const std::vector &vpls = BounceLightsForFaceNum(Face_GetNum(lightsurf->bsp, lightsurf->face)); - const std::vector &all_vpls = BounceLights(); + const std::vector> &vpls = BounceLightsForFaceNum(Face_GetNum(lightsurf->bsp, lightsurf->face)); /* Overwrite each point with the emitted color... */ for (int i = 0; i < lightsurf->points.size(); i++) { if (lightsurf->occluded[i]) continue; - for (const auto &vplnum : vpls) { - const bouncelight_t &vpl = all_vpls[vplnum]; + for (const auto &vpl_ref : vpls) { + auto &vpl = vpl_ref.get(); // check for point in polygon (note: could be on the edge of more than one) if (!GLM_EdgePlanes_PointInside(vpl.poly_edgeplanes, lightsurf->points[i])) @@ -2966,7 +2977,7 @@ void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings:: float minlight = 0; qvec3d minlight_color; - /* minlight - use the greater of global or model minlight, or Q2 surface emission */ + // first, check for global minlight; this only affects style 0 if (lightsurf.minlight > cfg.minlight.value()) { minlight = lightsurf.minlight; minlight_color = lightsurf.minlight_color; @@ -2975,17 +2986,18 @@ void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings:: minlight_color = cfg.minlight_color.value(); } - if (!minlight) { - if (auto value = IsSurfaceLitFace(bsp, face)) { - minlight = *value * 64.0f; - minlight_color = Face_LookupTextureColor(bsp, face); - } + if (minlight) { + LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps, 0); } - if (minlight) { - LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps); + if (auto value = IsSurfaceLitFace(bsp, face)) { + minlight = std::get<0>(value.value()) * 64.0f; + minlight_color = Face_LookupTextureColor(bsp, face); + LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps, std::get<1>(value.value())); } + LightFace_LocalMin(bsp, face, &lightsurf, lightmaps); + /* negative lights */ if (!(modelinfo->lightignore.value() || extended_flags.light_ignore)) { for (const auto &entity : GetLights()) { diff --git a/light/surflight.cc b/light/surflight.cc index 5715e9a2..732457e4 100644 --- a/light/surflight.cc +++ b/light/surflight.cc @@ -141,20 +141,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 info->value; + return std::make_tuple(info->value, 0); } } for (const auto &surflight : GetSurfaceLightTemplates()) { if (FaceMatchesSurfaceLightTemplate(bsp, face, *surflight, SURFLIGHT_RAD)) { - return surflight->light.value(); + return std::make_tuple(surflight->light.value(), surflight->style.value()); } } diff --git a/qbsp/portals.cc b/qbsp/portals.cc index fa79dd41..aa7d10ee 100644 --- a/qbsp/portals.cc +++ b/qbsp/portals.cc @@ -435,7 +435,10 @@ void MakeTreePortals(tree_t *tree) portalstats_t stats{}; MakeHeadnodePortals(tree); + MakeTreePortals_r(tree, tree->headnode.get(), stats); + + logging::print(logging::flag::STAT, " {:8} tiny portals\n", stats.c_tinyportals); } static void AssertNoPortals_r(node_t *node)