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
|
// 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
|
// 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
|
// override surface lighting style
|
||||||
std::optional<int32_t> surflight_style;
|
std::optional<int32_t> surflight_style;
|
||||||
|
|
|
||||||
|
|
@ -29,5 +29,4 @@ struct mbsp_t;
|
||||||
// public functions
|
// public functions
|
||||||
|
|
||||||
void ResetBounce();
|
void ResetBounce();
|
||||||
const std::vector<struct surfacelight_t> &BounceLights();
|
|
||||||
void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp);
|
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;
|
std::unique_ptr<raystream_intersection_t> intersection_stream;
|
||||||
|
|
||||||
lightmapdict_t lightmapsByStyle;
|
lightmapdict_t lightmapsByStyle;
|
||||||
|
|
||||||
|
// surface light stuff
|
||||||
|
std::unique_ptr<surfacelight_t> vpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* debug */
|
/* debug */
|
||||||
|
|
|
||||||
|
|
@ -39,33 +39,40 @@ struct surfacelight_t
|
||||||
{
|
{
|
||||||
qvec3d pos;
|
qvec3d pos;
|
||||||
qvec3f surfnormal;
|
qvec3f surfnormal;
|
||||||
/**
|
size_t points_before_culling;
|
||||||
* 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
|
|
||||||
|
|
||||||
// Estimated visible AABB culling
|
// Estimated visible AABB culling
|
||||||
aabb3d bounds;
|
aabb3d bounds;
|
||||||
|
|
||||||
int32_t style;
|
|
||||||
|
|
||||||
// rescale faces to account for perpendicular lights
|
|
||||||
bool rescale;
|
|
||||||
std::optional<vec_t> minlight_scale;
|
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;
|
class light_t;
|
||||||
|
|
||||||
void ResetSurflight();
|
void ResetSurflight();
|
||||||
std::vector<surfacelight_t> &GetSurfaceLights();
|
|
||||||
size_t GetSurflightPoints();
|
size_t GetSurflightPoints();
|
||||||
std::optional<std::tuple<int32_t, int32_t, qvec3d, light_t *>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face);
|
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);
|
const std::vector<int> &SurfaceLightsForFaceNum(int facenum);
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,10 @@
|
||||||
#include <common/qvec.hh>
|
#include <common/qvec.hh>
|
||||||
#include <common/parallel.hh>
|
#include <common/parallel.hh>
|
||||||
|
|
||||||
std::mutex bouncelights_lock;
|
|
||||||
static std::vector<surfacelight_t> bouncelights;
|
|
||||||
static std::atomic_size_t bouncelightpoints;
|
static std::atomic_size_t bouncelightpoints;
|
||||||
|
|
||||||
void ResetBounce()
|
void ResetBounce()
|
||||||
{
|
{
|
||||||
bouncelights.clear();
|
|
||||||
bouncelightpoints = 0;
|
bouncelightpoints = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,16 +85,14 @@ static bool Face_ShouldBounce(const mbsp_t *bsp, const mface_t *face)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MakeBounceLight(const mbsp_t *bsp, const settings::worldspawn_keys &cfg, const mface_t *face,
|
static void MakeBounceLight(const mbsp_t *bsp, const settings::worldspawn_keys &cfg, lightsurf_t &surf,
|
||||||
qvec3d texture_color, int32_t style, const std::vector<qvec3f> &points, const polylib::winding_t &winding,
|
qvec3d texture_color, int32_t style, std::vector<qvec3f> &points,
|
||||||
const vec_t &area, const qvec3d &facenormal, const qvec3d &facemidpoint)
|
const vec_t &area, const qvec3d &facenormal, const qvec3d &facemidpoint)
|
||||||
{
|
{
|
||||||
if (!Face_IsEmissive(bsp, face)) {
|
if (!Face_IsEmissive(bsp, surf.face)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bouncelightpoints += points.size();
|
|
||||||
|
|
||||||
// Calculate emit color and intensity...
|
// Calculate emit color and intensity...
|
||||||
|
|
||||||
// Calculate intensity...
|
// Calculate intensity...
|
||||||
|
|
@ -107,50 +102,48 @@ static void MakeBounceLight(const mbsp_t *bsp, const settings::worldspawn_keys &
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize color...
|
// Normalize color...
|
||||||
if (intensity > 1.0) {
|
if (intensity > 1.0) {
|
||||||
texture_color *= 1.0 / intensity;
|
texture_color *= 1.0 / intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!surf.vpl) {
|
||||||
|
auto &l = surf.vpl = std::make_unique<surfacelight_t>();
|
||||||
|
|
||||||
// Sanity checks...
|
// Sanity checks...
|
||||||
Q_assert(!points.empty());
|
Q_assert(!points.empty());
|
||||||
|
|
||||||
// Add surfacelight...
|
// Add surfacelight...
|
||||||
surfacelight_t l;
|
l->surfnormal = facenormal;
|
||||||
l.surfnormal = facenormal;
|
l->points = std::move(points);
|
||||||
l.omnidirectional = false;
|
|
||||||
l.points = points;
|
|
||||||
l.style = style;
|
|
||||||
|
|
||||||
// Init bbox...
|
// Init bbox...
|
||||||
if (light_options.visapprox.value() == visapprox_t::RAYS) {
|
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) {
|
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) {
|
} 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...
|
// 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)
|
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) {
|
for (auto &style : emitcolors) {
|
||||||
MakeBounceLight(
|
MakeBounceLight(bsp, cfg, surf, style.second, style.first, points, area, facenormal, facemidpoint);
|
||||||
bsp, cfg, &face, style.second, style.first, points, winding, 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::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, nullptr, nullptr, surf.get(), surf->extents, surf->vanilla_extents);
|
||||||
SaveLightmapSurface(bsp, f, &faces_sup[i], nullptr, surf.get(), surf->extents, surf->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)
|
static void FindModelInfo(const mbsp_t *bsp)
|
||||||
{
|
{
|
||||||
Q_assert(modelinfo.size() == 0);
|
Q_assert(modelinfo.size() == 0);
|
||||||
|
|
@ -1595,6 +1599,8 @@ int light_main(int argc, const char **argv)
|
||||||
|
|
||||||
LightGrid(&bspdata);
|
LightGrid(&bspdata);
|
||||||
|
|
||||||
|
ClearLightmapSurfaces(&std::get<mbsp_t>(bspdata.bsp));
|
||||||
|
|
||||||
// invalidate normals
|
// invalidate normals
|
||||||
bspdata.bspx.entries.erase("FACENORMALS");
|
bspdata.bspx.entries.erase("FACENORMALS");
|
||||||
|
|
||||||
|
|
|
||||||
138
light/ltface.cc
138
light/ltface.cc
|
|
@ -26,7 +26,6 @@
|
||||||
#include <light/entities.hh>
|
#include <light/entities.hh>
|
||||||
#include <light/lightgrid.hh>
|
#include <light/lightgrid.hh>
|
||||||
#include <light/trace.hh>
|
#include <light/trace.hh>
|
||||||
#include <light/bounce.hh>
|
|
||||||
#include <light/litfile.hh> // for facesup_t
|
#include <light/litfile.hh> // for facesup_t
|
||||||
|
|
||||||
#include <common/imglib.hh>
|
#include <common/imglib.hh>
|
||||||
|
|
@ -1018,13 +1017,22 @@ constexpr vec_t SQR(vec_t x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: naming? why clamp*min*?
|
// 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++) {
|
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)
|
constexpr vec_t fraction(const vec_t &min, const vec_t &val, const vec_t &max)
|
||||||
{
|
{
|
||||||
if (val >= 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()) {
|
if (cfg.addminlight.value()) {
|
||||||
sample.color += color * (value / 255.0);
|
sample.color += color * (value / 255.0);
|
||||||
|
hit = true;
|
||||||
} else {
|
} else {
|
||||||
if (lightsurf->minlightMottle) {
|
if (lightsurf->minlightMottle) {
|
||||||
value += Mottle(surf_sample.point);
|
value += Mottle(surf_sample.point);
|
||||||
}
|
}
|
||||||
Light_ClampMin(sample, value, color);
|
hit = Light_ClampMin(sample, value, color) || hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
hit = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hit) {
|
if (hit) {
|
||||||
|
|
@ -1751,11 +1758,11 @@ static void LightFace_LocalMin(
|
||||||
cfg, lightsurf->samples[i].occlusion, entity.get(), 0.0 /* TODO: pass distance */, lightsurf);
|
cfg, lightsurf->samples[i].occlusion, entity.get(), 0.0 /* TODO: pass distance */, lightsurf);
|
||||||
if (cfg.addminlight.value()) {
|
if (cfg.addminlight.value()) {
|
||||||
sample.color += entity->color.value() * (value / 255.0);
|
sample.color += entity->color.value() * (value / 255.0);
|
||||||
|
hit = true;
|
||||||
} else {
|
} else {
|
||||||
Light_ClampMin(sample, value, entity->color.value());
|
hit = Light_ClampMin(sample, value, entity->color.value()) || hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
hit = true;
|
|
||||||
total_light_ray_hits++;
|
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]
|
// 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)
|
const float &intensity, const qvec3d &color, const float &dist, const float &hotspot_clamp)
|
||||||
{
|
{
|
||||||
// Exponential falloff
|
// Exponential falloff
|
||||||
|
|
@ -1911,25 +1918,25 @@ inline qvec3f SurfaceLight_ColorAtDist(const settings::worldspawn_keys &cfg, con
|
||||||
|
|
||||||
// dir: vpl -> sample point direction
|
// dir: vpl -> sample point direction
|
||||||
// mxd. returns color in [0,255]
|
// mxd. returns color in [0,255]
|
||||||
inline qvec3f GetSurfaceLighting(const settings::worldspawn_keys &cfg, const surfacelight_t *vpl, const qvec3f &dir,
|
inline qvec3f GetSurfaceLighting(const settings::worldspawn_keys &cfg, const surfacelight_t &vpl,
|
||||||
const float dist, const qvec3f &normal, bool use_normal, const vec_t &standard_scale, const vec_t &sky_scale,
|
const surfacelight_t::per_style_t &vpl_settings, const qvec3f &dir, const float dist, const qvec3f &normal,
|
||||||
const float &hotspot_clamp)
|
bool use_normal, const vec_t &standard_scale, const vec_t &sky_scale, const float &hotspot_clamp)
|
||||||
{
|
{
|
||||||
qvec3f result;
|
qvec3f result;
|
||||||
float dotProductFactor = 1.0f;
|
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;
|
const qvec3f sp_vpl = dir * -1.0f;
|
||||||
float dp2 = use_normal ? qv::dot(sp_vpl, normal) : 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)
|
if (dp1 < -LIGHT_ANGLE_EPSILON)
|
||||||
return {0}; // sample point behind vpl
|
return {0}; // sample point behind vpl
|
||||||
if (dp2 < -LIGHT_ANGLE_EPSILON)
|
if (dp2 < -LIGHT_ANGLE_EPSILON)
|
||||||
return {0}; // vpl behind sample face
|
return {0}; // vpl behind sample face
|
||||||
|
|
||||||
// Rescale a bit to brighten the faces nearly-perpendicular to the surface light plane...
|
// 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;
|
dp1 = 0.5f + dp1 * 0.5f;
|
||||||
dp2 = 0.5f + dp2 * 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;
|
dotProductFactor = dp1 * dp2;
|
||||||
} else {
|
} else {
|
||||||
// used for sky face surface lights
|
// used for sky face surface lights
|
||||||
dotProductFactor = dp2;
|
dotProductFactor = dp2 * 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
dotProductFactor = std::max(0.0f, dotProductFactor);
|
dotProductFactor = std::max(0.0f, dotProductFactor);
|
||||||
|
|
||||||
// Get light contribution
|
// Get light contribution
|
||||||
result = SurfaceLight_ColorAtDist(
|
result = SurfaceLight_ColorAtDist(cfg, vpl_settings.omnidirectional ? sky_scale : standard_scale,
|
||||||
cfg, vpl->omnidirectional ? sky_scale : standard_scale, vpl->intensity, vpl->color, dist, hotspot_clamp);
|
vpl_settings.intensity, vpl_settings.color, dist, hotspot_clamp);
|
||||||
|
|
||||||
// Apply angle scale
|
// Apply angle scale
|
||||||
const qvec3f resultscaled = result * dotProductFactor;
|
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;
|
return resultscaled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool // mxd
|
static bool // mxd
|
||||||
SurfaceLight_SphereCull(
|
SurfaceLight_SphereCull(const surfacelight_t *vpl, const lightsurf_t *lightsurf,
|
||||||
const surfacelight_t *vpl, const lightsurf_t *lightsurf, const vec_t &bouncelight_gate, const float &hotspot_clamp)
|
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 &&
|
if (light_options.visapprox.value() == visapprox_t::RAYS &&
|
||||||
vpl->bounds.disjoint(lightsurf->extents.bounds, 0.001)) {
|
vpl->bounds.disjoint(lightsurf->extents.bounds, 0.001)) {
|
||||||
|
|
@ -1967,17 +1974,16 @@ SurfaceLight_SphereCull(
|
||||||
const float dist = qv::length(dir) + lightsurf->extents.radius;
|
const float dist = qv::length(dir) + lightsurf->extents.radius;
|
||||||
|
|
||||||
// Get light contribution
|
// Get light contribution
|
||||||
const qvec3f color =
|
const qvec3f color = SurfaceLight_ColorAtDist(cfg,
|
||||||
SurfaceLight_ColorAtDist(cfg, vpl->omnidirectional ? cfg.surflightskyscale.value() : cfg.surflightscale.value(),
|
vpl_settings.omnidirectional ? cfg.surflightskyscale.value() : cfg.surflightscale.value(),
|
||||||
vpl->totalintensity, vpl->color, dist, hotspot_clamp);
|
vpl_settings.totalintensity, vpl_settings.color, dist, hotspot_clamp);
|
||||||
|
|
||||||
return qv::gate(color, (float)bouncelight_gate);
|
return qv::gate(color, (float)bouncelight_gate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void // mxd
|
static void // mxd
|
||||||
LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t *lightmaps,
|
LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t *lightmaps, bool bounce,
|
||||||
const std::vector<surfacelight_t> &surface_lights, const vec_t &standard_scale, const vec_t &sky_scale,
|
const vec_t &standard_scale, const vec_t &sky_scale, const float &hotspot_clamp)
|
||||||
const float &hotspot_clamp)
|
|
||||||
{
|
{
|
||||||
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||||
const float surflight_gate = 0.01f;
|
const float surflight_gate = 0.01f;
|
||||||
|
|
@ -1987,9 +1993,21 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const surfacelight_t &vpl : surface_lights) {
|
for (const auto &surf_ptr : LightSurfaces()) {
|
||||||
if (SurfaceLight_SphereCull(&vpl, lightsurf, surflight_gate, hotspot_clamp))
|
|
||||||
|
if (!surf_ptr || !surf_ptr->vpl) {
|
||||||
|
// didn't emit anthing
|
||||||
continue;
|
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;
|
raystream_occlusion_t &rs = *lightsurf->occlusion_stream;
|
||||||
|
|
||||||
|
|
@ -2025,8 +2043,8 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
|
||||||
dir /= dist;
|
dir /= dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
const qvec3f indirect = GetSurfaceLighting(
|
const qvec3f indirect = GetSurfaceLighting(cfg, vpl, vpl_setting, dir, dist, lightsurf_normal,
|
||||||
cfg, &vpl, dir, dist, lightsurf_normal, use_normal, standard_scale, sky_scale, hotspot_clamp);
|
use_normal, standard_scale, sky_scale, hotspot_clamp);
|
||||||
if (!qv::gate(indirect, surflight_gate)) { // Each point contributes very little to the final result
|
if (!qv::gate(indirect, surflight_gate)) { // Each point contributes very little to the final result
|
||||||
rs.pushRay(i, pos, dir, dist, &indirect);
|
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();
|
total_surflight_rays += rs.numPushedRays();
|
||||||
rs.tracePushedRaysOcclusion(lightsurf->modelinfo, CHANNEL_MASK_DEFAULT);
|
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);
|
lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, lightmapstyle, lightsurf);
|
||||||
|
|
||||||
bool hit = false;
|
bool hit = false;
|
||||||
|
|
@ -2050,7 +2068,7 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
|
||||||
const int i = rs.getPushedRayPointIndex(j);
|
const int i = rs.getPushedRayPointIndex(j);
|
||||||
qvec3f indirect = rs.getPushedRayColor(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.
|
// Use dirt scaling on the surface lighting.
|
||||||
const vec_t dirtscale =
|
const vec_t dirtscale =
|
||||||
|
|
@ -2070,25 +2088,33 @@ LightFace_SurfaceLight(const mbsp_t *bsp, lightsurf_t *lightsurf, lightmapdict_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void // mxd
|
static void // mxd
|
||||||
LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, raystream_occlusion_t &rs,
|
LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, raystream_occlusion_t &rs, bool bounce,
|
||||||
const std::vector<surfacelight_t> &surface_lights, const vec_t &standard_scale, const vec_t &sky_scale,
|
const vec_t &standard_scale, const vec_t &sky_scale, const float &hotspot_clamp, const qvec3d &surfpoint,
|
||||||
const float &hotspot_clamp, const qvec3d &surfpoint, lightgrid_samples_t &result)
|
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;
|
||||||
|
|
||||||
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++) {
|
for (int c = 0; c < vpl.points.size(); c++) {
|
||||||
if (light_options.visapprox.value() == visapprox_t::VIS && pvs && VisCullEntity(bsp, *pvs, vpl.leaves[c])) {
|
if (light_options.visapprox.value() == visapprox_t::VIS && pvs && VisCullEntity(bsp, *pvs, vpl.leaves[c])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
rs.clearPushedRays();
|
|
||||||
|
|
||||||
// 1 ray
|
// 1 ray
|
||||||
{
|
for (auto &vpl_settings : vpl.styles) {
|
||||||
|
if (vpl_settings.bounce != bounce)
|
||||||
|
continue;
|
||||||
|
|
||||||
qvec3f pos = vpl.points[c];
|
qvec3f pos = vpl.points[c];
|
||||||
qvec3f dir = surfpoint - pos;
|
qvec3f dir = surfpoint - pos;
|
||||||
float dist = qv::length(dir);
|
float dist = qv::length(dir);
|
||||||
|
|
@ -2100,6 +2126,8 @@ LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, rays
|
||||||
|
|
||||||
qvec3f indirect{};
|
qvec3f indirect{};
|
||||||
|
|
||||||
|
rs.clearPushedRays();
|
||||||
|
|
||||||
for (int axis = 0; axis < 3; ++axis) {
|
for (int axis = 0; axis < 3; ++axis) {
|
||||||
for (int sign = -1; sign <= +1; sign += 2) {
|
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{};
|
qvec3f cube_normal{};
|
||||||
cube_normal[axis] = sign;
|
cube_normal[axis] = sign;
|
||||||
|
|
||||||
cube_color = GetSurfaceLighting(
|
cube_color = GetSurfaceLighting(cfg, vpl, vpl_settings, dir, dist, cube_normal, true,
|
||||||
cfg, &vpl, dir, dist, cube_normal, true, standard_scale, sky_scale, hotspot_clamp);
|
standard_scale, sky_scale, hotspot_clamp);
|
||||||
|
|
||||||
#ifdef LIGHTPOINT_TAKE_MAX
|
#ifdef LIGHTPOINT_TAKE_MAX
|
||||||
if (qv::length2(cube_color) > qv::length2(indirect)) {
|
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
|
if (!qv::gate(indirect, surflight_gate)) { // Each point contributes very little to the final result
|
||||||
rs.pushRay(0, pos, dir, dist, &indirect);
|
rs.pushRay(0, pos, dir, dist, &indirect);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!rs.numPushedRays())
|
if (!rs.numPushedRays())
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2138,13 +2165,14 @@ LightPoint_SurfaceLight(const mbsp_t *bsp, const std::vector<uint8_t> *pvs, rays
|
||||||
|
|
||||||
qvec3f indirect = rs.getPushedRayColor(j);
|
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)
|
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...
|
// mxd. Add surface lights...
|
||||||
// FIXME: negative surface lights
|
// FIXME: negative surface lights
|
||||||
LightFace_SurfaceLight(bsp, &lightsurf, lightmaps, GetSurfaceLights(), cfg.surflightscale.value(),
|
LightFace_SurfaceLight(
|
||||||
cfg.surflightskyscale.value(), 16.0f);
|
bsp, &lightsurf, lightmaps, false, cfg.surflightscale.value(), cfg.surflightskyscale.value(), 16.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
LightFace_LocalMin(bsp, face, &lightsurf, lightmaps);
|
LightFace_LocalMin(bsp, face, &lightsurf, lightmaps);
|
||||||
|
|
@ -3373,8 +3401,8 @@ void IndirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings
|
||||||
|
|
||||||
/* add bounce lighting */
|
/* add bounce lighting */
|
||||||
// note: scale here is just to keep it close-ish to the old code
|
// 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,
|
LightFace_SurfaceLight(
|
||||||
cfg.bouncescale.value(), 128.0f);
|
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);
|
LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lightsurf.vpl) {
|
||||||
if (auto value = IsSurfaceLitFace(bsp, face)) {
|
if (auto value = IsSurfaceLitFace(bsp, face)) {
|
||||||
auto *entity = std::get<3>(value.value());
|
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;
|
surface_minlight_scale *= lightsurf.surflight_minlight_scale;
|
||||||
|
|
||||||
if (surface_minlight_scale > 0) {
|
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()));
|
bsp, face, minlight_color, minlight, &lightsurf, lightmaps, std::get<1>(value.value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!modelinfo->isWorld()) {
|
if (!modelinfo->isWorld()) {
|
||||||
LightFace_AutoMin(bsp, face, &lightsurf, lightmaps);
|
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...
|
// mxd. Add surface lights...
|
||||||
// FIXME: negative surface lights
|
// FIXME: negative surface lights
|
||||||
LightPoint_SurfaceLight(bsp, pvs, rs, GetSurfaceLights(), cfg.surflightscale.value(), cfg.surflightskyscale.value(),
|
LightPoint_SurfaceLight(
|
||||||
16.0f, world_point, result);
|
bsp, pvs, rs, false, cfg.surflightscale.value(), cfg.surflightskyscale.value(), 16.0f, world_point, result);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// FIXME: port to lightgrid
|
// FIXME: port to lightgrid
|
||||||
|
|
@ -3613,8 +3643,8 @@ lightgrid_samples_t CalcLightgridAtPoint(const mbsp_t *bsp, const qvec3d &world_
|
||||||
|
|
||||||
/* add bounce lighting */
|
/* add bounce lighting */
|
||||||
// note: scale here is just to keep it close-ish to the old code
|
// 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(),
|
LightPoint_SurfaceLight(
|
||||||
128.0f, world_point, result);
|
bsp, pvs, rs, true, cfg.bouncescale.value() * 0.5, cfg.bouncescale.value(), 128.0f, world_point, result);
|
||||||
|
|
||||||
LightPoint_ScaleAndClamp(result);
|
LightPoint_ScaleAndClamp(result);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,23 +37,13 @@ See file, 'COPYING', for details.
|
||||||
|
|
||||||
#include <common/qvec.hh>
|
#include <common/qvec.hh>
|
||||||
|
|
||||||
static std::mutex surfacelights_lock;
|
static std::atomic_size_t total_surflight_points;
|
||||||
static std::vector<surfacelight_t> surfacelights;
|
|
||||||
static std::map<int, std::vector<int>> surfacelightsByFacenum;
|
|
||||||
static size_t total_surflight_points = 0;
|
|
||||||
|
|
||||||
void ResetSurflight()
|
void ResetSurflight()
|
||||||
{
|
{
|
||||||
surfacelights = {};
|
|
||||||
surfacelightsByFacenum = {};
|
|
||||||
total_surflight_points = {};
|
total_surflight_points = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<surfacelight_t> &GetSurfaceLights()
|
|
||||||
{
|
|
||||||
return surfacelights;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t GetSurflightPoints()
|
size_t GetSurflightPoints()
|
||||||
{
|
{
|
||||||
return total_surflight_points;
|
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,
|
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)
|
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...
|
// Create face points...
|
||||||
auto poly = Face_Points(bsp, face);
|
auto poly = Face_Points(bsp, face);
|
||||||
const float facearea = qv::PolyArea(poly.begin(), poly.end());
|
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)
|
if (facearea < 1)
|
||||||
return;
|
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...
|
// Calculate emit color and intensity...
|
||||||
|
|
||||||
if (extended_flags.surflight_color.has_value()) {
|
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)
|
if (intensity > 1.0f)
|
||||||
texture_color.value() *= 1.0f / intensity;
|
texture_color.value() *= 1.0f / intensity;
|
||||||
|
|
||||||
// Sanity checks...
|
if (!surf.vpl) {
|
||||||
if (points.empty())
|
auto &l = surf.vpl = std::make_unique<surfacelight_t>();
|
||||||
return;
|
|
||||||
|
|
||||||
// Add surfacelight...
|
// Create winding...
|
||||||
surfacelight_t l;
|
auto winding = polylib::winding_t::from_winding_points(poly);
|
||||||
l.surfnormal = facenormal;
|
auto face_modelinfo = ModelInfoForFace(bsp, face - bsp->dfaces.data());
|
||||||
l.omnidirectional = !is_directional;
|
|
||||||
l.points = std::move(points);
|
for (auto &pt : winding) {
|
||||||
if (extended_flags.surflight_targetname) {
|
pt += face_modelinfo->offset;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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...
|
// Init bbox...
|
||||||
if (light_options.visapprox.value() == visapprox_t::RAYS) {
|
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) {
|
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) {
|
} 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...
|
// Store surfacelight settings...
|
||||||
l.totalintensity = intensity * facearea;
|
setting.totalintensity = intensity * facearea;
|
||||||
l.intensity = l.totalintensity / points_before_culling;
|
setting.intensity = setting.totalintensity / l->points_before_culling;
|
||||||
l.color = texture_color.value();
|
setting.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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::tuple<int32_t, int32_t, qvec3d, light_t *>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face)
|
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
|
void // Quake 2 surface lights
|
||||||
MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
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(
|
logging::parallel_for(
|
||||||
static_cast<size_t>(0), bsp->dfaces.size(), [&](size_t i) { MakeSurfaceLightsThread(bsp, cfg, i); });
|
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);
|
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;
|
flags.no_minlight = true;
|
||||||
if (entity.epairs.get_int("_lightignore") == 1)
|
if (entity.epairs.get_int("_lightignore") == 1)
|
||||||
flags.light_ignore = true;
|
flags.light_ignore = true;
|
||||||
if (entity.epairs.has("_surflight_rescale") && entity.epairs.get_int("_surflight_rescale") == 0)
|
if (entity.epairs.has("_surflight_rescale")) {
|
||||||
flags.surflight_rescale = false;
|
flags.surflight_rescale = entity.epairs.get_int("_surflight_rescale") == 1;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
qvec3d color;
|
qvec3d color;
|
||||||
// FIXME: get_color, to match settings
|
// FIXME: get_color, to match settings
|
||||||
|
|
|
||||||
|
|
@ -381,8 +381,8 @@ static void WriteExtendedTexinfoFlags(void)
|
||||||
if (tx.flags.light_ignore) {
|
if (tx.flags.light_ignore) {
|
||||||
t["light_ignore"] = tx.flags.light_ignore;
|
t["light_ignore"] = tx.flags.light_ignore;
|
||||||
}
|
}
|
||||||
if (tx.flags.surflight_rescale == false) {
|
if (tx.flags.surflight_rescale) {
|
||||||
t["surflight_rescale"] = tx.flags.surflight_rescale;
|
t["surflight_rescale"] = tx.flags.surflight_rescale.value();
|
||||||
}
|
}
|
||||||
if (tx.flags.surflight_style.has_value()) {
|
if (tx.flags.surflight_style.has_value()) {
|
||||||
t["surflight_style"] = tx.flags.surflight_style.value();
|
t["surflight_style"] = tx.flags.surflight_style.value();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue