light: write styles into the experimental lightgrid lump

This commit is contained in:
Eric Wasylishen 2023-02-05 17:16:57 -07:00
parent 89fa416708
commit 2cc513848b
3 changed files with 127 additions and 28 deletions

View File

@ -57,5 +57,21 @@ void FinishLightmapSurface(const mbsp_t *bsp, lightsurf_t *lightsurf);
void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, 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, bspx_decoupled_lm_perface *facesup_decoupled, lightsurf_t *lightsurf, const faceextents_t &extents,
const faceextents_t &output_extents); const faceextents_t &output_extents);
qvec3d CalcLightgridAtPoint(const mbsp_t *bsp, const qvec3d &world_point);
struct lightgrid_sample_t {
bool used = false;
int style = 0;
qvec3d color {};
qvec3b round_to_int() const;
};
struct lightgrid_samples_t {
std::array<lightgrid_sample_t, 4> samples_by_style;
void add(const qvec3d &color, int style);
int used_styles() const;
};
lightgrid_samples_t CalcLightgridAtPoint(const mbsp_t *bsp, const qvec3d &world_point);
void ResetLtFace(); void ResetLtFace();

View File

@ -1064,10 +1064,9 @@ static void LightGrid(bspdata_t *bspdata)
// number of grid points on each axis // number of grid points on each axis
const qvec3i grid_size = {GRIDSIZE, GRIDSIZE, GRIDSIZE}; const qvec3i grid_size = {GRIDSIZE, GRIDSIZE, GRIDSIZE};
const qvec3f grid_mins = bsp.dmodels[0].mins; const qvec3f grid_mins = bsp.dmodels[0].mins;
const uint8_t num_styles = 1;
std::vector<uint8_t> grid_result; std::vector<lightgrid_samples_t> grid_result;
grid_result.resize(GRIDSIZE * GRIDSIZE * GRIDSIZE * 3); grid_result.resize(GRIDSIZE * GRIDSIZE * GRIDSIZE);
std::vector<uint8_t> occlusion; std::vector<uint8_t> occlusion;
occlusion.resize(GRIDSIZE * GRIDSIZE * GRIDSIZE); occlusion.resize(GRIDSIZE * GRIDSIZE * GRIDSIZE);
@ -1081,24 +1080,42 @@ static void LightGrid(bspdata_t *bspdata)
for (int z = z_range.begin(); z < z_range.end(); ++z) { for (int z = z_range.begin(); z < z_range.end(); ++z) {
for (int y = y_range.begin(); y < y_range.end(); ++y) { for (int y = y_range.begin(); y < y_range.end(); ++y) {
for (int x = x_range.begin(); x < x_range.end(); ++x) { for (int x = x_range.begin(); x < x_range.end(); ++x) {
qvec3d world_point = grid_mins + (qvec3d{x,y,z} * grid_dist); qvec3d world_point = grid_mins + (qvec3d{x,y,z} * grid_dist);
qvec3d color = CalcLightgridAtPoint(&bsp, world_point); lightgrid_samples_t samples = CalcLightgridAtPoint(&bsp, world_point);
bool occluded = Light_PointInWorld(&bsp, world_point); bool occluded = Light_PointInWorld(&bsp, world_point);
int sample_index = (GRIDSIZE * GRIDSIZE * z) + (GRIDSIZE * y) + x; int sample_index = (GRIDSIZE * GRIDSIZE * z) + (GRIDSIZE * y) + x;
grid_result[sample_index * 3] = clamp((int)color[0], 0, 255); grid_result[sample_index] = samples;
grid_result[sample_index * 3 + 1] = clamp((int)color[1], 0, 255);
grid_result[sample_index * 3 + 2] = clamp((int)color[2], 0, 255);
occlusion[sample_index] = occluded; occlusion[sample_index] = occluded;
} }
} }
} }
}); });
// num_styles == 1 is a flag for "all grid points use only style 0"
const uint8_t all_style_0 = [&](){
for (auto &samples : grid_result) {
if (samples.used_styles() != 1)
return false;
if (samples.samples_by_style[0].style != 0)
return false;
}
return true;
}();
// otherwise, it gives the maximum used styles across the map.
const uint8_t num_styles = [&](){
int result = 0;
for (auto &samples : grid_result) {
result = max(result, samples.used_styles());
}
return result;
}();
// FIXME: technically num_styles == 1 could happen if all grid points are style 1 or something
// non-final, experimental lump // non-final, experimental lump
std::ostringstream str(std::ios_base::out | std::ios_base::binary); std::ostringstream str(std::ios_base::out | std::ios_base::binary);
str << endianness<std::endian::little>; str << endianness<std::endian::little>;
@ -1107,9 +1124,23 @@ static void LightGrid(bspdata_t *bspdata)
str <= grid_mins; str <= grid_mins;
str <= num_styles; str <= num_styles;
// color data 3D array // if the map only has 1 style, write a more compact form
for (uint8_t byte : grid_result) { if (num_styles == 1) {
str <= byte; // color data 3D array
for (const lightgrid_samples_t &samples : grid_result) {
str <= samples.samples_by_style[0].round_to_int();
}
} else {
// general case
for (const lightgrid_samples_t &samples : grid_result) {
str <= static_cast<uint8_t>(samples.used_styles());
for (int i = 0; i < samples.used_styles(); ++i) {
str <= static_cast<uint8_t>(samples.samples_by_style[i].style);
}
for (int i = 0; i < samples.used_styles(); ++i) {
str <= samples.samples_by_style[i].round_to_int();
}
}
} }
// occlusion 3D array // occlusion 3D array

View File

@ -1253,11 +1253,8 @@ static void LightFace_Entity(
* Calculates light at a given point from an entity * Calculates light at a given point from an entity
*/ */
static void LightPoint_Entity( static void LightPoint_Entity(
const mbsp_t *bsp, raystream_occlusion_t &rs, const light_t *entity, const qvec3d &surfpoint, qvec3d &result) const mbsp_t *bsp, raystream_occlusion_t &rs, const light_t *entity, const qvec3d &surfpoint, lightgrid_samples_t &result)
{ {
if (entity->style.value() != 0)
return; // not doing style lightgrid for now
rs.clearPushedRays(); rs.clearPushedRays();
qvec3d surfpointToLightDir; qvec3d surfpointToLightDir;
@ -1297,7 +1294,7 @@ static void LightPoint_Entity(
continue; continue;
} }
result += rs.getPushedRayColor(j); result.add(rs.getPushedRayColor(j), entity->style.value());
} }
} }
@ -1415,11 +1412,8 @@ static void LightFace_Sky(const sun_t *sun, lightsurf_t *lightsurf, lightmapdict
} }
static void LightPoint_Sky( static void LightPoint_Sky(
const mbsp_t *bsp, raystream_intersection_t &rs, const sun_t *sun, const qvec3d &surfpoint, qvec3d &result) const mbsp_t *bsp, raystream_intersection_t &rs, const sun_t *sun, const qvec3d &surfpoint, lightgrid_samples_t &result)
{ {
if (sun->style != 0)
return; // not doing style lightgrid for now
// FIXME: Normalized sun vector should be stored in the sun_t. Also clarify which way the vector points (towards or // FIXME: Normalized sun vector should be stored in the sun_t. Also clarify which way the vector points (towards or
// away..) // away..)
// FIXME: Much of this is copied/pasted from LightFace_Entity, should probably be merged // FIXME: Much of this is copied/pasted from LightFace_Entity, should probably be merged
@ -1471,7 +1465,7 @@ static void LightPoint_Sky(
continue; continue;
} }
result += rs.getPushedRayColor(j); result.add(rs.getPushedRayColor(j), sun->style);
} }
} }
@ -1923,7 +1917,7 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
static void // mxd static void // mxd
LightPoint_SurfaceLight(const mbsp_t *bsp, raystream_occlusion_t &rs, const std::vector<surfacelight_t> &surface_lights, LightPoint_SurfaceLight(const mbsp_t *bsp, raystream_occlusion_t &rs, const std::vector<surfacelight_t> &surface_lights,
const vec_t &standard_scale, const vec_t &sky_scale, const float &hotspot_clamp, const qvec3d &surfpoint, qvec3d &result) const vec_t &standard_scale, const vec_t &sky_scale, const float &hotspot_clamp, const qvec3d &surfpoint, lightgrid_samples_t &result)
{ {
const settings::worldspawn_keys &cfg = light_options; const settings::worldspawn_keys &cfg = light_options;
const float surflight_gate = 0.01f; const float surflight_gate = 0.01f;
@ -1978,7 +1972,7 @@ LightPoint_SurfaceLight(const mbsp_t *bsp, raystream_occlusion_t &rs, const std:
Q_assert(!std::isnan(indirect[0])); Q_assert(!std::isnan(indirect[0]));
result += indirect; result.add(indirect, vpl.style);
} }
} }
} }
@ -2267,7 +2261,7 @@ inline void LightFace_ScaleAndClamp(lightsurf_t *lightsurf)
* Same as above LightFace_ScaleAndClamp, but for lightgrid * Same as above LightFace_ScaleAndClamp, but for lightgrid
* TODO: share code with above * TODO: share code with above
*/ */
inline void LightPoint_ScaleAndClamp(qvec3d &color) static void LightPoint_ScaleAndClamp(qvec3d &color)
{ {
const settings::worldspawn_keys &cfg = light_options; const settings::worldspawn_keys &cfg = light_options;
@ -2303,6 +2297,15 @@ inline void LightPoint_ScaleAndClamp(qvec3d &color)
} }
} }
static void LightPoint_ScaleAndClamp(lightgrid_samples_t &result)
{
for (auto &sample : result.samples_by_style) {
if (sample.used) {
LightPoint_ScaleAndClamp(sample.color);
}
}
}
void FinishLightmapSurface(const mbsp_t *bsp, lightsurf_t *lightsurf) void FinishLightmapSurface(const mbsp_t *bsp, lightsurf_t *lightsurf)
{ {
/* Apply gamma, rangescale, and clamp */ /* Apply gamma, rangescale, and clamp */
@ -3244,7 +3247,56 @@ void IndirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings
// lightgrid // lightgrid
qvec3d CalcLightgridAtPoint(const mbsp_t *bsp, const qvec3d &world_point) void lightgrid_samples_t::add(const qvec3d &color, int style)
{
for (auto &sample : samples_by_style) {
if (!sample.used) {
// allocate new style
sample.used = true;
sample.style = style;
sample.color = color;
return;
}
if (sample.style == style) {
// found matching style
sample.color += color;
return;
}
}
// uncommon case: all slots are used, but we didn't find a matching style
// drop the style with the lowest brightness
// FIXME: pick lowest brightness
logging::print("out of lightstyles\n");
samples_by_style[0].style = style;
samples_by_style[0].color = color;
}
qvec3b lightgrid_sample_t::round_to_int() const
{
return qvec3b{
clamp((int)round(color[0]), 0, 255),
clamp((int)round(color[1]), 0, 255),
clamp((int)round(color[2]), 0, 255)
};
}
int lightgrid_samples_t::used_styles() const
{
int used = 0;
for (auto &sample : samples_by_style) {
if (sample.used) {
used++;
} else {
break;
}
}
return used;
}
lightgrid_samples_t CalcLightgridAtPoint(const mbsp_t *bsp, const qvec3d &world_point)
{ {
// TODO: use more than 1 ray for better performance // TODO: use more than 1 ray for better performance
raystream_occlusion_t rs(1); raystream_occlusion_t rs(1);
@ -3252,7 +3304,7 @@ qvec3d CalcLightgridAtPoint(const mbsp_t *bsp, const qvec3d &world_point)
auto &cfg = light_options; auto &cfg = light_options;
qvec3d result {0, 0, 0}; lightgrid_samples_t result;
// from DirectLightFace // from DirectLightFace