ltface: support -world_units_per_luxel without -novanilla

first pass implementation - quality of vanilla LM is bad, due to nearest sampling
the decoupled lightmap
This commit is contained in:
Eric Wasylishen 2022-11-14 23:58:31 -07:00
parent 959fe32e18
commit 46d460277a
3 changed files with 89 additions and 5 deletions

View File

@ -2656,6 +2656,54 @@ static void WriteSingleLightmap(const mbsp_t *bsp, const mface_t *face, const li
}
}
/**
* - Writes (output_width * output_height) bytes to `out`
* - Writes (output_width * output_height * 3) bytes to `lit`
* - 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)
{
// this is the lightmap data in the "decoupled" coordinate system
std::vector<qvec4f> fullres = LightmapColorsToGLMVector(lightsurf, lm);
for (int t = 0; t < output_height; t++) {
for (int s = 0; s < output_width; s++) {
// convert from vanilla lm coord to decoupled lm coord
qvec3f world = lightsurf->vanilla_extents.LMCoordToWorld(qvec2f(s, t));
qvec2f decoupled_lm_coord = lightsurf->extents.worldToLMCoord(world);
decoupled_lm_coord = decoupled_lm_coord * light_options.extra.value();
const int input_sample_s = clamp((int)decoupled_lm_coord[0], 0, lightsurf->width - 1);
const int input_sample_t = clamp((int)decoupled_lm_coord[1], 0, lightsurf->height - 1);
const int sampleindex = (input_sample_t * lightsurf->width) + input_sample_s;
if (lit || out) {
const qvec4f &color = fullres.at(sampleindex);
if (lit) {
*lit++ = color[0];
*lit++ = color[1];
*lit++ = color[2];
}
if (out) {
// FIXME: implement
*out++ = 0;
}
}
if (lux) {
// FIXME: implement
*lux++ = 0;
*lux++ = 0;
*lux++ = 0;
}
}
}
}
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)
@ -2848,11 +2896,9 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
lightofs = out - filebase.data();
}
if (facesup_decoupled && light_options.novanilla.value()) {
if (facesup_decoupled) {
facesup_decoupled->offset = lightofs;
face->lightofs = -1;
} else if (facesup_decoupled && !light_options.novanilla.value()) {
FError("-world_units_per_luxel currently requires -novanilla");
} else if (facesup) {
facesup->lightofs = lightofs;
} else {
@ -2882,6 +2928,37 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
lux += (size * 3);
}
}
// 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);
// Q2/HL native colored lightmaps
if (bsp->loadversion->game->has_rgb_lightmap) {
lightofs = lit - lit_filebase.data();
} else {
lightofs = out - filebase.data();
}
face->lightofs = lightofs;
for (int mapnum = 0; mapnum < numstyles; mapnum++) {
const lightmap_t *lm = sorted.at(mapnum);
WriteSingleLightmap_FromDecoupled(bsp, face, lightsurf, lm, lightsurf->vanilla_extents.width(),
lightsurf->vanilla_extents.height(), out, lit, lux);
if (out) {
out += lightsurf->vanilla_extents.numsamples();
}
if (lit) {
lit += (lightsurf->vanilla_extents.numsamples() * 3);
}
if (lux) {
lux += (lightsurf->vanilla_extents.numsamples() * 3);
}
}
}
}
std::unique_ptr<lightsurf_t> CreateLightmapSurface(const mbsp_t *bsp, const mface_t *face, const facesup_t *facesup,

View File

@ -977,3 +977,10 @@
"origin" "-398 -160 94"
"light" "1200"
}
// entity 7
{
"classname" "light"
"origin" "232 -248 104"
"style" "1"
"_color" "183 255 227"
}

View File

@ -63,8 +63,8 @@ static testresults_t LoadTestmap(const std::filesystem::path &name, std::vector<
}
}
TEST_CASE("TestLight") {
LoadTestmap("q2_lightmap_custom_scale.map", {"-threads", "1", "-world_units_per_luxel", "8", "-novanilla"});
TEST_CASE("-world_units_per_luxel") {
LoadTestmap("q2_lightmap_custom_scale.map", {"-world_units_per_luxel", "8"});
}
TEST_CASE("emissive cube artifacts") {