Paril/mem write (#412)

* simplify light_surfaces storage

* memory on writes

* Revert "batch together traces on the whole surface - saves a small amount of time"

This reverts commit 72611b7e97.

# Conflicts:
#	light/ltface.cc

* fix a use-after-move

* don't try to write lightmap if it has no styles

* fix issue with alignment
This commit is contained in:
Jonathan 2024-03-13 22:01:05 -04:00 committed by GitHub
parent b89bac4e8c
commit 71aa8aaeea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1263 additions and 1220 deletions

View File

@ -32,6 +32,17 @@ constexpr auto avg(T &&...args)
return (args + ...) / sizeof...(args); return (args + ...) / sizeof...(args);
} }
template<size_t step, typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
constexpr T align_value(T value)
{
// round up to multiple of 4
if (value % step) {
return value + (step - (value % step));
}
return value;
}
constexpr double VECT_MAX = std::numeric_limits<double>::max(); constexpr double VECT_MAX = std::numeric_limits<double>::max();
/* /*

View File

@ -19,6 +19,8 @@
#pragma once #pragma once
#include <span>
#include <common/settings.hh> #include <common/settings.hh>
#include <common/bsputils.hh> // for faceextents_t #include <common/bsputils.hh> // for faceextents_t
@ -427,24 +429,20 @@ public:
extern settings::light_settings light_options; extern settings::light_settings light_options;
extern std::vector<uint8_t> filebase;
extern std::vector<uint8_t> lit_filebase;
extern std::vector<uint8_t> lux_filebase;
const std::unordered_map<int, std::vector<uint8_t>> &UncompressedVis(); const std::unordered_map<int, std::vector<uint8_t>> &UncompressedVis();
bool IsOutputtingSupplementaryData(); bool IsOutputtingSupplementaryData();
std::vector<std::unique_ptr<lightsurf_t>> &LightSurfaces(); std::span<lightsurf_t> &LightSurfaces();
std::vector<lightsurf_t*> &EmissiveLightSurfaces(); std::vector<lightsurf_t*> &EmissiveLightSurfaces();
extern std::vector<surfflags_t> extended_texinfo_flags; extern std::vector<surfflags_t> extended_texinfo_flags;
lightmap_t *Lightmap_ForStyle(lightmapdict_t *lightmaps, const int style, const lightsurf_t *lightsurf);
// public functions // public functions
void FixupGlobalSettings(); void FixupGlobalSettings();
void GetFileSpace(uint8_t **lightdata, uint8_t **colordata, uint8_t **deluxdata, int size);
void GetFileSpace_PreserveOffsetInBsp(uint8_t **lightdata, uint8_t **colordata, uint8_t **deluxdata, int lightofs);
const modelinfo_t *ModelInfoForModel(const mbsp_t *bsp, int modelnum); const modelinfo_t *ModelInfoForModel(const mbsp_t *bsp, int modelnum);
/** /**
* returns nullptr for "skip" faces * returns nullptr for "skip" faces

View File

@ -42,23 +42,19 @@ extern std::atomic<uint32_t> total_light_rays, total_light_ray_hits, total_sampl
extern std::atomic<uint32_t> total_bounce_rays, total_bounce_ray_hits; extern std::atomic<uint32_t> total_bounce_rays, total_bounce_ray_hits;
extern std::atomic<uint32_t> total_surflight_rays, total_surflight_ray_hits; // mxd extern std::atomic<uint32_t> total_surflight_rays, total_surflight_ray_hits; // mxd
#endif #endif
extern std::atomic<uint32_t> fully_transparent_lightmaps; extern std::atomic<uint32_t> fully_transparent_lightmaps; // write.cc
void PrintFaceInfo(const mface_t *face, const mbsp_t *bsp); void PrintFaceInfo(const mface_t *face, const mbsp_t *bsp);
// FIXME: remove light param. add normal param and dir params. // FIXME: remove light param. add normal param and dir params.
float GetLightValue(const settings::worldspawn_keys &cfg, const light_t *entity, float dist); float GetLightValue(const settings::worldspawn_keys &cfg, const light_t *entity, float dist);
void SetupDirt(settings::worldspawn_keys &cfg); void SetupDirt(settings::worldspawn_keys &cfg);
std::unique_ptr<lightsurf_t> CreateLightmapSurface(const mbsp_t *bsp, const mface_t *face, const facesup_t *facesup, lightsurf_t CreateLightmapSurface(const mbsp_t *bsp, const mface_t *face, const facesup_t *facesup,
const bspx_decoupled_lm_perface *facesup_decoupled, const settings::worldspawn_keys &cfg); const bspx_decoupled_lm_perface *facesup_decoupled, const settings::worldspawn_keys &cfg);
bool Face_IsLightmapped(const mbsp_t *bsp, const mface_t *face); bool Face_IsLightmapped(const mbsp_t *bsp, const mface_t *face);
bool Face_IsEmissive(const mbsp_t *bsp, const mface_t *face); bool Face_IsEmissive(const mbsp_t *bsp, const mface_t *face);
void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::worldspawn_keys &cfg); void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::worldspawn_keys &cfg);
void IndirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::worldspawn_keys &cfg, size_t bounce_depth); void IndirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::worldspawn_keys &cfg, size_t bounce_depth);
void PostProcessLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::worldspawn_keys &cfg); void PostProcessLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::worldspawn_keys &cfg);
void FinishLightmapSurface(const mbsp_t *bsp, lightsurf_t *lightsurf);
void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
bspx_decoupled_lm_perface *facesup_decoupled, lightsurf_t *lightsurf, const faceextents_t &extents,
const faceextents_t &output_extents);
struct lightgrid_sample_t struct lightgrid_sample_t
{ {

View File

@ -26,6 +26,7 @@
#include <common/fs.hh> #include <common/fs.hh>
struct mbsp_t; struct mbsp_t;
struct bspdata_t;
constexpr int32_t LIT_VERSION = 1; constexpr int32_t LIT_VERSION = 1;
@ -66,5 +67,7 @@ struct facesup_t
twosided<uint16_t> extent; twosided<uint16_t> extent;
}; };
void WriteLitFile(const mbsp_t *bsp, const std::vector<facesup_t> &facesup, const fs::path &filename, int version); void WriteLitFile(const mbsp_t *bsp, const std::vector<facesup_t> &facesup, const fs::path &filename, int version, const std::vector<uint8_t> &lit_filebase, const std::vector<uint8_t> &lux_filebase);
void WriteLuxFile(const mbsp_t *bsp, const fs::path &filename, int version); void WriteLuxFile(const mbsp_t *bsp, const fs::path &filename, int version, const std::vector<uint8_t> &lux_filebase);
void SaveLightmapSurfaces(bspdata_t *bspdata, const fs::path &source);

View File

@ -10,11 +10,10 @@ set(LIGHT_INCLUDES
../include/light/surflight.hh ../include/light/surflight.hh
../include/light/ltface.hh ../include/light/ltface.hh
../include/light/trace.hh ../include/light/trace.hh
../include/light/litfile.hh) ../include/light/write.hh)
set(LIGHT_SOURCES set(LIGHT_SOURCES
entities.cc entities.cc
litfile.cc
ltface.cc ltface.cc
trace.cc trace.cc
light.cc light.cc
@ -22,6 +21,7 @@ set(LIGHT_SOURCES
phong.cc phong.cc
bounce.cc bounce.cc
surflight.cc surflight.cc
write.cc
${LIGHT_INCLUDES}) ${LIGHT_INCLUDES})
if (embree_FOUND) if (embree_FOUND)

View File

@ -136,13 +136,7 @@ static bool MakeBounceLightsThread(const settings::worldspawn_keys &cfg, const m
return false; return false;
} }
auto &surf_ptr = LightSurfaces()[&face - bsp->dfaces.data()]; auto &surf = LightSurfaces()[&face - bsp->dfaces.data()];
if (!surf_ptr) {
return false;
}
auto &surf = *surf_ptr.get();
// no lights // no lights
if (!surf.lightmapsByStyle.size()) { if (!surf.lightmapsByStyle.size()) {

View File

@ -27,7 +27,7 @@
#include <common/cmdlib.hh> #include <common/cmdlib.hh>
#include <common/parser.hh> #include <common/parser.hh>
#include <light/litfile.hh> #include <light/write.hh>
#include <light/trace.hh> #include <light/trace.hh>
#include <light/trace_embree.hh> #include <light/trace_embree.hh>
#include <light/light.hh> #include <light/light.hh>

View File

@ -29,7 +29,7 @@
#include <light/surflight.hh> //mxd #include <light/surflight.hh> //mxd
#include <light/entities.hh> #include <light/entities.hh>
#include <light/ltface.hh> #include <light/ltface.hh>
#include <light/litfile.hh> // for facesup_t #include <light/write.hh> // for facesup_t
#include <light/trace_embree.hh> #include <light/trace_embree.hh>
#include <common/log.hh> #include <common/log.hh>
@ -59,13 +59,15 @@
bool dirt_in_use = false; bool dirt_in_use = false;
// intermediate representation of lightmap surfaces // intermediate representation of lightmap surfaces
static std::vector<std::unique_ptr<lightsurf_t>> light_surfaces; static std::unique_ptr<lightsurf_t[]> light_surfaces;
static std::span<lightsurf_t> light_surfaces_span;
// light_surfaces filtered down to just the emissive ones // light_surfaces filtered down to just the emissive ones
static std::vector<lightsurf_t*> emissive_light_surfaces; static std::vector<lightsurf_t*> emissive_light_surfaces;
std::vector<std::unique_ptr<lightsurf_t>> &LightSurfaces() std::span<lightsurf_t> &LightSurfaces()
{ {
return light_surfaces; return light_surfaces_span;
} }
std::vector<lightsurf_t*> &EmissiveLightSurfaces() std::vector<lightsurf_t*> &EmissiveLightSurfaces()
@ -77,44 +79,21 @@ static void UpdateEmissiveLightSurfacesList()
{ {
emissive_light_surfaces.clear(); emissive_light_surfaces.clear();
for (const auto &surf_ptr : light_surfaces) { for (auto &surf_ptr : light_surfaces_span) {
if (!surf_ptr || !surf_ptr->vpl) { if (surf_ptr.vpl) {
// didn't emit anthing emissive_light_surfaces.push_back(&surf_ptr);
continue;
} }
emissive_light_surfaces.push_back(surf_ptr.get());
} }
} }
static std::vector<facesup_t> faces_sup; // lit2/bspx stuff std::vector<facesup_t> faces_sup; // lit2/bspx stuff
static std::vector<bspx_decoupled_lm_perface> facesup_decoupled_global; std::vector<bspx_decoupled_lm_perface> facesup_decoupled_global;
bool IsOutputtingSupplementaryData() bool IsOutputtingSupplementaryData()
{ {
return !faces_sup.empty(); return !faces_sup.empty();
} }
/// start of lightmap data
std::vector<uint8_t> filebase;
/// offset of start of free space after data (should be kept a multiple of 4)
static int file_p;
/// offset of end of free space for lightmap data
static int file_end;
/// start of litfile data
std::vector<uint8_t> lit_filebase;
/// offset of start of free space after litfile data (should be kept a multiple of 12)
static int lit_file_p;
/// offset of end of space for litfile data
static int lit_file_end;
/// start of luxfile data
std::vector<uint8_t> lux_filebase;
/// offset of start of free space after luxfile data (should be kept a multiple of 12)
static int lux_file_p;
/// offset of end of space for luxfile data
static int lux_file_end;
static std::unordered_map<int, std::vector<uint8_t>> all_uncompressed_vis; static std::unordered_map<int, std::vector<uint8_t>> all_uncompressed_vis;
const std::unordered_map<int, std::vector<uint8_t>> &UncompressedVis() const std::unordered_map<int, std::vector<uint8_t>> &UncompressedVis()
@ -554,82 +533,6 @@ void FixupGlobalSettings()
} }
} }
static std::mutex light_mutex;
/*
* Return space for the lightmap and colourmap at the same time so it can
* be done in a thread-safe manner.
*
* size is the number of greyscale pixels = number of bytes to allocate
* and return in *lightdata
*/
void GetFileSpace(uint8_t **lightdata, uint8_t **colordata, uint8_t **deluxdata, int size)
{
light_mutex.lock();
*lightdata = *colordata = *deluxdata = nullptr;
if (!filebase.empty()) {
*lightdata = filebase.data() + file_p;
}
if (!lit_filebase.empty()) {
*colordata = lit_filebase.data() + lit_file_p;
}
if (!lux_filebase.empty()) {
*deluxdata = lux_filebase.data() + lux_file_p;
}
// if size isn't a multiple of 4, round up to the next multiple of 4
if ((size % 4) != 0) {
size += (4 - (size % 4));
}
// increment the next writing offsets, aligning them to 4 uint8_t boundaries (file_p)
// and 12-uint8_t boundaries (lit_file_p/lux_file_p)
if (!filebase.empty()) {
file_p += size;
}
if (!lit_filebase.empty()) {
lit_file_p += 3 * size;
}
if (!lux_filebase.empty()) {
lux_file_p += 3 * size;
}
light_mutex.unlock();
if (file_p > file_end)
FError("overrun");
if (lit_file_p > lit_file_end)
FError("overrun");
}
/**
* Special version of GetFileSpace for when we're relighting a .bsp and can't modify it.
* In this case the offsets are already known.
*/
void GetFileSpace_PreserveOffsetInBsp(uint8_t **lightdata, uint8_t **colordata, uint8_t **deluxdata, int lightofs)
{
Q_assert(lightofs >= 0);
*lightdata = *colordata = *deluxdata = nullptr;
if (!filebase.empty()) {
*lightdata = filebase.data() + lightofs;
}
if (colordata && !lit_filebase.empty()) {
*colordata = lit_filebase.data() + (lightofs * 3);
}
if (deluxdata && !lux_filebase.empty()) {
*deluxdata = lux_filebase.data() + (lightofs * 3);
}
// NOTE: file_p et. al. are not updated, since we're not dynamically allocating the lightmaps
}
const modelinfo_t *ModelInfoForModel(const mbsp_t *bsp, int modelnum) const modelinfo_t *ModelInfoForModel(const mbsp_t *bsp, int modelnum)
{ {
return modelinfo.at(modelnum); return modelinfo.at(modelnum);
@ -700,7 +603,8 @@ static void CacheTextures(const mbsp_t &bsp)
static void CreateLightmapSurfaces(mbsp_t *bsp) static void CreateLightmapSurfaces(mbsp_t *bsp)
{ {
light_surfaces.resize(bsp->dfaces.size()); light_surfaces = std::make_unique<lightsurf_t[]>(bsp->dfaces.size());
light_surfaces_span = { light_surfaces.get(), light_surfaces.get() + bsp->dfaces.size() };
logging::funcheader(); logging::funcheader();
logging::parallel_for(static_cast<size_t>(0), bsp->dfaces.size(), [&bsp](size_t i) { logging::parallel_for(static_cast<size_t>(0), bsp->dfaces.size(), [&bsp](size_t i) {
auto facesup = faces_sup.empty() ? nullptr : &faces_sup[i]; auto facesup = faces_sup.empty() ? nullptr : &faces_sup[i];
@ -733,48 +637,11 @@ static void CreateLightmapSurfaces(mbsp_t *bsp)
}); });
} }
static void SaveLightmapSurfaces(mbsp_t *bsp) static void ClearLightmapSurfaces()
{ {
logging::funcheader(); logging::funcheader();
logging::parallel_for(static_cast<size_t>(0), bsp->dfaces.size(), [&bsp](size_t i) { light_surfaces.reset();
auto &surf = light_surfaces[i]; light_surfaces_span = {};
if (!surf || surf->samples.empty()) {
return;
}
FinishLightmapSurface(bsp, surf.get());
auto f = &bsp->dfaces[i];
const modelinfo_t *face_modelinfo = ModelInfoForFace(bsp, i);
if (!facesup_decoupled_global.empty()) {
SaveLightmapSurface(
bsp, f, nullptr, &facesup_decoupled_global[i], surf.get(), surf->extents, surf->extents);
} else if (faces_sup.empty()) {
SaveLightmapSurface(bsp, f, nullptr, nullptr, surf.get(), surf->extents, surf->extents);
} else if (light_options.novanilla.value() || faces_sup[i].lmscale == face_modelinfo->lightmapscale) {
if (faces_sup[i].lmscale == face_modelinfo->lightmapscale) {
f->lightofs = faces_sup[i].lightofs;
} else {
f->lightofs = -1;
}
SaveLightmapSurface(bsp, f, &faces_sup[i], nullptr, surf.get(), surf->extents, surf->extents);
for (int j = 0; j < MAXLIGHTMAPS; j++) {
f->styles[j] =
faces_sup[i].styles[j] == INVALID_LIGHTSTYLE ? INVALID_LIGHTSTYLE_OLD : faces_sup[i].styles[j];
}
} else {
SaveLightmapSurface(bsp, f, nullptr, nullptr, surf.get(), surf->extents, surf->vanilla_extents);
SaveLightmapSurface(bsp, f, &faces_sup[i], nullptr, surf.get(), surf->extents, surf->extents);
}
});
}
void ClearLightmapSurfaces(mbsp_t *bsp)
{
logging::funcheader();
logging::parallel_for(static_cast<size_t>(0), bsp->dfaces.size(), [](size_t i) { light_surfaces[i].reset(); });
} }
static void FindModelInfo(const mbsp_t *bsp) static void FindModelInfo(const mbsp_t *bsp)
@ -852,47 +719,18 @@ static void FindModelInfo(const mbsp_t *bsp)
Q_assert(modelinfo.size() == bsp->dmodels.size()); Q_assert(modelinfo.size() == bsp->dmodels.size());
} }
// FIXME: in theory can't we calculate the exact amount of
// storage required? we'd have to expand it by 4 to account for
// lightstyles though
static constexpr size_t MAX_MAP_LIGHTING = 0x8000000;
/* /*
* ============= * =============
* LightWorld * LightWorld
* ============= * =============
*/ */
static void LightWorld(bspdata_t *bspdata, bool forcedscale) static void LightWorld(bspdata_t *bspdata, const fs::path &source, bool forcedscale)
{ {
logging::funcheader(); logging::funcheader();
mbsp_t &bsp = std::get<mbsp_t>(bspdata->bsp); mbsp_t &bsp = std::get<mbsp_t>(bspdata->bsp);
light_surfaces.clear(); ClearLightmapSurfaces();
filebase.clear();
lit_filebase.clear();
lux_filebase.clear();
if (!bsp.loadversion->game->has_rgb_lightmap) {
/* greyscale data stored in a separate buffer */
filebase.resize(MAX_MAP_LIGHTING);
file_p = 0;
file_end = MAX_MAP_LIGHTING;
}
if (bsp.loadversion->game->has_rgb_lightmap || light_options.write_litfile) {
/* litfile data stored in a separate buffer */
lit_filebase.resize(MAX_MAP_LIGHTING * 3);
lit_file_p = 0;
lit_file_end = (MAX_MAP_LIGHTING * 3);
}
if (light_options.write_luxfile) {
/* lux data stored in a separate buffer */
lux_filebase.resize(MAX_MAP_LIGHTING * 3);
lux_file_p = 0;
lux_file_end = (MAX_MAP_LIGHTING * 3);
}
if (forcedscale) { if (forcedscale) {
bspdata->bspx.entries.erase("LMSHIFT"); bspdata->bspx.entries.erase("LMSHIFT");
@ -949,11 +787,11 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
logging::header("Direct Lighting"); // mxd logging::header("Direct Lighting"); // mxd
logging::parallel_for(static_cast<size_t>(0), bsp.dfaces.size(), [&bsp](size_t i) { logging::parallel_for(static_cast<size_t>(0), bsp.dfaces.size(), [&bsp](size_t i) {
if (light_surfaces[i] && Face_IsLightmapped(&bsp, &bsp.dfaces[i])) { if (Face_IsLightmapped(&bsp, &bsp.dfaces[i])) {
#if defined(HAVE_EMBREE) && defined(__SSE2__) #if defined(HAVE_EMBREE) && defined(__SSE2__)
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
#endif #endif
DirectLightFace(&bsp, *light_surfaces[i].get(), light_options); DirectLightFace(&bsp, light_surfaces[i], light_options);
} }
}); });
@ -970,12 +808,12 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
logging::header(fmt::format("Indirect Lighting (pass {0})", i).c_str()); // mxd logging::header(fmt::format("Indirect Lighting (pass {0})", i).c_str()); // mxd
logging::parallel_for(static_cast<size_t>(0), bsp.dfaces.size(), [i, &bsp](size_t f) { logging::parallel_for(static_cast<size_t>(0), bsp.dfaces.size(), [i, &bsp](size_t f) {
if (light_surfaces[f] && Face_IsLightmapped(&bsp, &bsp.dfaces[f])) { if (Face_IsLightmapped(&bsp, &bsp.dfaces[f])) {
#if defined(HAVE_EMBREE) && defined(__SSE2__) #if defined(HAVE_EMBREE) && defined(__SSE2__)
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
#endif #endif
IndirectLightFace(&bsp, *light_surfaces[f].get(), light_options, i); IndirectLightFace(&bsp, light_surfaces[f], light_options, i);
} }
}); });
} }
@ -984,33 +822,17 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
if (!light_options.nolighting.value()) { if (!light_options.nolighting.value()) {
logging::header("Post-Processing"); // mxd logging::header("Post-Processing"); // mxd
logging::parallel_for(static_cast<size_t>(0), bsp.dfaces.size(), [&bsp](size_t i) { logging::parallel_for(static_cast<size_t>(0), bsp.dfaces.size(), [&bsp](size_t i) {
if (light_surfaces[i] && Face_IsLightmapped(&bsp, &bsp.dfaces[i])) { if (Face_IsLightmapped(&bsp, &bsp.dfaces[i])) {
#if defined(HAVE_EMBREE) && defined(__SSE2__) #if defined(HAVE_EMBREE) && defined(__SSE2__)
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
#endif #endif
PostProcessLightFace(&bsp, *light_surfaces[i].get(), light_options); PostProcessLightFace(&bsp, light_surfaces[i], light_options);
} }
}); });
} }
SaveLightmapSurfaces(&bsp); SaveLightmapSurfaces(bspdata, source);
logging::print("Lighting Completed.\n\n");
// Transfer greyscale lightmap (or color lightmap for Q2/HL) to the bsp and update lightdatasize
if (!light_options.litonly.value()) {
if (bsp.loadversion->game->has_rgb_lightmap) {
bsp.dlightdata.resize(lit_file_p);
memcpy(bsp.dlightdata.data(), lit_filebase.data(), bsp.dlightdata.size());
} else {
bsp.dlightdata.resize(file_p);
memcpy(bsp.dlightdata.data(), filebase.data(), bsp.dlightdata.size());
}
} else {
// NOTE: bsp.lightdatasize is already valid in the -litonly case
}
logging::print("lightdatasize: {}\n", bsp.dlightdata.size());
// kill this stuff if its somehow found. // kill this stuff if its somehow found.
bspdata->bspx.entries.erase("LMSTYLE16"); bspdata->bspx.entries.erase("LMSTYLE16");
@ -1470,22 +1292,10 @@ static inline void WriteNormals(const mbsp_t &bsp, bspdata_t &bspdata)
static void ResetLight() static void ResetLight()
{ {
dirt_in_use = false; dirt_in_use = false;
light_surfaces.clear(); ClearLightmapSurfaces();
faces_sup.clear(); faces_sup.clear();
facesup_decoupled_global.clear(); facesup_decoupled_global.clear();
filebase.clear();
file_p = 0;
file_end = 0;
lit_filebase.clear();
lit_file_p = 0;
lit_file_end = 0;
lux_filebase.clear();
lux_file_p = 0;
lux_file_end = 0;
all_uncompressed_vis.clear(); all_uncompressed_vis.clear();
modelinfo.clear(); modelinfo.clear();
tracelist.clear(); tracelist.clear();
@ -1627,11 +1437,11 @@ int light_main(int argc, const char **argv)
SetupDirt(light_options); SetupDirt(light_options);
LightWorld(&bspdata, light_options.lightmap_scale.is_changed()); LightWorld(&bspdata, source, light_options.lightmap_scale.is_changed());
LightGrid(&bspdata); LightGrid(&bspdata);
ClearLightmapSurfaces(&std::get<mbsp_t>(bspdata.bsp)); ClearLightmapSurfaces();
// invalidate normals // invalidate normals
bspdata.bspx.entries.erase("FACENORMALS"); bspdata.bspx.entries.erase("FACENORMALS");
@ -1640,30 +1450,9 @@ int light_main(int argc, const char **argv)
WriteNormals(bsp, bspdata); WriteNormals(bsp, bspdata);
} }
/*invalidate any bspx lighting info early*/
bspdata.bspx.entries.erase("RGBLIGHTING");
bspdata.bspx.entries.erase("LIGHTINGDIR");
if (light_options.write_litfile == lightfile::lit2) { if (light_options.write_litfile == lightfile::lit2) {
WriteLitFile(&bsp, faces_sup, source, 2);
return 0; // run away before any files are written return 0; // run away before any files are written
} }
/*fixme: add a new per-surface offset+lmscale lump for compat/versitility?*/
if (light_options.write_litfile & lightfile::external) {
WriteLitFile(&bsp, faces_sup, source, LIT_VERSION);
}
if (light_options.write_litfile & lightfile::bspx) {
lit_filebase.resize(bsp.dlightdata.size() * 3);
bspdata.bspx.transfer("RGBLIGHTING", lit_filebase);
}
if (light_options.write_luxfile & lightfile::external) {
WriteLuxFile(&bsp, source, LIT_VERSION);
}
if (light_options.write_luxfile & lightfile::bspx) {
lux_filebase.resize(bsp.dlightdata.size() * 3);
bspdata.bspx.transfer("LIGHTINGDIR", lux_filebase);
}
} }
/* -novanilla + internal lighting = no grey lightmap */ /* -novanilla + internal lighting = no grey lightmap */

View File

@ -1,102 +0,0 @@
/* Copyright (C) 2002-2006 Kevin Shanahan
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
See file, 'COPYING', for details.
*/
#include <light/litfile.hh>
#include <fstream>
#include <light/light.hh>
#include <common/bspfile.hh>
#include <common/cmdlib.hh>
#include <common/fs.hh>
// litheader_t::v1_t
void litheader_t::v1_t::stream_write(std::ostream &s) const
{
s <= std::tie(ident, version);
}
void litheader_t::v1_t::stream_read(std::istream &s)
{
s >= std::tie(ident, version);
}
// litheader_t::v2_t
void litheader_t::v2_t::stream_write(std::ostream &s) const
{
s <= std::tie(numsurfs, lmsamples);
}
void litheader_t::v2_t::stream_read(std::istream &s)
{
s >= std::tie(numsurfs, lmsamples);
}
void WriteLitFile(const mbsp_t *bsp, const std::vector<facesup_t> &facesup, const fs::path &filename, int version)
{
litheader_t header;
fs::path litname = filename;
litname.replace_extension("lit");
header.v1.version = version;
header.v2.numsurfs = bsp->dfaces.size();
header.v2.lmsamples = bsp->dlightdata.size();
logging::print("Writing {}\n", litname);
std::ofstream litfile(litname, std::ios_base::out | std::ios_base::binary);
litfile <= header.v1;
if (version == 2) {
unsigned int i, j;
litfile <= header.v2;
for (i = 0; i < bsp->dfaces.size(); i++) {
litfile <= facesup[i].lightofs;
for (int j = 0; j < 4; j++) {
litfile <= facesup[i].styles[j];
}
for (int j = 0; j < 2; j++) {
litfile <= facesup[i].extent[j];
}
j = 0;
while (nth_bit(j) < facesup[i].lmscale)
j++;
litfile <= (uint8_t)j;
}
litfile.write((const char *)lit_filebase.data(), bsp->dlightdata.size() * 3);
litfile.write((const char *)lux_filebase.data(), bsp->dlightdata.size() * 3);
} else
litfile.write((const char *)lit_filebase.data(), bsp->dlightdata.size() * 3);
}
void WriteLuxFile(const mbsp_t *bsp, const fs::path &filename, int version)
{
litheader_t header;
fs::path luxname = filename;
luxname.replace_extension("lux");
header.v1.version = version;
std::ofstream luxfile(luxname, std::ios_base::out | std::ios_base::binary);
luxfile <= header.v1;
luxfile.write((const char *)lux_filebase.data(), bsp->dlightdata.size() * 3);
}

File diff suppressed because it is too large Load Diff

View File

@ -53,13 +53,11 @@ int LightStyleForTargetname(const settings::worldspawn_keys &cfg, const std::str
static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys &cfg, const mface_t *face, static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys &cfg, const mface_t *face,
std::optional<qvec3f> texture_color, bool is_directional, bool is_sky, int32_t style, int32_t light_value) std::optional<qvec3f> texture_color, bool is_directional, bool is_sky, int32_t style, int32_t light_value)
{ {
auto &surf_ptr = LightSurfaces()[face - bsp->dfaces.data()]; if (!Face_IsEmissive(bsp, face)) {
if (!surf_ptr || !Face_IsEmissive(bsp, face)) {
return; return;
} }
auto &surf = *surf_ptr.get(); auto &surf = LightSurfaces()[face - bsp->dfaces.data()];
// Create face points... // Create face points...
auto poly = Face_Points(bsp, face); auto poly = Face_Points(bsp, face);

1112
light/write.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -279,13 +279,7 @@ TEST_CASE("-novanilla + -world_units_per_luxel")
// count used pixels per style // count used pixels per style
auto lm_info = BSPX_DecoupledLM(bspx, Face_GetNum(&bsp, &face)); auto lm_info = BSPX_DecoupledLM(bspx, Face_GetNum(&bsp, &face));
const faceextents_t extents(face, bsp, lm_info.lmwidth, lm_info.lmheight, lm_info.world_to_lm_space); const faceextents_t extents(face, bsp, lm_info.lmwidth, lm_info.lmheight, lm_info.world_to_lm_space);
int samples_per_face = extents.numsamples() * face_used_styles; int samples_per_face = align_value<4>(extents.numsamples() * face_used_styles);
// round up to multiple of 4
if (samples_per_face % 4) {
samples_per_face += (4 - (samples_per_face % 4));
}
int bytes_per_face = 3 * samples_per_face; int bytes_per_face = 3 * samples_per_face;
expected_dlightdata_bytes += bytes_per_face; expected_dlightdata_bytes += bytes_per_face;
} }