fix crash in light from bounce lighting storage

move bounce lights to a forwardly linked list
fix minlight affecting style 0 for switchables
This commit is contained in:
Jonathan 2022-07-29 00:41:24 -04:00
parent 7810875860
commit 3ee28fc416
6 changed files with 54 additions and 41 deletions

View File

@ -27,6 +27,7 @@
#include <map>
#include <common/qvec.hh>
#include <forward_list>
struct bouncelight_t
{
@ -47,7 +48,7 @@ struct bouncelight_t
// public functions
const std::vector<bouncelight_t> &BounceLights();
const std::vector<int> &BounceLightsForFaceNum(int facenum);
const std::forward_list<bouncelight_t> &BounceLights();
const std::vector<std::reference_wrapper<bouncelight_t>> &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

View File

@ -21,6 +21,7 @@ See file, 'COPYING', for details.
#pragma once
#include <vector>
#include <tuple>
struct surfacelight_t
{
@ -46,6 +47,6 @@ struct surfacelight_t
};
std::vector<surfacelight_t> &GetSurfaceLights();
std::optional<int32_t> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face);
std::optional<std::tuple<int32_t, int32_t>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face);
const std::vector<int> &SurfaceLightsForFaceNum(int facenum);
void MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp);

View File

@ -47,8 +47,9 @@ using namespace std;
using namespace polylib;
mutex bouncelights_lock;
static std::vector<bouncelight_t> bouncelights;
std::unordered_map<int, std::vector<int>> bouncelightsByFacenum;
static std::forward_list<bouncelight_t> bouncelights;
static size_t lastBounceLightIndex;
static std::unordered_map<size_t, std::vector<std::reference_wrapper<bouncelight_t>>> 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<mutex> lck{bouncelights_lock};
bouncelight_t &l = bouncelights.emplace_back();
bouncelight_t &l = bouncelights.emplace_front();
const int lastBounceLightIndex = static_cast<int>(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<int, qvec3d> &colorByStyle,
static void AddBounceLight(const qvec3d &pos, std::unordered_map<int, qvec3d> &&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<int, qvec
l.pos = pos;
l.colorByStyle = colorByStyle;
qvec3f componentwiseMaxColor{};
for (const auto &styleColor : colorByStyle) {
for (const auto &styleColor : l.colorByStyle) {
for (int i = 0; i < 3; i++) {
if (styleColor.second[i] > 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<int, qvec
}
}
const std::vector<bouncelight_t> &BounceLights()
const std::forward_list<bouncelight_t> &BounceLights()
{
return bouncelights;
}
const std::vector<int> &BounceLightsForFaceNum(int facenum)
const std::vector<std::reference_wrapper<bouncelight_t>> &BounceLightsForFaceNum(int facenum)
{
const auto &vec = bouncelightsByFacenum.find(facenum);
if (vec != bouncelightsByFacenum.end()) {
return vec->second;
}
static std::vector<int> empty;
static std::vector<std::reference_wrapper<bouncelight_t>> 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);
}

View File

@ -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<int> &vpls = BounceLightsForFaceNum(Face_GetNum(lightsurf->bsp, lightsurf->face));
const std::vector<bouncelight_t> &all_vpls = BounceLights();
const std::vector<std::reference_wrapper<bouncelight_t>> &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()) {

View File

@ -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<int32_t> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face)
std::optional<std::tuple<int32_t, int32_t>> 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());
}
}

View File

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