light: remove hack which disable vis culling inside liquids
instead, implement the equivalent by bridging the PVS across opaque liquid faces
This commit is contained in:
parent
6b707b6d5a
commit
64d6cbad4f
|
|
@ -655,6 +655,35 @@ void DecompressVis(const uint8_t *in, const uint8_t *inend, uint8_t *out, uint8_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the visdata so everything that:
|
||||||
|
* everything that can see into cluster a, can also see into cluster b + its pvs
|
||||||
|
*/
|
||||||
|
static void ConnectLeafVisibilityDirectional(const mbsp_t *bsp, std::unordered_map<int, std::vector<uint8_t>> &all_visdata, int a, int b)
|
||||||
|
{
|
||||||
|
Q_assert(bsp->loadversion->game->id == GAME_QUAKE_II);
|
||||||
|
|
||||||
|
if (a < 0)
|
||||||
|
return;
|
||||||
|
if (b < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const std::vector<uint8_t> b_pvs_copy = all_visdata.at(b);
|
||||||
|
|
||||||
|
for (auto &[cluster, pvs] : all_visdata) {
|
||||||
|
// can cluster see into `a`?
|
||||||
|
if (pvs[a >> 3] & (1 << (a & 7))) {
|
||||||
|
// update `pvs` to see into `b`
|
||||||
|
pvs[b >> 3] |= (1 << (b & 7));
|
||||||
|
|
||||||
|
// update `pvs` to see into b's pvs
|
||||||
|
for (int i = 0; i < pvs.size(); ++i) {
|
||||||
|
pvs[i] |= b_pvs_copy[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decompress visdata for the entire map, and returns a map of:
|
* Decompress visdata for the entire map, and returns a map of:
|
||||||
*
|
*
|
||||||
|
|
@ -666,6 +695,8 @@ void DecompressVis(const uint8_t *in, const uint8_t *inend, uint8_t *out, uint8_
|
||||||
*/
|
*/
|
||||||
std::unordered_map<int, std::vector<uint8_t>> DecompressAllVis(const mbsp_t *bsp, bool trans_water)
|
std::unordered_map<int, std::vector<uint8_t>> DecompressAllVis(const mbsp_t *bsp, bool trans_water)
|
||||||
{
|
{
|
||||||
|
logging::funcheader();
|
||||||
|
|
||||||
std::unordered_map<int, std::vector<uint8_t>> result;
|
std::unordered_map<int, std::vector<uint8_t>> result;
|
||||||
|
|
||||||
const size_t decompressed_size = DecompressedVisSize(bsp);
|
const size_t decompressed_size = DecompressedVisSize(bsp);
|
||||||
|
|
@ -710,6 +741,47 @@ std::unordered_map<int, std::vector<uint8_t>> DecompressAllVis(const mbsp_t *bsp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (trans_water && bsp->loadversion->game->id == GAME_QUAKE_II) {
|
||||||
|
// FIXME: implement non q2 path
|
||||||
|
|
||||||
|
// we want to make all visblocking liquids transparent
|
||||||
|
|
||||||
|
std::set<std::pair<int, int>> cluster_pairs_to_unify;
|
||||||
|
|
||||||
|
const auto &world = bsp->dmodels[0];
|
||||||
|
for (int i = world.firstface; i < (world.firstface + world.numfaces); ++i) {
|
||||||
|
const mface_t &face = bsp->dfaces[i];
|
||||||
|
|
||||||
|
qvec3f centroid = Face_Centroid(bsp, &face);
|
||||||
|
auto plane = Face_Plane(bsp, &face);
|
||||||
|
|
||||||
|
auto *top = BSP_FindLeafAtPoint(bsp, &world, centroid + (plane.normal * 0.5));
|
||||||
|
auto *bottom = BSP_FindLeafAtPoint(bsp, &world, centroid - (plane.normal * 0.5));
|
||||||
|
|
||||||
|
contentflags_t top_contents{top->contents};
|
||||||
|
contentflags_t bottom_contents{bottom->contents};
|
||||||
|
|
||||||
|
// this weakens the pvs culling effectiveness, so only do it if top and bottom can't see each other
|
||||||
|
// FIXME: would be better to do a PVS check (especially for Q1)
|
||||||
|
if (Face_IsTranslucent(bsp, &face)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top_contents.is_empty(bsp->loadversion->game) && bottom_contents.is_liquid(bsp->loadversion->game)) {
|
||||||
|
cluster_pairs_to_unify.insert(std::make_pair(top->cluster, bottom->cluster));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cluster_pairs_to_unify.size()) {
|
||||||
|
logging::print("{:9} cluster pairs PVS connected to make liquid translucent\n", cluster_pairs_to_unify.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto [top, bottom] : cluster_pairs_to_unify) {
|
||||||
|
ConnectLeafVisibilityDirectional(bsp, result, top, bottom);
|
||||||
|
ConnectLeafVisibilityDirectional(bsp, result, bottom, top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -513,16 +513,6 @@ static void CalcPvs(const mbsp_t *bsp, lightsurf_t *lightsurf)
|
||||||
/* copy the pvs for this leaf into pointpvs */
|
/* copy the pvs for this leaf into pointpvs */
|
||||||
Mod_LeafPvs(bsp, leaf, pointpvs);
|
Mod_LeafPvs(bsp, leaf, pointpvs);
|
||||||
|
|
||||||
if (bsp->loadversion->game->contents_are_liquid({leaf->contents})) {
|
|
||||||
// hack for when the sample point might be in an opaque liquid, blocking vis,
|
|
||||||
// but we typically want light to pass through these.
|
|
||||||
// see also VisCullEntity() which handles the case when the light emitter is in liquid.
|
|
||||||
for (int j = 0; j < pvssize; j++) {
|
|
||||||
lightsurf->pvs[j] |= 0xff;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* merge the pvs for this sample point into lightsurf->pvs */
|
/* merge the pvs for this sample point into lightsurf->pvs */
|
||||||
for (int j = 0; j < pvssize; j++) {
|
for (int j = 0; j < pvssize; j++) {
|
||||||
lightsurf->pvs[j] |= pointpvs[j];
|
lightsurf->pvs[j] |= pointpvs[j];
|
||||||
|
|
@ -1090,11 +1080,7 @@ static bool VisCullEntity(const mbsp_t *bsp, const std::vector<uint8_t> &pvs, co
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bsp->loadversion->game->contents_are_solid({entleaf->contents}) ||
|
if (bsp->loadversion->game->contents_are_solid({entleaf->contents}) ||
|
||||||
bsp->loadversion->game->contents_are_sky({entleaf->contents}) ||
|
bsp->loadversion->game->contents_are_sky({entleaf->contents})) {
|
||||||
bsp->loadversion->game->contents_are_liquid({entleaf->contents})) {
|
|
||||||
// the liquid case is because entleaf->contents might be in an opaque liquid,
|
|
||||||
// which we typically want light to pass through, but visdata would report that
|
|
||||||
// there's no visibility across the opaque liquid. so, skip culling and do the raytracing.
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue