re-introduce vis culling, mainly for Q2/surface lit maps
-novisapprox gone; replaced with -visapprox auto|none|vis|rays
This commit is contained in:
parent
b54e72a184
commit
e366898796
|
|
@ -69,7 +69,7 @@ struct mvis_t
|
|||
|
||||
// fetch the bit offset of the specified cluster/vistype
|
||||
// relative to the start of the bits array
|
||||
inline int32_t get_bit_offset(vistype_t type, size_t cluster)
|
||||
inline int32_t get_bit_offset(vistype_t type, size_t cluster) const
|
||||
{
|
||||
return bit_offsets[cluster][type] - header_offset();
|
||||
}
|
||||
|
|
@ -451,7 +451,7 @@ struct mleaf_t
|
|||
{
|
||||
// bsp2_dleaf_t
|
||||
int32_t contents;
|
||||
int32_t visofs; /* -1 = no visibility info */
|
||||
int32_t visofs; /* -1 = no visibility info; Q1 only! */
|
||||
qvec3f mins; /* for frustum culling */
|
||||
qvec3f maxs;
|
||||
uint32_t firstmarksurface;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ struct bouncelight_t
|
|||
qvec3f surfnormal;
|
||||
float area;
|
||||
|
||||
const mleaf_t *leaf;
|
||||
|
||||
/* estimated visible AABB culling */
|
||||
aabb3d bounds;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ public:
|
|||
|
||||
bool generated = false; // if true, don't write to the bsp
|
||||
|
||||
const mleaf_t *leaf;
|
||||
|
||||
aabb3d bounds;
|
||||
|
||||
settings::setting_scalar light{this, "light", DEFAULTLIGHTLEVEL};
|
||||
|
|
|
|||
|
|
@ -141,6 +141,13 @@ struct lightsurf_t
|
|||
fully occluded. dirtgain/dirtscale are not applied yet
|
||||
*/
|
||||
float *occlusion; // new'ed array of numpoints
|
||||
|
||||
/*
|
||||
pvs for the entire light surface. generated by ORing together
|
||||
the pvs at each of the sample points
|
||||
*/
|
||||
std::vector<uint8_t> pvs;
|
||||
bool skyvisible;
|
||||
|
||||
/* for sphere culling */
|
||||
qvec3d origin;
|
||||
|
|
@ -249,6 +256,14 @@ public:
|
|||
modelinfo_t(const mbsp_t *b, const dmodelh2_t *m, float lmscale) : bsp{b}, model{m}, lightmapscale{lmscale} { }
|
||||
};
|
||||
|
||||
enum class visapprox_t
|
||||
{
|
||||
NONE,
|
||||
AUTO,
|
||||
VIS,
|
||||
RAYS
|
||||
};
|
||||
|
||||
//
|
||||
// worldspawn keys / command-line settings
|
||||
//
|
||||
|
|
@ -409,8 +424,8 @@ public:
|
|||
this, "lmscale", 0, &experimental_group, "change lightmap scale, vanilla engines only allow 16"};
|
||||
setting_extra extra{
|
||||
this, {"extra", "extra4"}, 1, &performance_group, "supersampling; 2x2 (extra) or 4x4 (extra4) respectively"};
|
||||
setting_bool novisapprox{
|
||||
this, "novisapprox", false, &debug_group, "disable approximate visibility culling of lights"};
|
||||
setting_enum<visapprox_t> visapprox{
|
||||
this, "visapprox", visapprox_t::AUTO, { { "auto", visapprox_t::AUTO }, { "none", visapprox_t::NONE }, { "vis", visapprox_t::VIS }, { "rays", visapprox_t::RAYS } }, &debug_group, "change approximate visibility algorithm. auto = choose default based on format. vis = use BSP vis data. rays = use sphere culling with fired rays"};
|
||||
setting_func lit{this, "lit", [&]() { write_litfile |= lightfile::external; }, &output_group, "write .lit file"};
|
||||
setting_func lit2{
|
||||
this, "lit2", [&]() { write_litfile = lightfile::lit2; }, &experimental_group, "write .lit2 file"};
|
||||
|
|
@ -518,6 +533,8 @@ extern uint8_t *lux_filebase;
|
|||
|
||||
extern std::vector<surfflags_t> extended_texinfo_flags;
|
||||
|
||||
bool Leaf_HasSky(const mbsp_t *bsp, const mleaf_t *leaf);
|
||||
|
||||
// public functions
|
||||
|
||||
void SetGlobalSetting(std::string name, std::string value, bool cmdline);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ struct surfacelight_t
|
|||
*/
|
||||
bool omnidirectional;
|
||||
std::vector<qvec3f> points;
|
||||
std::vector<const mleaf_t *> leaves;
|
||||
|
||||
// Surface light settings...
|
||||
float intensity; // Surface light strength for each point
|
||||
|
|
|
|||
|
|
@ -107,3 +107,6 @@ raystream_intersection_t *MakeIntersectionRayStream(int maxrays);
|
|||
raystream_occlusion_t *MakeOcclusionRayStream(int maxrays);
|
||||
|
||||
void MakeTnodes(const mbsp_t *bsp);
|
||||
|
||||
const mleaf_t *Light_PointInLeaf( const mbsp_t *bsp, const qvec3d &point );
|
||||
int Light_PointContents( const mbsp_t *bsp, const qvec3d &point );
|
||||
|
|
|
|||
|
|
@ -144,7 +144,9 @@ static void AddBounceLight(const T &pos, const std::map<int, qvec3f> &colorBySty
|
|||
l.area = area;
|
||||
l.bounds = qvec3d(0);
|
||||
|
||||
if (!options.novisapprox.value()) {
|
||||
if (options.visapprox.value() == visapprox_t::VIS) {
|
||||
l.leaf = Light_PointInLeaf(bsp, pos);
|
||||
} else if (options.visapprox.value() == visapprox_t::RAYS) {
|
||||
l.bounds = EstimateVisibleBoundsAtPoint(pos);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -945,6 +945,13 @@ void FixLightsOnFaces(const mbsp_t *bsp)
|
|||
}
|
||||
}
|
||||
|
||||
static void SetupLightLeafnums(const mbsp_t *bsp)
|
||||
{
|
||||
for (auto &entity : all_lights) {
|
||||
entity->leaf = Light_PointInLeaf(bsp, entity->origin.value());
|
||||
}
|
||||
}
|
||||
|
||||
// Maps uniform random variables U and V in [0, 1] to uniformly distributed points on a sphere
|
||||
|
||||
// from http://mathworld.wolfram.com/SpherePointPicking.html
|
||||
|
|
@ -1025,8 +1032,9 @@ inline void EstimateLightAABB(const std::unique_ptr<light_t> &light)
|
|||
|
||||
void EstimateLightVisibility(void)
|
||||
{
|
||||
if (options.novisapprox.value())
|
||||
if (options.visapprox.value() != visapprox_t::RAYS) {
|
||||
return;
|
||||
}
|
||||
|
||||
logging::print("--- EstimateLightVisibility ---\n");
|
||||
|
||||
|
|
@ -1054,6 +1062,9 @@ void SetupLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
|||
SetupSkyDomes(cfg);
|
||||
FixLightsOnFaces(bsp);
|
||||
EstimateLightVisibility();
|
||||
if (options.visapprox.value() == visapprox_t::VIS) {
|
||||
SetupLightLeafnums(bsp);
|
||||
}
|
||||
|
||||
logging::print("Final count: {} lights, {} suns in use.\n", all_lights.size(), all_suns.size());
|
||||
|
||||
|
|
|
|||
|
|
@ -646,6 +646,59 @@ static void ExportObj(const fs::path &filename, const mbsp_t *bsp)
|
|||
}
|
||||
|
||||
// obj
|
||||
static vector<vector<const mleaf_t *>> faceleafs;
|
||||
static vector<bool> leafhassky;
|
||||
|
||||
// index some stuff from the bsp
|
||||
static void BuildPvsIndex(const mbsp_t *bsp)
|
||||
{
|
||||
// build leafsForFace
|
||||
faceleafs.resize(bsp->dfaces.size());
|
||||
for (size_t i = 0; i < bsp->dleafs.size(); i++) {
|
||||
const mleaf_t &leaf = bsp->dleafs[i];
|
||||
for (int k = 0; k < leaf.nummarksurfaces; k++) {
|
||||
const int facenum = bsp->dleaffaces[leaf.firstmarksurface + k];
|
||||
faceleafs.at(facenum).push_back(&leaf);
|
||||
}
|
||||
}
|
||||
|
||||
// build leafhassky
|
||||
leafhassky.resize(bsp->dleafs.size(), false);
|
||||
for (size_t i = 0; i < bsp->dleafs.size(); i++) {
|
||||
const bsp2_dleaf_t &leaf = bsp->dleafs[i];
|
||||
|
||||
// check for sky, contents check
|
||||
if (bsp->loadversion->game->contents_are_sky({ leaf.contents })) {
|
||||
leafhassky.at(i) = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// search for sky faces
|
||||
for (size_t k = 0; k < leaf.nummarksurfaces; k++) {
|
||||
const mface_t &surf = bsp->dfaces[bsp->dleaffaces[leaf.firstmarksurface + k]];
|
||||
const mtexinfo_t &texinfo = bsp->texinfo[surf.texinfo];
|
||||
|
||||
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
|
||||
if (texinfo.flags.native & Q2_SURF_SKY) {
|
||||
leafhassky.at(i) = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const char *texname = Face_TextureName(bsp, &surf);
|
||||
if (!strncmp("sky", texname, 3)) {
|
||||
leafhassky.at(i) = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Leaf_HasSky(const mbsp_t *bsp, const mleaf_t *leaf)
|
||||
{
|
||||
const int leafnum = leaf - bsp->dleafs.data();
|
||||
return leafhassky.at(leafnum);
|
||||
}
|
||||
|
||||
// returns the face with a centroid nearest the given point.
|
||||
static const mface_t *Face_NearestCentroid(const mbsp_t *bsp, const qvec3f &point)
|
||||
|
|
@ -914,9 +967,19 @@ int light_main(int argc, const char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
// check vis approx type
|
||||
if (options.visapprox.value() == visapprox_t::AUTO) {
|
||||
if (bspdata.loadversion->game->id == GAME_QUAKE_II) {
|
||||
options.visapprox.setValue(visapprox_t::VIS);
|
||||
} else {
|
||||
options.visapprox.setValue(visapprox_t::RAYS);
|
||||
}
|
||||
}
|
||||
|
||||
img::init_palette(bspdata.loadversion->game);
|
||||
img::load_textures(&bsp);
|
||||
|
||||
|
||||
BuildPvsIndex(&bsp);
|
||||
LoadExtendedTexinfoFlags(source, &bsp);
|
||||
LoadEntities(options, &bsp);
|
||||
|
||||
|
|
|
|||
230
light/ltface.cc
230
light/ltface.cc
|
|
@ -687,6 +687,179 @@ static void CalcPoints(
|
|||
}
|
||||
}
|
||||
|
||||
static size_t DecompressedVisSize(const mbsp_t *bsp)
|
||||
{
|
||||
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
|
||||
return (bsp->dvis.bit_offsets.size() + 7) / 8;
|
||||
}
|
||||
|
||||
return (bsp->dmodels[0].visleafs + 7) / 8;
|
||||
}
|
||||
|
||||
// from DarkPlaces
|
||||
static void Mod_Q1BSP_DecompressVis(const uint8_t *in, const uint8_t *inend, uint8_t *out, uint8_t *outend)
|
||||
{
|
||||
int c;
|
||||
uint8_t *outstart = out;
|
||||
while (out < outend)
|
||||
{
|
||||
if (in == inend)
|
||||
{
|
||||
logging::print("Mod_Q1BSP_DecompressVis: input underrun (decompressed {} of {} output bytes)\n", (out - outstart), (outend - outstart));
|
||||
return;
|
||||
}
|
||||
|
||||
c = *in++;
|
||||
if (c) {
|
||||
*out++ = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in == inend)
|
||||
{
|
||||
logging::print("Mod_Q1BSP_DecompressVis: input underrun (during zero-run) (decompressed {} of {} output bytes)\n", (out - outstart), (outend - outstart));
|
||||
return;
|
||||
}
|
||||
|
||||
for (c = *in++;c > 0;c--)
|
||||
{
|
||||
if (out == outend)
|
||||
{
|
||||
logging::print("Mod_Q1BSP_DecompressVis: output overrun (decompressed {} of {} output bytes)\n", (out - outstart), (outend - outstart));
|
||||
return;
|
||||
}
|
||||
*out++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool Mod_LeafPvs(const mbsp_t *bsp, const mleaf_t *leaf, uint8_t *out)
|
||||
{
|
||||
const size_t num_pvsclusterbytes = DecompressedVisSize(bsp);
|
||||
|
||||
// init to all visible
|
||||
memset(out, 0xFF, num_pvsclusterbytes);
|
||||
|
||||
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
|
||||
if (leaf->cluster < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (leaf->cluster >= bsp->dvis.bit_offsets.size() ||
|
||||
bsp->dvis.get_bit_offset(VIS_PVS, leaf->cluster) >= bsp->dvis.bits.size()) {
|
||||
logging::print("Mod_LeafPvs: invalid visofs for cluster {}\n", leaf->cluster);
|
||||
return false;
|
||||
}
|
||||
|
||||
Mod_Q1BSP_DecompressVis(bsp->dvis.bits.data() + bsp->dvis.get_bit_offset(VIS_PVS, leaf->cluster),
|
||||
bsp->dvis.bits.data() + bsp->dvis.bits.size(),
|
||||
out,
|
||||
out + num_pvsclusterbytes);
|
||||
} else {
|
||||
if (leaf->visofs < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ptrdiff_t leafnum = (leaf - bsp->dleafs.data());
|
||||
|
||||
// this is confusing.. "visleaf numbers" are the leaf number minus 1.
|
||||
// they also don't go as high, bsp->dmodels[0].visleafs instead of bsp->numleafs
|
||||
const int visleaf = leafnum - 1;
|
||||
if (visleaf < 0 || visleaf >= bsp->dmodels[0].visleafs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (leaf->visofs >= bsp->dvis.bits.size()) {
|
||||
logging::print("Mod_LeafPvs: invalid visofs for leaf {}\n", leafnum);
|
||||
return false;
|
||||
}
|
||||
|
||||
Mod_Q1BSP_DecompressVis(bsp->dvis.bits.data() + leaf->visofs,
|
||||
bsp->dvis.bits.data() + bsp->dvis.bits.size(),
|
||||
out,
|
||||
out + num_pvsclusterbytes);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns true if pvs can see leaf
|
||||
static bool Pvs_LeafVisible(const mbsp_t *bsp, const std::vector<uint8_t> &pvs, const mleaf_t *leaf)
|
||||
{
|
||||
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
|
||||
if (leaf->cluster < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (leaf->cluster >= bsp->dvis.bit_offsets.size() ||
|
||||
bsp->dvis.get_bit_offset(VIS_PVS, leaf->cluster) >= bsp->dvis.bits.size()) {
|
||||
logging::print("Pvs_LeafVisible: invalid visofs for cluster {}\n", leaf->cluster);
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!(pvs[leaf->cluster>>3] & (1<<(leaf->cluster&7)));
|
||||
} else {
|
||||
const int leafnum = (leaf - bsp->dleafs.data());
|
||||
const int visleaf = leafnum - 1;
|
||||
|
||||
if (visleaf < 0 || visleaf >= bsp->dmodels[0].visleafs) {
|
||||
logging::print("WARNING: bad/empty vis data on leaf?");
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!(pvs[visleaf>>3] & (1<<(visleaf&7)));
|
||||
}
|
||||
}
|
||||
|
||||
static void CalcPvs(const mbsp_t *bsp, lightsurf_t *lightsurf)
|
||||
{
|
||||
const int pvssize = DecompressedVisSize(bsp);
|
||||
const mleaf_t *lastleaf = nullptr;
|
||||
|
||||
// set defaults
|
||||
lightsurf->pvs.clear();
|
||||
lightsurf->skyvisible = true;
|
||||
|
||||
if (!bsp->dvis.bits.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set lightsurf->pvs
|
||||
uint8_t *pointpvs = (uint8_t *) alloca(pvssize);
|
||||
lightsurf->pvs.resize(pvssize);
|
||||
|
||||
for (int i = 0; i < lightsurf->numpoints; i++) {
|
||||
const mleaf_t *leaf = Light_PointInLeaf (bsp, lightsurf->points[i]);
|
||||
|
||||
/* most/all of the surface points are probably in the same leaf */
|
||||
if (leaf == lastleaf)
|
||||
continue;
|
||||
|
||||
lastleaf = leaf;
|
||||
|
||||
/* copy the pvs for this leaf into pointpvs */
|
||||
Mod_LeafPvs(bsp, leaf, pointpvs);
|
||||
|
||||
/* merge the pvs for this sample point into lightsurf->pvs */
|
||||
for (int j=0; j<pvssize; j++) {
|
||||
lightsurf->pvs[j] |= pointpvs[j];
|
||||
}
|
||||
}
|
||||
|
||||
// set lightsurf->skyvisible
|
||||
lightsurf->skyvisible = false;
|
||||
for (int i = 0; i < bsp->dleafs.size(); i++) {
|
||||
const mleaf_t *leaf = &bsp->dleafs[i];
|
||||
if (Pvs_LeafVisible(bsp, lightsurf->pvs, leaf)) {
|
||||
// we can see this leaf, search for sky faces in it
|
||||
if (Leaf_HasSky(bsp, leaf)) {
|
||||
lightsurf->skyvisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool Lightsurf_Init(
|
||||
const modelinfo_t *modelinfo, const mface_t *face, const mbsp_t *bsp, lightsurf_t *lightsurf, facesup_t *facesup)
|
||||
{
|
||||
|
|
@ -794,6 +967,12 @@ static bool Lightsurf_Init(
|
|||
|
||||
lightsurf->intersection_stream = MakeIntersectionRayStream(lightsurf->numpoints);
|
||||
lightsurf->occlusion_stream = MakeOcclusionRayStream(lightsurf->numpoints);
|
||||
|
||||
/* Setup vis data */
|
||||
if (options.visapprox.value() == visapprox_t::VIS) {
|
||||
CalcPvs(bsp, lightsurf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1204,7 +1383,7 @@ inline bool CullLight(const light_t *entity, const lightsurf_t *lightsurf)
|
|||
{
|
||||
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||
|
||||
if (!options.novisapprox.value() && entity->bounds.disjoint(lightsurf->bounds, 0.001)) {
|
||||
if (options.visapprox.value() == visapprox_t::RAYS && entity->bounds.disjoint(lightsurf->bounds, 0.001)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1356,6 +1535,27 @@ std::map<int, qvec3f> GetDirectLighting(
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool VisCullEntity(const mbsp_t *bsp, const std::vector<uint8_t> &pvs, const mleaf_t *entleaf)
|
||||
{
|
||||
if (options.visapprox.value() != visapprox_t::VIS) {
|
||||
return false;
|
||||
}
|
||||
if (pvs.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (entleaf == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bsp->loadversion->game->contents_are_solid({ entleaf->contents }) ||
|
||||
bsp->loadversion->game->contents_are_sky({ entleaf->contents })) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !Pvs_LeafVisible(bsp, pvs, entleaf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ================
|
||||
* LightFace_Entity
|
||||
|
|
@ -1368,6 +1568,11 @@ static void LightFace_Entity(
|
|||
const modelinfo_t *modelinfo = lightsurf->modelinfo;
|
||||
const qplane3d *plane = &lightsurf->plane;
|
||||
|
||||
/* vis cull */
|
||||
if (VisCullEntity(bsp, lightsurf->pvs, entity->leaf)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const vec_t planedist = plane->distance_to(entity->origin.value());
|
||||
|
||||
/* don't bother with lights behind the surface.
|
||||
|
|
@ -1473,6 +1678,11 @@ static void LightFace_Entity(
|
|||
*/
|
||||
static void LightFace_Sky(const sun_t *sun, const lightsurf_t *lightsurf, lightmapdict_t *lightmaps)
|
||||
{
|
||||
/* If vis data says we can't see any sky faces, skip raytracing */
|
||||
if (!lightsurf->skyvisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||
const modelinfo_t *modelinfo = lightsurf->modelinfo;
|
||||
const qplane3d *plane = &lightsurf->plane;
|
||||
|
|
@ -1861,8 +2071,9 @@ inline bool BounceLight_SphereCull(const mbsp_t *bsp, const bouncelight_t *vpl,
|
|||
{
|
||||
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||
|
||||
if (!options.novisapprox.value() && vpl->bounds.disjoint(lightsurf->bounds, 0.001))
|
||||
if (options.visapprox.value() == visapprox_t::RAYS && vpl->bounds.disjoint(lightsurf->bounds, 0.001)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const qvec3f dir = qvec3f(lightsurf->origin) - vpl->pos; // vpl -> sample point
|
||||
const float dist = qv::length(dir) + lightsurf->radius;
|
||||
|
|
@ -1876,8 +2087,9 @@ inline bool BounceLight_SphereCull(const mbsp_t *bsp, const bouncelight_t *vpl,
|
|||
static bool // mxd
|
||||
SurfaceLight_SphereCull(const surfacelight_t *vpl, const lightsurf_t *lightsurf)
|
||||
{
|
||||
if (!options.novisapprox.value() && vpl->bounds.disjoint(lightsurf->bounds, 0.001))
|
||||
if (options.visapprox.value() == visapprox_t::RAYS && vpl->bounds.disjoint(lightsurf->bounds, 0.001)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||
const qvec3f dir = qvec3f(lightsurf->origin) - qvec3f(vpl->pos); // vpl -> sample point
|
||||
|
|
@ -1930,6 +2142,10 @@ static void LightFace_Bounce(
|
|||
|
||||
#if 1
|
||||
for (const bouncelight_t &vpl : BounceLights()) {
|
||||
if (VisCullEntity(bsp, lightsurf->pvs, vpl.leaf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BounceLight_SphereCull(bsp, &vpl, lightsurf))
|
||||
continue;
|
||||
|
||||
|
|
@ -2103,7 +2319,7 @@ static void LightFace_Bounce(
|
|||
}
|
||||
|
||||
static void // mxd
|
||||
LightFace_SurfaceLight(const lightsurf_t *lightsurf, lightmapdict_t *lightmaps)
|
||||
LightFace_SurfaceLight(const mbsp_t *bsp, const lightsurf_t *lightsurf, lightmapdict_t *lightmaps)
|
||||
{
|
||||
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||
|
||||
|
|
@ -2114,6 +2330,10 @@ LightFace_SurfaceLight(const lightsurf_t *lightsurf, lightmapdict_t *lightmaps)
|
|||
raystream_occlusion_t *rs = lightsurf->occlusion_stream;
|
||||
|
||||
for (int c = 0; c < vpl.points.size(); c++) {
|
||||
if (VisCullEntity(bsp, lightsurf->pvs, vpl.leaves[c])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rs->clearPushedRays();
|
||||
|
||||
for (int i = 0; i < lightsurf->numpoints; i++) {
|
||||
|
|
@ -3235,7 +3455,7 @@ void LightFace(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const setti
|
|||
LightFace_Sky(&sun, lightsurf, lightmaps);
|
||||
|
||||
// mxd. Add surface lights...
|
||||
LightFace_SurfaceLight(lightsurf, lightmaps);
|
||||
LightFace_SurfaceLight(bsp, lightsurf, lightmaps);
|
||||
|
||||
/* add indirect lighting */
|
||||
LightFace_Bounce(bsp, face, lightsurf, lightmaps);
|
||||
|
|
|
|||
|
|
@ -118,6 +118,13 @@ static void MakeSurfaceLightsThread(const mbsp_t *bsp, const settings::worldspaw
|
|||
l.surfnormal = facenormal;
|
||||
l.omnidirectional = true;//(info->flags.native & Q2_SURF_SKY) ? true : false;
|
||||
l.points = points;
|
||||
|
||||
if (options.visapprox.value() == visapprox_t::VIS) {
|
||||
for (auto &pt : points) {
|
||||
l.leaves.push_back(Light_PointInLeaf(bsp, pt + l.surfnormal));
|
||||
}
|
||||
}
|
||||
|
||||
l.pos = facemidpoint;
|
||||
|
||||
// Store surfacelight settings...
|
||||
|
|
@ -128,8 +135,9 @@ static void MakeSurfaceLightsThread(const mbsp_t *bsp, const settings::worldspaw
|
|||
// Init bbox...
|
||||
l.bounds = qvec3d(0);
|
||||
|
||||
if (!options.novisapprox.value())
|
||||
if (options.visapprox.value() == visapprox_t::RAYS) {
|
||||
l.bounds = EstimateVisibleBoundsAtPoint(facemidpoint);
|
||||
}
|
||||
|
||||
// Store light...
|
||||
unique_lock<mutex> lck{surfacelights_lock};
|
||||
|
|
|
|||
|
|
@ -26,6 +26,35 @@
|
|||
#endif
|
||||
#include <cassert>
|
||||
|
||||
/*
|
||||
==============
|
||||
Light_PointInLeaf
|
||||
|
||||
from hmap2
|
||||
==============
|
||||
*/
|
||||
const mleaf_t *Light_PointInLeaf( const mbsp_t *bsp, const qvec3d &point )
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
while( num >= 0 )
|
||||
num = bsp->dnodes[num].children[bsp->dplanes[bsp->dnodes[num].planenum].distance_to_fast(point) < 0];
|
||||
|
||||
return &bsp->dleafs[-1 - num];
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Light_PointContents
|
||||
|
||||
from hmap2
|
||||
==============
|
||||
*/
|
||||
int Light_PointContents( const mbsp_t *bsp, const qvec3d &point )
|
||||
{
|
||||
return Light_PointInLeaf(bsp, point)->contents;
|
||||
}
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* FENCE TEXTURE TESTING
|
||||
|
|
|
|||
|
|
@ -486,13 +486,7 @@ static void ClusterFlow(int clusternum, leafbits_t &buffer, mbsp_t *bsp)
|
|||
bsp->dvis.set_bit_offset(VIS_PVS, clusternum, visofs);
|
||||
|
||||
// Set pointers
|
||||
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
|
||||
for (i = 1; i < bsp->dleafs.size(); i++) {
|
||||
if (bsp->dleafs[i].cluster == clusternum) {
|
||||
bsp->dleafs[i].visofs = visofs;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (bsp->loadversion->game->id != GAME_QUAKE_II) {
|
||||
for (i = 0; i < portalleafs_real; i++) {
|
||||
if (bsp->dleafs[i + 1].cluster == clusternum) {
|
||||
bsp->dleafs[i + 1].visofs = visofs;
|
||||
|
|
|
|||
Loading…
Reference in New Issue