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:
parent
b89bac4e8c
commit
71aa8aaeea
|
|
@ -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();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
267
light/light.cc
267
light/light.cc
|
|
@ -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 */
|
||||||
|
|
|
||||||
102
light/litfile.cc
102
light/litfile.cc
|
|
@ -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);
|
|
||||||
}
|
|
||||||
936
light/ltface.cc
936
light/ltface.cc
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue