light: write styles into the experimental lightgrid lump
This commit is contained in:
parent
89fa416708
commit
2cc513848b
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue