Revert "Revert "reduce memory usage by only storing VPLs when we need to, and only once""
This reverts commit 2e0e23622b.
Disable rescale by default on sky faces.
Light is now in control of rescales' default value.
Multiply omni light faces by 0.5 to better match qrad3
Remove some asserts to increase perf
This commit is contained in:
parent
1262ce3f78
commit
7d881768fa
|
|
@ -152,7 +152,7 @@ struct surfflags_t
|
|||
|
||||
// if true, rescales any surface light emitted by these brushes to emit 50% light at 90 degrees from the surface
|
||||
// normal if false, use a more natural angle falloff of 0% at 90 degrees
|
||||
bool surflight_rescale = true;
|
||||
std::optional<bool> surflight_rescale;
|
||||
|
||||
// override surface lighting style
|
||||
std::optional<int32_t> surflight_style;
|
||||
|
|
|
|||
|
|
@ -29,5 +29,4 @@ struct mbsp_t;
|
|||
// public functions
|
||||
|
||||
void ResetBounce();
|
||||
const std::vector<struct surfacelight_t> &BounceLights();
|
||||
void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp);
|
||||
|
|
|
|||
|
|
@ -143,6 +143,9 @@ struct lightsurf_t
|
|||
std::unique_ptr<raystream_intersection_t> intersection_stream;
|
||||
|
||||
lightmapdict_t lightmapsByStyle;
|
||||
|
||||
// surface light stuff
|
||||
std::unique_ptr<surfacelight_t> vpl;
|
||||
};
|
||||
|
||||
/* debug */
|
||||
|
|
|
|||
|
|
@ -39,33 +39,40 @@ struct surfacelight_t
|
|||
{
|
||||
qvec3d pos;
|
||||
qvec3f surfnormal;
|
||||
/**
|
||||
* disables use of the surfnormal. We set this to true on sky surface lights,
|
||||
* to avoid black seams on geometry meeting the sky
|
||||
*/
|
||||
bool omnidirectional;
|
||||
std::vector<qvec3f> points;
|
||||
std::vector<const mleaf_t *> leaves;
|
||||
|
||||
// Surface light settings...
|
||||
float intensity; // Surface light strength for each point
|
||||
float totalintensity; // Total surface light strength
|
||||
qvec3d color; // Surface color
|
||||
size_t points_before_culling;
|
||||
|
||||
// Estimated visible AABB culling
|
||||
aabb3d bounds;
|
||||
|
||||
int32_t style;
|
||||
|
||||
// rescale faces to account for perpendicular lights
|
||||
bool rescale;
|
||||
std::optional<vec_t> minlight_scale;
|
||||
|
||||
std::vector<qvec3f> points;
|
||||
std::vector<const mleaf_t *> leaves;
|
||||
|
||||
// Surface light settings...
|
||||
struct per_style_t
|
||||
{
|
||||
bool bounce = false; // whether this is a direct or indirect emission
|
||||
/**
|
||||
* disables use of the surfnormal. We set this to true on sky surface lights,
|
||||
* to avoid black seams on geometry meeting the sky
|
||||
*/
|
||||
bool omnidirectional = false;
|
||||
// rescale faces to account for perpendicular lights
|
||||
bool rescale = false;
|
||||
int32_t style = 0; // style ID
|
||||
float intensity = 0; // Surface light strength for each point
|
||||
float totalintensity = 0; // Total surface light strength
|
||||
qvec3d color; // Surface color
|
||||
};
|
||||
|
||||
// Light data per style
|
||||
std::vector<per_style_t> styles;
|
||||
};
|
||||
|
||||
class light_t;
|
||||
|
||||
void ResetSurflight();
|
||||
std::vector<surfacelight_t> &GetSurfaceLights();
|
||||
size_t GetSurflightPoints();
|
||||
std::optional<std::tuple<int32_t, int32_t, qvec3d, light_t *>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face);
|
||||
const std::vector<int> &SurfaceLightsForFaceNum(int facenum);
|
||||
|
|
|
|||
|
|
@ -39,13 +39,10 @@
|
|||
#include <common/qvec.hh>
|
||||
#include <common/parallel.hh>
|
||||
|
||||
std::mutex bouncelights_lock;
|
||||
static std::vector<surfacelight_t> bouncelights;
|
||||
static std::atomic_size_t bouncelightpoints;
|
||||
|
||||
void ResetBounce()
|
||||
{
|
||||
bouncelights.clear();
|
||||
bouncelightpoints = 0;
|
||||
}
|
||||
|
||||
|
|
@ -88,16 +85,14 @@ static bool Face_ShouldBounce(const mbsp_t *bsp, const mface_t *face)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void MakeBounceLight(const mbsp_t *bsp, const settings::worldspawn_keys &cfg, const mface_t *face,
|
||||
qvec3d texture_color, int32_t style, const std::vector<qvec3f> &points, const polylib::winding_t &winding,
|
||||
static void MakeBounceLight(const mbsp_t *bsp, const settings::worldspawn_keys &cfg, lightsurf_t &surf,
|
||||
qvec3d texture_color, int32_t style, std::vector<qvec3f> &points,
|
||||
const vec_t &area, const qvec3d &facenormal, const qvec3d &facemidpoint)
|
||||
{
|
||||
if (!Face_IsEmissive(bsp, face)) {
|
||||
if (!Face_IsEmissive(bsp, surf.face)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bouncelightpoints += points.size();
|
||||
|
||||
// Calculate emit color and intensity...
|
||||
|
||||
// Calculate intensity...
|
||||
|
|
@ -107,50 +102,48 @@ static void MakeBounceLight(const mbsp_t *bsp, const settings::worldspawn_keys &
|
|||
return;
|
||||
}
|
||||
|
||||
// Normalize color...
|
||||
if (intensity > 1.0) {
|
||||
texture_color *= 1.0 / intensity;
|
||||
}
|
||||
// Normalize color...
|
||||
if (intensity > 1.0) {
|
||||
texture_color *= 1.0 / intensity;
|
||||
}
|
||||
|
||||
if (!surf.vpl) {
|
||||
auto &l = surf.vpl = std::make_unique<surfacelight_t>();
|
||||
|
||||
// Sanity checks...
|
||||
Q_assert(!points.empty());
|
||||
|
||||
// Add surfacelight...
|
||||
surfacelight_t l;
|
||||
l.surfnormal = facenormal;
|
||||
l.omnidirectional = false;
|
||||
l.points = points;
|
||||
l.style = style;
|
||||
l->surfnormal = facenormal;
|
||||
l->points = std::move(points);
|
||||
|
||||
// Init bbox...
|
||||
if (light_options.visapprox.value() == visapprox_t::RAYS) {
|
||||
l.bounds = EstimateVisibleBoundsAtPoint(facemidpoint);
|
||||
l->bounds = EstimateVisibleBoundsAtPoint(facemidpoint);
|
||||
}
|
||||
|
||||
for (auto &pt : l.points) {
|
||||
for (auto &pt : l->points) {
|
||||
if (light_options.visapprox.value() == visapprox_t::VIS) {
|
||||
l.leaves.push_back(Light_PointInLeaf(bsp, pt));
|
||||
l->leaves.push_back(Light_PointInLeaf(bsp, pt));
|
||||
} else if (light_options.visapprox.value() == visapprox_t::RAYS) {
|
||||
l.bounds += EstimateVisibleBoundsAtPoint(pt);
|
||||
l->bounds += EstimateVisibleBoundsAtPoint(pt);
|
||||
}
|
||||
}
|
||||
|
||||
l.pos = facemidpoint;
|
||||
l->pos = facemidpoint;
|
||||
}
|
||||
|
||||
// Store surfacelight settings...
|
||||
l.totalintensity = intensity * area;
|
||||
l.intensity = l.totalintensity / l.points.size();
|
||||
l.color = texture_color;
|
||||
|
||||
// Store light...
|
||||
std::unique_lock<std::mutex> lck{bouncelights_lock};
|
||||
bouncelights.push_back(l);
|
||||
}
|
||||
|
||||
const std::vector<surfacelight_t> &BounceLights()
|
||||
{
|
||||
return bouncelights;
|
||||
auto &l = surf.vpl;
|
||||
auto &setting = l->styles.emplace_back();
|
||||
setting.bounce = true;
|
||||
setting.style = style;
|
||||
setting.totalintensity = intensity * area;
|
||||
setting.intensity = setting.totalintensity / l->points.size();
|
||||
setting.color = texture_color;
|
||||
}
|
||||
}
|
||||
|
||||
static void MakeBounceLightsThread(const settings::worldspawn_keys &cfg, const mbsp_t *bsp, const mface_t &face)
|
||||
{
|
||||
|
|
@ -245,8 +238,7 @@ static void MakeBounceLightsThread(const settings::worldspawn_keys &cfg, const m
|
|||
}
|
||||
|
||||
for (auto &style : emitcolors) {
|
||||
MakeBounceLight(
|
||||
bsp, cfg, &face, style.second, style.first, points, winding, area, facenormal, facemidpoint);
|
||||
MakeBounceLight(bsp, cfg, surf, style.second, style.first, points, area, facenormal, facemidpoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -256,5 +248,5 @@ void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
|||
|
||||
logging::parallel_for_each(bsp->dfaces, [&](const mface_t &face) { MakeBounceLightsThread(cfg, bsp, face); });
|
||||
|
||||
logging::print("{} bounce lights created, with {} points\n", bouncelights.size(), bouncelightpoints);
|
||||
// logging::print("{} bounce lights created, with {} points\n", bouncelights.size(), bouncelightpoints);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -745,11 +745,15 @@ static void SaveLightmapSurfaces(mbsp_t *bsp)
|
|||
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);
|
||||
}
|
||||
|
||||
light_surfaces[i].reset();
|
||||
});
|
||||
}
|
||||
|
||||
void ClearLightmapSurfaces(mbsp_t *bsp)
|
||||
{
|
||||
logging::funcheader();
|
||||
logging::parallel_for(static_cast<size_t>(0), bsp->dfaces.size(), [&bsp](size_t i) { light_surfaces[i].reset(); });
|
||||
}
|
||||
|
||||
static void FindModelInfo(const mbsp_t *bsp)
|
||||
{
|
||||
Q_assert(modelinfo.size() == 0);
|
||||
|
|
@ -1595,6 +1599,8 @@ int light_main(int argc, const char **argv)
|
|||
|
||||
LightGrid(&bspdata);
|
||||
|
||||
ClearLightmapSurfaces(&std::get<mbsp_t>(bspdata.bsp));
|
||||
|
||||
// invalidate normals
|
||||
bspdata.bspx.entries.erase("FACENORMALS");
|
||||
|
||||
|
|
|
|||
138
light/ltface.cc
138
light/ltface.cc
|
|
@ -26,7 +26,6 @@
|
|||
#include <light/entities.hh>
|
||||
#include <light/lightgrid.hh>
|
||||
#include <light/trace.hh>
|
||||
#include <light/bounce.hh>
|
||||
#include <light/litfile.hh> // for facesup_t
|
||||
|
||||
#include <common/imglib.hh>
|
||||
|
|
@ -1018,13 +1017,22 @@ constexpr vec_t SQR(vec_t x)
|
|||
}
|
||||
|
||||
// CHECK: naming? why clamp*min*?
|
||||
constexpr void Light_ClampMin(lightsample_t &sample, const vec_t light, const qvec3d &color)
|
||||
constexpr bool Light_ClampMin(lightsample_t &sample, const vec_t light, const qvec3d &color)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
sample.color[i] = std::max(sample.color[i], (float)(color[i] * (light / 255.0f)));
|
||||
float c = (float)(color[i] * (light / 255.0f));
|
||||
|
||||
if (c > sample.color[i]) {
|
||||
sample.color[i] = c;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
constexpr vec_t fraction(const vec_t &min, const vec_t &val, const vec_t &max)
|
||||
{
|
||||
if (val >= max)
|
||||
|
|
@ -1668,14 +1676,13 @@ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d &
|
|||
}
|
||||
if (cfg.addminlight.value()) {
|
||||
sample.color += color * (value / 255.0);
|
||||
hit = true;
|
||||
} else {
|
||||
if (lightsurf->minlightMottle) {
|
||||
value += Mottle(surf_sample.point);
|
||||
}
|
||||
Light_ClampMin(sample, value, color);
|
||||
hit = Light_ClampMin(sample, value, color) || hit;
|
||||
}
|
||||
|
||||
hit = true;
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
|
|
@ -1751,11 +1758,11 @@ static void LightFace_LocalMin(
|
|||
cfg, lightsurf->samples[i].occlusion, entity.get(), 0.0 /* TODO: pass distance */, lightsurf);
|
||||
if (cfg.addminlight.value()) {
|
||||
sample.color += entity->color.value() * (value / 255.0);
|
||||
hit = true;
|
||||
} else {
|
||||
Light_ClampMin(sample, value, entity->color.value());
|
||||
hit = Light_ClampMin(sample, value, entity->color.value()) || hit;
|
||||
}
|
||||
|
||||
hit = true;
|
||||
total_light_ray_hits++;
|
||||
}
|
||||
|
||||
|
|
@ -1898,7 +1905,7 @@ static void LightFace_DebugMottle(const mbsp_t *bsp, const lightsurf_t *lightsur
|
|||
}
|
||||
|
||||
// mxd. Surface light falloff. Returns color in [0,255]
|
||||
inline qvec3f SurfaceLight_ColorAtDist(const settings::worldspawn_keys &cfg, const float &surf_scale,
|
||||
constexpr qvec3f SurfaceLight_ColorAtDist(const settings::worldspawn_keys &cfg, const float &surf_scale,
|
||||
const float &intensity, const qvec3d &color, const float &dist, const float &hotspot_clamp)
|
||||
{
|
||||
// Exponential falloff
|
||||
|
|
@ -1911,25 +1918,25 @@ inline qvec3f SurfaceLight_ColorAtDist(const settings::worldspawn_keys &cfg, con
|
|||
|
||||
// dir: vpl -> sample point direction
|
||||
// mxd. returns color in [0,255]
|
||||
inline qvec3f GetSurfaceLighting(const settings::worldspawn_keys &cfg, const surfacelight_t *vpl, const qvec3f &dir,
|
||||
const float dist, const qvec3f &normal, bool use_normal, const vec_t &standard_scale, const vec_t &sky_scale,
|
||||
const float &hotspot_clamp)
|
||||
inline qvec3f GetSurfaceLighting(const settings::worldspawn_keys &cfg, const surfacelight_t &vpl,
|
||||
const surfacelight_t::per_style_t &vpl_settings, const qvec3f &dir, const float dist, const qvec3f &normal,
|
||||
bool use_normal, const vec_t &standard_scale, const vec_t &sky_scale, const float &hotspot_clamp)
|
||||
{
|
||||
qvec3f result;
|
||||
float dotProductFactor = 1.0f;
|
||||
|
||||
float dp1 = qv::dot(vpl->surfnormal, dir);
|
||||
float dp1 = qv::dot(vpl.surfnormal, dir);
|
||||
const qvec3f sp_vpl = dir * -1.0f;
|
||||
float dp2 = use_normal ? qv::dot(sp_vpl, normal) : 1.0f;
|
||||
|
||||
if (!vpl->omnidirectional) {
|
||||
if (!vpl_settings.omnidirectional) {
|
||||
if (dp1 < -LIGHT_ANGLE_EPSILON)
|
||||
return {0}; // sample point behind vpl
|
||||
if (dp2 < -LIGHT_ANGLE_EPSILON)
|
||||
return {0}; // vpl behind sample face
|
||||
|
||||
// Rescale a bit to brighten the faces nearly-perpendicular to the surface light plane...
|
||||
if (vpl->rescale) {
|
||||
if (vpl_settings.rescale) {
|
||||
dp1 = 0.5f + dp1 * 0.5f;
|
||||
dp2 = 0.5f + dp2 * 0.5f;
|
||||
}
|
||||
|
|
@ -1937,25 +1944,25 @@ inline qvec3f GetSurfaceLighting(const settings::worldspawn_keys &cfg, const sur
|
|||
dotProductFactor = dp1 * dp2;
|
||||
} else {
|
||||
// used for sky face surface lights
|
||||
dotProductFactor = dp2;
|
||||
dotProductFactor = dp2 * 0.5f;
|
||||
}
|
||||
|
||||
dotProductFactor = std::max(0.0f, dotProductFactor);
|
||||
|
||||
// Get light contribution
|
||||
result = SurfaceLight_ColorAtDist(
|
||||
cfg, vpl->omnidirectional ? sky_scale : standard_scale, vpl->intensity, vpl->color, dist, hotspot_clamp);
|
||||
result = SurfaceLight_ColorAtDist(cfg, vpl_settings.omnidirectional ? sky_scale : standard_scale,
|
||||
vpl_settings.intensity, vpl_settings.color, dist, hotspot_clamp);
|
||||
|
||||
// Apply angle scale
|
||||
const qvec3f resultscaled = result * dotProductFactor;
|
||||
|
||||
Q_assert(!std::isnan(resultscaled[0]) && !std::isnan(resultscaled[1]) && !std::isnan(resultscaled[2]));
|
||||
//Q_assert(!std::isnan(resultscaled[0]) && !std::isnan(resultscaled[1]) && !std::isnan(resultscaled[2]));
|
||||
return resultscaled;
|
||||
}
|
||||
|
||||
static bool // mxd
|
||||
SurfaceLight_SphereCull(
|
||||
const surfacelight_t *vpl, const lightsurf_t *lightsurf, const vec_t &bouncelight_gate, const float &hotspot_clamp)
|
||||
SurfaceLight_SphereCull(const surfacelight_t *vpl, const lightsurf_t *lightsurf,
|
||||
const surfacelight_t::per_style_t &vpl_settings, const vec_t &bouncelight_gate, const float &hotspot_clamp)
|
||||
{
|
||||
if (light_options.visapprox.value() == visapprox_t::RAYS &&
|
||||
vpl->bounds.disjoint(lightsurf->extents.bounds, 0.001)) {
|
||||
|
|
@ -1967,17 +1974,16 @@ SurfaceLight_SphereCull(
|
|||
const float dist = qv::length(dir) + lightsurf->extents.radius;
|
||||
|
||||
// Get light contribution
|
||||
const qvec3f color =
|
||||
SurfaceLight_ColorAtDist(cfg, vpl->omnidirectional ? cfg.surflightskyscale.value() : cfg.surflightscale.value(),
|
||||
vpl->totalintensity, vpl->color, dist, hotspot_clamp);
|
||||
const qvec3f color = SurfaceLight_ColorAtDist(cfg,
|
||||
vpl_settings.omnidirectional ? cfg.surflightskyscale.value() : cfg.surflightscale.value(),
|
||||
vpl_settings.totalintensity, vpl_settings.color, dist, hotspot_clamp);
|
||||
|
||||
return qv::gate(color, (float)bouncelight_gate);
|
||||
}
|
||||
|
||||
static void // mxd
|
||||
LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t *lightmaps,
|
||||
const std::vector<surfacelight_t> &surface_lights, const vec_t &standard_scale, const vec_t &sky_scale,
|
||||
const float &hotspot_clamp)
|
||||
LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t *lightmaps, bool bounce,
|
||||
const vec_t &standard_scale, const vec_t &sky_scale, const float &hotspot_clamp)
|
||||
{
|
||||
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||
const float surflight_gate = 0.01f;
|
||||
|
|
@ -1987,9 +1993,21 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
|
|||
return;
|
||||
}
|
||||
|
||||
for (const surfacelight_t &vpl : surface_lights) {
|
||||
if (SurfaceLight_SphereCull(&vpl, lightsurf, surflight_gate, hotspot_clamp))
|
||||
for (const auto &surf_ptr : LightSurfaces()) {
|
||||
|
||||
if (!surf_ptr || !surf_ptr->vpl) {
|
||||
// didn't emit anthing
|
||||
continue;
|
||||
}
|
||||
|
||||
auto &vpl = *surf_ptr->vpl.get();
|
||||
|
||||
for (const auto &vpl_setting : surf_ptr->vpl->styles) {
|
||||
|
||||
if (vpl_setting.bounce != bounce)
|
||||
continue;
|
||||
else if (SurfaceLight_SphereCull(&vpl, lightsurf, vpl_setting, surflight_gate, hotspot_clamp))
|
||||
continue;
|
||||
|
||||
raystream_occlusion_t &rs = *lightsurf->occlusion_stream;
|
||||
|
||||
|
|
@ -2025,8 +2043,8 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
|
|||
dir /= dist;
|
||||
}
|
||||
|
||||
const qvec3f indirect = GetSurfaceLighting(
|
||||
cfg, &vpl, dir, dist, lightsurf_normal, use_normal, standard_scale, sky_scale, hotspot_clamp);
|
||||
const qvec3f indirect = GetSurfaceLighting(cfg, vpl, vpl_setting, dir, dist, lightsurf_normal,
|
||||
use_normal, standard_scale, sky_scale, hotspot_clamp);
|
||||
if (!qv::gate(indirect, surflight_gate)) { // Each point contributes very little to the final result
|
||||
rs.pushRay(i, pos, dir, dist, &indirect);
|
||||
}
|
||||
|
|
@ -2038,7 +2056,7 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
|
|||
total_surflight_rays += rs.numPushedRays();
|
||||
rs.tracePushedRaysOcclusion(lightsurf->modelinfo, CHANNEL_MASK_DEFAULT);
|
||||
|
||||
const int lightmapstyle = vpl.style;
|
||||
const int lightmapstyle = vpl_setting.style;
|
||||
lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, lightmapstyle, lightsurf);
|
||||
|
||||
bool hit = false;
|
||||
|
|
@ -2050,7 +2068,7 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
|
|||
const int i = rs.getPushedRayPointIndex(j);
|
||||
qvec3f indirect = rs.getPushedRayColor(j);
|
||||
|
||||
Q_assert(!std::isnan(indirect[0]));
|
||||
//Q_assert(!std::isnan(indirect[0]));
|
||||
|
||||
// Use dirt scaling on the surface lighting.
|
||||
const vec_t dirtscale =
|
||||
|
|
@ -2070,25 +2088,33 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void // mxd
|
||||
LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, 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, lightgrid_samples_t &result)
|
||||
LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, raystream_occlusion_t &rs, bool bounce,
|
||||
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 float surflight_gate = 0.01f;
|
||||
|
||||
for (const surfacelight_t &vpl : surface_lights) {
|
||||
for (const auto &surf : LightSurfaces()) {
|
||||
if (!surf || !surf->vpl) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const surfacelight_t &vpl = *surf->vpl;
|
||||
|
||||
for (int c = 0; c < vpl.points.size(); c++) {
|
||||
if (light_options.visapprox.value() == visapprox_t::VIS && pvs && VisCullEntity(bsp, *pvs, vpl.leaves[c])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rs.clearPushedRays();
|
||||
|
||||
// 1 ray
|
||||
{
|
||||
for (auto &vpl_settings : vpl.styles) {
|
||||
if (vpl_settings.bounce != bounce)
|
||||
continue;
|
||||
|
||||
qvec3f pos = vpl.points[c];
|
||||
qvec3f dir = surfpoint - pos;
|
||||
float dist = qv::length(dir);
|
||||
|
|
@ -2100,6 +2126,8 @@ LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, rays
|
|||
|
||||
qvec3f indirect{};
|
||||
|
||||
rs.clearPushedRays();
|
||||
|
||||
for (int axis = 0; axis < 3; ++axis) {
|
||||
for (int sign = -1; sign <= +1; sign += 2) {
|
||||
|
||||
|
|
@ -2108,8 +2136,8 @@ LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, rays
|
|||
qvec3f cube_normal{};
|
||||
cube_normal[axis] = sign;
|
||||
|
||||
cube_color = GetSurfaceLighting(
|
||||
cfg, &vpl, dir, dist, cube_normal, true, standard_scale, sky_scale, hotspot_clamp);
|
||||
cube_color = GetSurfaceLighting(cfg, vpl, vpl_settings, dir, dist, cube_normal, true,
|
||||
standard_scale, sky_scale, hotspot_clamp);
|
||||
|
||||
#ifdef LIGHTPOINT_TAKE_MAX
|
||||
if (qv::length2(cube_color) > qv::length2(indirect)) {
|
||||
|
|
@ -2124,7 +2152,6 @@ LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, rays
|
|||
if (!qv::gate(indirect, surflight_gate)) { // Each point contributes very little to the final result
|
||||
rs.pushRay(0, pos, dir, dist, &indirect);
|
||||
}
|
||||
}
|
||||
|
||||
if (!rs.numPushedRays())
|
||||
continue;
|
||||
|
|
@ -2138,13 +2165,14 @@ LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, rays
|
|||
|
||||
qvec3f indirect = rs.getPushedRayColor(j);
|
||||
|
||||
Q_assert(!std::isnan(indirect[0]));
|
||||
//Q_assert(!std::isnan(indirect[0]));
|
||||
|
||||
result.add(indirect, vpl.style);
|
||||
result.add(indirect, vpl_settings.style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LightFace_OccludedDebug(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t *lightmaps)
|
||||
{
|
||||
|
|
@ -3333,8 +3361,8 @@ void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::
|
|||
|
||||
// mxd. Add surface lights...
|
||||
// FIXME: negative surface lights
|
||||
LightFace_SurfaceLight(bsp, &lightsurf, lightmaps, GetSurfaceLights(), cfg.surflightscale.value(),
|
||||
cfg.surflightskyscale.value(), 16.0f);
|
||||
LightFace_SurfaceLight(
|
||||
bsp, &lightsurf, lightmaps, false, cfg.surflightscale.value(), cfg.surflightskyscale.value(), 16.0f);
|
||||
}
|
||||
|
||||
LightFace_LocalMin(bsp, face, &lightsurf, lightmaps);
|
||||
|
|
@ -3373,8 +3401,8 @@ void IndirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings
|
|||
|
||||
/* add bounce lighting */
|
||||
// note: scale here is just to keep it close-ish to the old code
|
||||
LightFace_SurfaceLight(bsp, &lightsurf, lightmaps, BounceLights(), cfg.bouncescale.value() * 0.5,
|
||||
cfg.bouncescale.value(), 128.0f);
|
||||
LightFace_SurfaceLight(
|
||||
bsp, &lightsurf, lightmaps, true, cfg.bouncescale.value() * 0.5, cfg.bouncescale.value(), 128.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3413,9 +3441,10 @@ void PostProcessLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const setti
|
|||
LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps, 0);
|
||||
}
|
||||
|
||||
if (lightsurf.vpl) {
|
||||
if (auto value = IsSurfaceLitFace(bsp, face)) {
|
||||
auto *entity = std::get<3>(value.value());
|
||||
float surface_minlight_scale = entity ? entity->surflight_minlight_scale.value() : 64.f;
|
||||
float surface_minlight_scale = entity ? entity->surflight_minlight_scale.value() : 1.f;
|
||||
surface_minlight_scale *= lightsurf.surflight_minlight_scale;
|
||||
|
||||
if (surface_minlight_scale > 0) {
|
||||
|
|
@ -3425,6 +3454,7 @@ void PostProcessLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const setti
|
|||
bsp, face, minlight_color, minlight, &lightsurf, lightmaps, std::get<1>(value.value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!modelinfo->isWorld()) {
|
||||
LightFace_AutoMin(bsp, face, &lightsurf, lightmaps);
|
||||
|
|
@ -3581,8 +3611,8 @@ lightgrid_samples_t CalcLightgridAtPoint(const mbsp_t *bsp, const qvec3d &world_
|
|||
|
||||
// mxd. Add surface lights...
|
||||
// FIXME: negative surface lights
|
||||
LightPoint_SurfaceLight(bsp, pvs, rs, GetSurfaceLights(), cfg.surflightscale.value(), cfg.surflightskyscale.value(),
|
||||
16.0f, world_point, result);
|
||||
LightPoint_SurfaceLight(
|
||||
bsp, pvs, rs, false, cfg.surflightscale.value(), cfg.surflightskyscale.value(), 16.0f, world_point, result);
|
||||
|
||||
#if 0
|
||||
// FIXME: port to lightgrid
|
||||
|
|
@ -3613,8 +3643,8 @@ lightgrid_samples_t CalcLightgridAtPoint(const mbsp_t *bsp, const qvec3d &world_
|
|||
|
||||
/* add bounce lighting */
|
||||
// note: scale here is just to keep it close-ish to the old code
|
||||
LightPoint_SurfaceLight(bsp, pvs, rs, BounceLights(), cfg.bouncescale.value() * 0.5, cfg.bouncescale.value(),
|
||||
128.0f, world_point, result);
|
||||
LightPoint_SurfaceLight(
|
||||
bsp, pvs, rs, true, cfg.bouncescale.value() * 0.5, cfg.bouncescale.value(), 128.0f, world_point, result);
|
||||
|
||||
LightPoint_ScaleAndClamp(result);
|
||||
|
||||
|
|
|
|||
|
|
@ -37,23 +37,13 @@ See file, 'COPYING', for details.
|
|||
|
||||
#include <common/qvec.hh>
|
||||
|
||||
static std::mutex surfacelights_lock;
|
||||
static std::vector<surfacelight_t> surfacelights;
|
||||
static std::map<int, std::vector<int>> surfacelightsByFacenum;
|
||||
static size_t total_surflight_points = 0;
|
||||
static std::atomic_size_t total_surflight_points;
|
||||
|
||||
void ResetSurflight()
|
||||
{
|
||||
surfacelights = {};
|
||||
surfacelightsByFacenum = {};
|
||||
total_surflight_points = {};
|
||||
}
|
||||
|
||||
std::vector<surfacelight_t> &GetSurfaceLights()
|
||||
{
|
||||
return surfacelights;
|
||||
}
|
||||
|
||||
size_t GetSurflightPoints()
|
||||
{
|
||||
return total_surflight_points;
|
||||
|
|
@ -64,6 +54,14 @@ 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,
|
||||
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 (!surf_ptr || !Face_IsEmissive(bsp, face)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &surf = *surf_ptr.get();
|
||||
|
||||
// Create face points...
|
||||
auto poly = Face_Points(bsp, face);
|
||||
const float facearea = qv::PolyArea(poly.begin(), poly.end());
|
||||
|
|
@ -74,38 +72,6 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys
|
|||
if (facearea < 1)
|
||||
return;
|
||||
|
||||
// Create winding...
|
||||
polylib::winding_t winding = polylib::winding_t::from_winding_points(poly);
|
||||
auto face_modelinfo = ModelInfoForFace(bsp, face - bsp->dfaces.data());
|
||||
|
||||
for (auto &pt : winding) {
|
||||
pt += face_modelinfo->offset;
|
||||
}
|
||||
|
||||
winding.remove_colinear();
|
||||
|
||||
// Get face normal and midpoint...
|
||||
qvec3d facenormal = Face_Normal(bsp, face);
|
||||
qvec3d facemidpoint = winding.center() + facenormal; // Lift 1 unit
|
||||
|
||||
// Dice winding...
|
||||
std::vector<qvec3f> points;
|
||||
size_t points_before_culling = 0;
|
||||
winding.dice(cfg.surflightsubdivision.value(), [&](polylib::winding_t &w) {
|
||||
++points_before_culling;
|
||||
|
||||
qvec3f point = w.center() + facenormal;
|
||||
|
||||
// optimization - cull surface lights in the void
|
||||
// also try to move them if they're slightly inside a wall
|
||||
auto [fixed_point, success] = FixLightOnFace(bsp, point, false, 0.5f);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
points.push_back(fixed_point);
|
||||
});
|
||||
|
||||
// Calculate emit color and intensity...
|
||||
|
||||
if (extended_flags.surflight_color.has_value()) {
|
||||
|
|
@ -137,52 +103,113 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys
|
|||
if (intensity > 1.0f)
|
||||
texture_color.value() *= 1.0f / intensity;
|
||||
|
||||
// Sanity checks...
|
||||
if (points.empty())
|
||||
return;
|
||||
if (!surf.vpl) {
|
||||
auto &l = surf.vpl = std::make_unique<surfacelight_t>();
|
||||
|
||||
// Add surfacelight...
|
||||
surfacelight_t l;
|
||||
l.surfnormal = facenormal;
|
||||
l.omnidirectional = !is_directional;
|
||||
l.points = std::move(points);
|
||||
if (extended_flags.surflight_targetname) {
|
||||
l.style = LightStyleForTargetname(cfg, extended_flags.surflight_targetname.value());
|
||||
} else if (extended_flags.surflight_style) {
|
||||
l.style = extended_flags.surflight_style.value();
|
||||
} else {
|
||||
l.style = style;
|
||||
// Create winding...
|
||||
auto winding = polylib::winding_t::from_winding_points(poly);
|
||||
auto face_modelinfo = ModelInfoForFace(bsp, face - bsp->dfaces.data());
|
||||
|
||||
for (auto &pt : winding) {
|
||||
pt += face_modelinfo->offset;
|
||||
}
|
||||
l.rescale = extended_flags.surflight_rescale;
|
||||
l.minlight_scale = extended_flags.surflight_minlight_scale;
|
||||
|
||||
winding.remove_colinear();
|
||||
|
||||
// Get face normal and midpoint...
|
||||
l->surfnormal = Face_Normal(bsp, face);
|
||||
l->pos = winding.center() + l->surfnormal; // Lift 1 unit
|
||||
|
||||
// Dice winding...
|
||||
l->points_before_culling = 0;
|
||||
|
||||
if (light_options.emissivequality.value() == emissivequality_t::LOW ||
|
||||
light_options.emissivequality.value() == emissivequality_t::MEDIUM) {
|
||||
l->points = {l->pos};
|
||||
l->points_before_culling++;
|
||||
total_surflight_points++;
|
||||
|
||||
if (light_options.emissivequality.value() == emissivequality_t::MEDIUM) {
|
||||
|
||||
for (auto &pt : winding) {
|
||||
l->points_before_culling++;
|
||||
auto point = pt + l->surfnormal;
|
||||
auto diff = qv::normalize(l->pos - pt);
|
||||
|
||||
point += diff;
|
||||
|
||||
// optimization - cull surface lights in the void
|
||||
// also try to move them if they're slightly inside a wall
|
||||
auto [fixed_point, success] = FixLightOnFace(bsp, point, false, 0.5f);
|
||||
if (!success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
l->points.push_back(fixed_point);
|
||||
total_surflight_points++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
winding.dice(cfg.surflightsubdivision.value(), [&](polylib::winding_t &w) {
|
||||
++l->points_before_culling;
|
||||
|
||||
qvec3f point = w.center() + l->surfnormal;
|
||||
|
||||
// optimization - cull surface lights in the void
|
||||
// also try to move them if they're slightly inside a wall
|
||||
auto [fixed_point, success] = FixLightOnFace(bsp, point, false, 0.5f);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
l->points.push_back(fixed_point);
|
||||
++total_surflight_points;
|
||||
});
|
||||
}
|
||||
|
||||
l->minlight_scale = extended_flags.surflight_minlight_scale;
|
||||
|
||||
// Init bbox...
|
||||
if (light_options.visapprox.value() == visapprox_t::RAYS) {
|
||||
l.bounds = EstimateVisibleBoundsAtPoint(facemidpoint);
|
||||
l->bounds = EstimateVisibleBoundsAtPoint(l->pos);
|
||||
}
|
||||
|
||||
for (auto &pt : l.points) {
|
||||
for (auto &pt : l->points) {
|
||||
if (light_options.visapprox.value() == visapprox_t::VIS) {
|
||||
l.leaves.push_back(Light_PointInLeaf(bsp, pt));
|
||||
l->leaves.push_back(Light_PointInLeaf(bsp, pt));
|
||||
} else if (light_options.visapprox.value() == visapprox_t::RAYS) {
|
||||
l.bounds += EstimateVisibleBoundsAtPoint(pt);
|
||||
l->bounds += EstimateVisibleBoundsAtPoint(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
l.pos = facemidpoint;
|
||||
auto &l = surf.vpl;
|
||||
|
||||
// Sanity checks...
|
||||
if (l->points.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add surfacelight...
|
||||
auto &setting = l->styles.emplace_back();
|
||||
setting.omnidirectional = !is_directional;
|
||||
if (extended_flags.surflight_targetname) {
|
||||
setting.style = LightStyleForTargetname(cfg, extended_flags.surflight_targetname.value());
|
||||
} else if (extended_flags.surflight_style) {
|
||||
setting.style = extended_flags.surflight_style.value();
|
||||
} else {
|
||||
setting.style = style;
|
||||
}
|
||||
if (extended_flags.surflight_rescale) {
|
||||
setting.rescale = extended_flags.surflight_rescale.value();
|
||||
} else {
|
||||
setting.rescale = is_sky ? false : true;
|
||||
}
|
||||
|
||||
// Store surfacelight settings...
|
||||
l.totalintensity = intensity * facearea;
|
||||
l.intensity = l.totalintensity / points_before_culling;
|
||||
l.color = texture_color.value();
|
||||
|
||||
// Store light...
|
||||
std::unique_lock<std::mutex> lck{surfacelights_lock};
|
||||
total_surflight_points += l.points.size();
|
||||
surfacelights.push_back(l);
|
||||
|
||||
const int index = static_cast<int>(surfacelights.size()) - 1;
|
||||
surfacelightsByFacenum[Face_GetNum(bsp, face)].push_back(index);
|
||||
setting.totalintensity = intensity * facearea;
|
||||
setting.intensity = setting.totalintensity / l->points_before_culling;
|
||||
setting.color = texture_color.value();
|
||||
}
|
||||
|
||||
std::optional<std::tuple<int32_t, int32_t, qvec3d, light_t *>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face)
|
||||
|
|
@ -251,17 +278,6 @@ static void MakeSurfaceLightsThread(const mbsp_t *bsp, const settings::worldspaw
|
|||
}
|
||||
}
|
||||
|
||||
// No surflight_debug (yet?), so unused...
|
||||
const std::vector<int> &SurfaceLightsForFaceNum(int facenum)
|
||||
{
|
||||
const auto &vec = surfacelightsByFacenum.find(facenum);
|
||||
if (vec != surfacelightsByFacenum.end())
|
||||
return vec->second;
|
||||
|
||||
static std::vector<int> empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
void // Quake 2 surface lights
|
||||
MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
||||
{
|
||||
|
|
@ -270,7 +286,7 @@ MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *b
|
|||
logging::parallel_for(
|
||||
static_cast<size_t>(0), bsp->dfaces.size(), [&](size_t i) { MakeSurfaceLightsThread(bsp, cfg, i); });
|
||||
|
||||
if (surfacelights.size()) {
|
||||
/*if (surfacelights.size()) {
|
||||
logging::print("{} surface lights ({} light points) in use.\n", surfacelights.size(), total_surflight_points);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -678,8 +678,9 @@ static surfflags_t SurfFlagsForEntity(
|
|||
flags.no_minlight = true;
|
||||
if (entity.epairs.get_int("_lightignore") == 1)
|
||||
flags.light_ignore = true;
|
||||
if (entity.epairs.has("_surflight_rescale") && entity.epairs.get_int("_surflight_rescale") == 0)
|
||||
flags.surflight_rescale = false;
|
||||
if (entity.epairs.has("_surflight_rescale")) {
|
||||
flags.surflight_rescale = entity.epairs.get_int("_surflight_rescale") == 1;
|
||||
}
|
||||
{
|
||||
qvec3d color;
|
||||
// FIXME: get_color, to match settings
|
||||
|
|
|
|||
|
|
@ -381,8 +381,8 @@ static void WriteExtendedTexinfoFlags(void)
|
|||
if (tx.flags.light_ignore) {
|
||||
t["light_ignore"] = tx.flags.light_ignore;
|
||||
}
|
||||
if (tx.flags.surflight_rescale == false) {
|
||||
t["surflight_rescale"] = tx.flags.surflight_rescale;
|
||||
if (tx.flags.surflight_rescale) {
|
||||
t["surflight_rescale"] = tx.flags.surflight_rescale.value();
|
||||
}
|
||||
if (tx.flags.surflight_style.has_value()) {
|
||||
t["surflight_style"] = tx.flags.surflight_style.value();
|
||||
|
|
|
|||
Loading…
Reference in New Issue