diff --git a/include/common/bspfile.hh b/include/common/bspfile.hh index 9213235d..def1f39b 100644 --- a/include/common/bspfile.hh +++ b/include/common/bspfile.hh @@ -355,6 +355,8 @@ typedef struct { #define TEX_NOMINLIGHT (1ULL << 54) /* opt out of minlight on this face */ #define TEX_NOEXPAND (1ULL << 55) /* don't expand this face for larger clip hulls */ #define TEX_LIGHTIGNORE (1ULL << 56) +#define TEX_LIGHT_ALPHA_SHIFT 57 +#define TEX_LIGHT_ALPHA_MASK (127ULL << TEX_LIGHT_ALPHA_SHIFT) /* 7 bit unsigned value. custom opacity */ // Q2 Texture flags. #define Q2_SURF_LIGHT 0x1 // value will hold the light strength diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index 001e99fc..eff7c070 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -144,7 +144,8 @@ #define TEX_NOMINLIGHT (1ULL << 54) /* opt out of minlight on this face */ #define TEX_NOEXPAND (1ULL << 55) /* don't expand this face for larger clip hulls */ #define TEX_LIGHTIGNORE (1ULL << 56) - +#define TEX_LIGHT_ALPHA_SHIFT 57 +#define TEX_LIGHT_ALPHA_MASK (127ULL << TEX_LIGHT_ALPHA_SHIFT) /* 7 bit unsigned value. custom opacity */ /* * The quality of the bsp output is highly sensitive to these epsilon values. * Notes: diff --git a/light/trace_embree.cc b/light/trace_embree.cc index eb138cce..bfd234ca 100644 --- a/light/trace_embree.cc +++ b/light/trace_embree.cc @@ -301,9 +301,7 @@ Embree_FilterFuncN(int* valid, // test fence textures and glass const bsp2_dface_t *face = Embree_LookupFace(geomID, primID); - - - float alpha = hit_modelinfo->alpha.floatValue(); + float alpha = Face_Alpha(hit_modelinfo, face); //mxd bool isFence, isGlass; @@ -561,6 +559,26 @@ MakeFaces(const mbsp_t *bsp, const dmodel_t *model) return result; } +/** + * Returns 1.0 unless a custom alpha value is set. + * The priority is: "_light_alpha" (read from extended_texinfo_flags), then "alpha" + */ +static float +Face_Alpha(const modelinfo_t *modelinfo, const bsp2_dface_t *face) +{ + const uint64_t extended_flags = extended_texinfo_flags[face->texinfo]; + + // for _light_alpha, 0 is considered unset + const uint64_t alpha_u7 = (extended_flags >> TEX_LIGHT_ALPHA_SHIFT) & 127ULL; + const float alpha_float = (float)alpha_u7 / (float)127; + if (alpha_float != 0.0f) { + return alpha_float; + } + + // next check modelinfo alpha (defaults to 1.0) + return modelinfo->alpha.floatValue(); +} + void Embree_TraceInit(const mbsp_t *bsp) { @@ -602,8 +620,9 @@ Embree_TraceInit(const mbsp_t *bsp) if(bsp->loadversion == Q2_BSPVERSION && (contents & Q2_SURF_NODRAW) && !(contents & Q2_SURF_SKY)) continue; - // handle glass - if (model->alpha.floatValue() < 1.0f + // handle glass / water + const float alpha = Face_Alpha(model, face); + if (alpha < 1.0f || (bsp->loadversion == Q2_BSPVERSION && (contents & Q2_SURF_TRANSLUCENT))) { //mxd. Both fence and transparent textures are done using SURF_TRANS flags in Q2 filterfaces.push_back(face); continue; diff --git a/qbsp/map.cc b/qbsp/map.cc index dad8ab08..1401f6ed 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -359,7 +359,7 @@ FindTexinfoEnt(mtexinfo_t *texinfo, const mapentity_t *entity) // handle "_minlight" const vec_t minlight = atof(ValueForKey(entity, "_minlight")); if (minlight > 0) { - const uint8_t minlight_byte = (uint8_t) qmax(0, qmin(255, (int)rint(minlight))); + const uint64_t minlight_byte = (uint64_t) qmax(0, qmin(255, (int)rint(minlight))); flags |= (minlight_byte << TEX_MINLIGHT_SHIFT); } @@ -383,6 +383,14 @@ FindTexinfoEnt(mtexinfo_t *texinfo, const mapentity_t *entity) flags |= (b_byte << TEX_MINLIGHT_COLOR_B_SHIFT); } } + + // handle "_light_alpha" + const vec_t lightalpha = atof(ValueForKey(entity, "_light_alpha")); + if (lightalpha != 0.0) { + const uint64_t lightalpha_u7 = (uint64_t) qmax(0, qmin(127, (int)rint(lightalpha * 127.0))); + Q_assert(lightalpha_u7 < 128u); + flags |= (lightalpha_u7 << TEX_LIGHT_ALPHA_SHIFT); + } return FindTexinfo(texinfo, flags); }