Skip to content

Commit

Permalink
WiP: Forward port HDR lightmaps to latest.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsvensson committed Nov 28, 2023
1 parent 3eb5cb7 commit 6378bf0
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 25 deletions.
16 changes: 16 additions & 0 deletions common/bspfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2479,6 +2479,22 @@ void bspdata_t::bspxentries::transfer(const char *xname, std::vector<uint8_t> &&
entries.insert_or_assign(xname, xdata);
}

// get rid of this, just stupid
void bspdata_t::bspxentries::transfer(const char *xname, std::vector<uint32_t> &xdata)
{
std::vector<uint8_t> output;
output.reserve(xdata.size() * 4);

for (uint32_t value : xdata) {
output.push_back(static_cast<uint8_t>(value & 0xFF));
output.push_back(static_cast<uint8_t>((value >> 8) & 0xFF));
output.push_back(static_cast<uint8_t>((value >> 16) & 0xFF));
output.push_back(static_cast<uint8_t>((value >> 24) & 0xFF));
}

entries.insert_or_assign(xname, std::move(output));
}

/*
* =============
* LoadBSPFile
Expand Down
3 changes: 3 additions & 0 deletions include/common/bspfile.hh
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,9 @@ struct bspdata_t
// transfer ownership of the vector into a BSPX lump
void transfer(const char *xname, std::vector<uint8_t> &xdata);

// transfer ownership of the vector into a BSPX lump
void transfer(const char *xname, std::vector<uint32_t> &xdata);

// transfer ownership of the vector into a BSPX lump
void transfer(const char *xname, std::vector<uint8_t> &&xdata);
};
Expand Down
10 changes: 7 additions & 3 deletions include/light/light.hh
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ enum class lightfile
external = 1,
bspx = 2,
both = external | bspx,
lit2 = 4
lit2 = 4,
hdr = 8,
};

/* tracelist is a std::vector of pointers to modelinfo_t to use for LOS tests */
Expand Down Expand Up @@ -390,6 +391,8 @@ public:
setting_func lit;
setting_func lit2;
setting_func bspxlit;
setting_func hdr;
setting_func bspxhdr;
setting_func lux;
setting_func bspxlux;
setting_func bspxonly;
Expand Down Expand Up @@ -432,6 +435,7 @@ extern settings::light_settings light_options;

extern std::vector<uint8_t> filebase;
extern std::vector<uint8_t> lit_filebase;
extern std::vector<uint32_t> hdr_filebase;
extern std::vector<uint8_t> lux_filebase;

const std::unordered_map<int, std::vector<uint8_t>> &UncompressedVis();
Expand All @@ -446,8 +450,8 @@ extern std::vector<surfflags_t> extended_texinfo_flags;
// public functions

void FixupGlobalSettings(void);
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);
void GetFileSpace(uint8_t **lightdata, uint8_t **colordata, uint32_t **hdrdata, uint8_t **deluxdata, int size);
void GetFileSpace_PreserveOffsetInBsp(uint8_t **lightdata, uint8_t **colordata, uint32_t **hdrdata, uint8_t **deluxdata, int lightofs);
const modelinfo_t *ModelInfoForModel(const mbsp_t *bsp, int modelnum);
/**
* returns nullptr for "skip" faces
Expand Down
44 changes: 42 additions & 2 deletions light/light.cc
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ static int lit_file_p;
/// offset of end of space for litfile data
static int lit_file_end;

/// start of litfile data
std::vector<uint32_t> hdr_filebase;
/// offset of start of free space after litfile data (should be kept a multiple of 12)
static int hdr_file_p;
/// offset of end of space for litfile data
static int hdr_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)
Expand Down Expand Up @@ -338,6 +345,9 @@ light_settings::light_settings()
lit2{this, "lit2", [&](source) { write_litfile = lightfile::lit2; }, &experimental_group, "write .lit2 file"},
bspxlit{this, "bspxlit", [&](source) { write_litfile |= lightfile::bspx; }, &experimental_group,
"writes rgb data into the bsp itself"},
hdr{this, "hdr", [&](source) { write_litfile |= lightfile::external; write_litfile |= lightfile::hdr; }, &experimental_group, "write .lit file as e5bgr9"},
bspxhdr{this, "bspxhdr", [&](source) { write_litfile |= lightfile::bspx; write_litfile |= lightfile::hdr; }, &experimental_group,
"writes rgb data into the bsp itself as e5bgr9"},
lux{this, "lux", [&](source) { write_luxfile |= lightfile::external; }, &experimental_group, "write .lux file"},
bspxlux{this, "bspxlux", [&](source) { write_luxfile |= lightfile::bspx; }, &experimental_group,
"writes lux data into the bsp itself"},
Expand Down Expand Up @@ -484,8 +494,12 @@ void light_settings::postinitialize(int argc, const char **argv)
} else {
if (write_litfile & lightfile::external)
logging::print(".lit colored light output requested on command line.\n");
if (write_litfile & lightfile::external && write_litfile & lightfile::hdr)
logging::print(".lit colored E5BGR9 light output requested on command line.\n");
if (write_litfile & lightfile::bspx)
logging::print("BSPX colored light output requested on command line.\n");
if (write_litfile & lightfile::bspx && write_litfile & lightfile::hdr)
logging::print("BSPX colored E5BGR9 light output requested on command line.\n");
if (write_luxfile & lightfile::external)
logging::print(".lux light directions output requested on command line.\n");
if (write_luxfile & lightfile::bspx)
Expand Down Expand Up @@ -563,7 +577,7 @@ static std::mutex light_mutex;
* 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)
void GetFileSpace(uint8_t **lightdata, uint8_t **colordata, uint32_t **hdrdata, uint8_t **deluxdata, int size)
{
light_mutex.lock();

Expand All @@ -575,6 +589,9 @@ void GetFileSpace(uint8_t **lightdata, uint8_t **colordata, uint8_t **deluxdata,
if (!lit_filebase.empty()) {
*colordata = lit_filebase.data() + lit_file_p;
}
if (!hdr_filebase.empty()) {
*hdrdata = hdr_filebase.data() + hdr_file_p;
}
if (!lux_filebase.empty()) {
*deluxdata = lux_filebase.data() + lux_file_p;
}
Expand All @@ -592,6 +609,9 @@ void GetFileSpace(uint8_t **lightdata, uint8_t **colordata, uint8_t **deluxdata,
if (!lit_filebase.empty()) {
lit_file_p += 3 * size;
}
if (!hdr_filebase.empty()) {
hdr_file_p += size;
}
if (!lux_filebase.empty()) {
lux_file_p += 3 * size;
}
Expand All @@ -603,13 +623,16 @@ void GetFileSpace(uint8_t **lightdata, uint8_t **colordata, uint8_t **deluxdata,

if (lit_file_p > lit_file_end)
FError("overrun");

if (hdr_file_p > hdr_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)
void GetFileSpace_PreserveOffsetInBsp(uint8_t **lightdata, uint8_t **colordata, uint32_t **hdrdata, uint8_t **deluxdata, int lightofs)
{
Q_assert(lightofs >= 0);

Expand All @@ -623,6 +646,10 @@ void GetFileSpace_PreserveOffsetInBsp(uint8_t **lightdata, uint8_t **colordata,
*colordata = lit_filebase.data() + (lightofs * 3);
}

if (hdrdata && !hdr_filebase.empty()) {
*hdrdata = hdr_filebase.data() + lightofs;
}

if (deluxdata && !lux_filebase.empty()) {
*deluxdata = lux_filebase.data() + (lightofs * 3);
}
Expand Down Expand Up @@ -871,6 +898,7 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
light_surfaces.clear();
filebase.clear();
lit_filebase.clear();
hdr_filebase.clear();
lux_filebase.clear();

if (!bsp.loadversion->game->has_rgb_lightmap) {
Expand All @@ -887,6 +915,13 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
lit_file_end = (MAX_MAP_LIGHTING * 3);
}

if (bsp.loadversion->game->has_rgb_lightmap || light_options.write_litfile) {
/* hdr data stored in a separate buffer */
hdr_filebase.resize(MAX_MAP_LIGHTING);
hdr_file_p = 0;
hdr_file_end = MAX_MAP_LIGHTING;
}

if (light_options.write_luxfile) {
/* lux data stored in a separate buffer */
lux_filebase.resize(MAX_MAP_LIGHTING * 3);
Expand Down Expand Up @@ -1643,6 +1678,7 @@ int light_main(int argc, const char **argv)

/*invalidate any bspx lighting info early*/
bspdata.bspx.entries.erase("RGBLIGHTING");
bspdata.bspx.entries.erase("LIGHTING_E5BGR9");
bspdata.bspx.entries.erase("LIGHTINGDIR");

if (light_options.write_litfile == lightfile::lit2) {
Expand All @@ -1658,6 +1694,10 @@ int light_main(int argc, const char **argv)
lit_filebase.resize(bsp.dlightdata.size() * 3);
bspdata.bspx.transfer("RGBLIGHTING", lit_filebase);
}
if (light_options.write_litfile & lightfile::bspx && light_options.write_litfile & lightfile::hdr) {
hdr_filebase.resize(bsp.dlightdata.size());
bspdata.bspx.transfer("LIGHTING_E5BGR9", hdr_filebase);
}
if (light_options.write_luxfile & lightfile::external) {
WriteLuxFile(&bsp, source, LIT_VERSION);
}
Expand Down
8 changes: 6 additions & 2 deletions light/litfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,12 @@ void WriteLitFile(const mbsp_t *bsp, const std::vector<facesup_t> &facesup, cons
}
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);
} else {
if ((version & 0xffff0000)==0x00010000)
litfile.write((const char *)hdr_filebase.data(), bsp->dlightdata.size() * 4);
else
litfile.write((const char *)lit_filebase.data(), bsp->dlightdata.size() * 3);
}
}

void WriteLuxFile(const mbsp_t *bsp, const fs::path &filename, int version)
Expand Down
82 changes: 64 additions & 18 deletions light/ltface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2406,14 +2406,6 @@ inline void LightFace_ScaleAndClamp(lightsurf_t *lightsurf)
c = pow(c / 255.0f, 1.0 / cfg.lightmapgamma.value()) * 255.0f;
}
}

// clamp
// FIXME: should this be a brightness clamp?
vec_t maxcolor = qv::max(color);

if (maxcolor > 255.0) {
color *= (255.0 / maxcolor);
}
}
}
}
Expand Down Expand Up @@ -2838,13 +2830,44 @@ bool Face_IsEmissive(const mbsp_t *bsp, const mface_t *face)
return bsp->loadversion->game->surf_is_emissive(texinfo->flags, texname);
}

static unsigned int HDR_PackResult(qvec4f rgba)
{
#define HDR_ONE 128.0f //logical value for 1.0 lighting (quake's overbrights give 255).
//we want 0-1-like values. except that we can oversample and express smaller values too.
float r = rgba[0]/HDR_ONE;
float g = rgba[1]/HDR_ONE;
float b = rgba[2]/HDR_ONE;

int e = 0;
float m = std::max(std::max(r, g), b);
float scale;

if (m >= 0.5f)
{ //positive exponent
while (m >= (1<<(e)) && e < 30-15) //don't do nans.
e++;
}
else
{ //negative exponent...
while (m < 1/(1<<-e) && e > -15) //don't do nans.
e--;
}

scale = pow(2, e-9);

return ((e+15)<<27) |
(std::min((int)(b/scale + 0.5f), 0x1ff)<<18) |
(std::min((int)(g/scale + 0.5f), 0x1ff)<<9) |
(std::min((int)(r/scale + 0.5f), 0x1ff)<<0);
}

/**
* - Writes (actual_width * actual_height) bytes to `out`
* - Writes (actual_width * actual_height * 3) bytes to `lit`
* - Writes (actual_width * actual_height * 3) bytes to `lux`
*/
static void WriteSingleLightmap(const mbsp_t *bsp, const mface_t *face, const lightsurf_t *lightsurf,
const lightmap_t *lm, const int actual_width, const int actual_height, uint8_t *out, uint8_t *lit, uint8_t *lux,
const lightmap_t *lm, const int actual_width, const int actual_height, uint8_t *out, uint8_t *lit, uint32_t *hdr, uint8_t *lux,
const faceextents_t &output_extents)
{
const int oversampled_width = actual_width * light_options.extra.value();
Expand Down Expand Up @@ -2886,7 +2909,16 @@ static void WriteSingleLightmap(const mbsp_t *bsp, const mface_t *face, const li
const int sampleindex = (input_sample_t * actual_width) + input_sample_s;

if (lit || out) {
const qvec4f &color = output_color.at(sampleindex);
qvec4f color = output_color.at(sampleindex);

if (hdr)
*hdr++ = HDR_PackResult(color);

const vec_t max_color = qv::max(color);
if (max_color > 255.0f)
{
color *= 255.0 / max_color;
}

if (lit) {
*lit++ = color[0];
Expand Down Expand Up @@ -2938,7 +2970,7 @@ static void WriteSingleLightmap(const mbsp_t *bsp, const mface_t *face, const li
* - Writes (output_width * output_height * 3) bytes to `lux`
*/
static void WriteSingleLightmap_FromDecoupled(const mbsp_t *bsp, const mface_t *face, const lightsurf_t *lightsurf,
const lightmap_t *lm, const int output_width, const int output_height, uint8_t *out, uint8_t *lit, uint8_t *lux)
const lightmap_t *lm, const int output_width, const int output_height, uint8_t *out, uint8_t *lit, uint32_t *hdr, uint8_t *lux)
{
// this is the lightmap data in the "decoupled" coordinate system
std::vector<qvec4f> fullres = LightmapColorsToGLMVector(lightsurf, lm);
Expand Down Expand Up @@ -2974,11 +3006,20 @@ static void WriteSingleLightmap_FromDecoupled(const mbsp_t *bsp, const mface_t *
const float coord_frac_y = decoupled_lm_coord[1] - coord_floor_y;

// 2D bilinear interpolation
const qvec4f color =
qvec4f color =
mix(mix(tex(coord_floor_x, coord_floor_y), tex(coord_floor_x + 1, coord_floor_y), coord_frac_x),
mix(tex(coord_floor_x, coord_floor_y + 1), tex(coord_floor_x + 1, coord_floor_y + 1), coord_frac_x),
coord_frac_y);

if (hdr)
*hdr++ = HDR_PackResult(color);

const vec_t max_color = qv::max(color);
if (max_color > 255.0f)
{
color *= 255.0 / max_color;
}

if (lit || out) {
if (lit) {
*lit++ = color[0];
Expand Down Expand Up @@ -3024,7 +3065,8 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
}

uint8_t *out, *lit, *lux;
GetFileSpace_PreserveOffsetInBsp(&out, &lit, &lux, face->lightofs);
uint32_t *hdr;
GetFileSpace_PreserveOffsetInBsp(&out, &lit, &hdr, &lux, face->lightofs);

for (int mapnum = 0; mapnum < MAXLIGHTMAPS; mapnum++) {
const int style = face->styles[mapnum];
Expand All @@ -3037,7 +3079,7 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
for (const lightmap_t &lm : lightmaps) {
if (lm.style == style) {
WriteSingleLightmap(
bsp, face, lightsurf, &lm, actual_width, actual_height, out, lit, lux, output_extents);
bsp, face, lightsurf, &lm, actual_width, actual_height, out, lit, hdr, lux, output_extents);
break;
}
}
Expand Down Expand Up @@ -3184,7 +3226,8 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
return;

uint8_t *out, *lit, *lux;
GetFileSpace(&out, &lit, &lux, size * numstyles);
uint32_t *hdr;
GetFileSpace(&out, &lit, &hdr, &lux, size * numstyles);

int lightofs;

Expand Down Expand Up @@ -3212,7 +3255,7 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
for (int mapnum = 0; mapnum < numstyles; mapnum++) {
const lightmap_t *lm = sorted.at(mapnum);

WriteSingleLightmap(bsp, face, lightsurf, lm, actual_width, actual_height, out, lit, lux, output_extents);
WriteSingleLightmap(bsp, face, lightsurf, lm, actual_width, actual_height, out, lit, hdr, lux, output_extents);

if (out) {
out += size;
Expand All @@ -3228,7 +3271,7 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
// write vanilla lightmap if -world_units_per_luxel is in use but not -novanilla
if (facesup_decoupled && !light_options.novanilla.value()) {
// FIXME: duplicates some code from above
GetFileSpace(&out, &lit, &lux, lightsurf->vanilla_extents.numsamples() * numstyles);
GetFileSpace(&out, &lit, &hdr, &lux, lightsurf->vanilla_extents.numsamples() * numstyles);

// Q2/HL native colored lightmaps
if (bsp->loadversion->game->has_rgb_lightmap) {
Expand All @@ -3242,14 +3285,17 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
const lightmap_t *lm = sorted.at(mapnum);

WriteSingleLightmap_FromDecoupled(bsp, face, lightsurf, lm, lightsurf->vanilla_extents.width(),
lightsurf->vanilla_extents.height(), out, lit, lux);
lightsurf->vanilla_extents.height(), out, lit, hdr, lux);

if (out) {
out += lightsurf->vanilla_extents.numsamples();
}
if (lit) {
lit += (lightsurf->vanilla_extents.numsamples() * 3);
}
if (hdr) {
hdr += (lightsurf->vanilla_extents.numsamples());
}
if (lux) {
lux += (lightsurf->vanilla_extents.numsamples() * 3);
}
Expand Down

0 comments on commit 6378bf0

Please sign in to comment.