cache anything related to triangle-face info in a single struct that we access per ray
This commit is contained in:
parent
8fe525f5b2
commit
033a84cac8
|
|
@ -74,6 +74,7 @@ public:
|
|||
float anglescale;
|
||||
int style;
|
||||
std::string suntexture;
|
||||
const img::texture *suntexture_value;
|
||||
};
|
||||
|
||||
/* for vanilla this would be 18. some engines allow higher limits though, which will be needed if we're scaling lightmap
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <common/log.hh>
|
||||
#include <common/threads.hh>
|
||||
#include <common/polylib.hh>
|
||||
#include <common/imglib.hh>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
|
@ -42,7 +43,7 @@ enum class hittype_t : uint8_t
|
|||
};
|
||||
|
||||
uint32_t clamp_texcoord(vec_t in, uint32_t width);
|
||||
qvec4b SampleTexture(const mface_t *face, const mbsp_t *bsp, const qvec3d &point); // mxd. Palette index -> RGBA
|
||||
qvec4b SampleTexture(const mface_t *face, const mtexinfo_t *tex, const img::texture *texture, const mbsp_t *bsp, const qvec3d &point); // mxd. Palette index -> RGBA
|
||||
|
||||
class modelinfo_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -142,13 +142,27 @@ struct ray_source_info : public RTCIntersectContext
|
|||
}
|
||||
};
|
||||
|
||||
class sceneinfo
|
||||
struct triinfo
|
||||
{
|
||||
const modelinfo_t *modelinfo;
|
||||
const mface_t *face;
|
||||
const mtexinfo_t *texinfo;
|
||||
|
||||
const img::texture *texture;
|
||||
float alpha;
|
||||
bool is_fence, is_glass;
|
||||
|
||||
bool shadowworldonly;
|
||||
bool shadowself;
|
||||
bool switchableshadow;
|
||||
int32_t switchshadstyle;
|
||||
};
|
||||
|
||||
struct sceneinfo
|
||||
{
|
||||
public:
|
||||
unsigned geomID;
|
||||
|
||||
std::vector<const mface_t *> triToFace;
|
||||
std::vector<const modelinfo_t *> triToModelinfo;
|
||||
std::vector<triinfo> triInfo;
|
||||
};
|
||||
|
||||
extern sceneinfo skygeom; // sky. always occludes.
|
||||
|
|
@ -240,17 +254,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
inline const mface_t *getPushedRayHitFace(size_t j)
|
||||
inline const triinfo *getPushedRayHitFaceInfo(size_t j)
|
||||
{
|
||||
Q_assert(j < _maxrays);
|
||||
|
||||
const RTCRayHit &ray = _rays[j];
|
||||
|
||||
if (ray.hit.geomID == RTC_INVALID_GEOMETRY_ID)
|
||||
if (ray.hit.geomID == RTC_INVALID_GEOMETRY_ID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const sceneinfo &si = Embree_SceneinfoForGeomID(ray.hit.geomID);
|
||||
const mface_t *face = si.triToFace.at(ray.hit.primID);
|
||||
const triinfo *face = &si.triInfo.at(ray.hit.primID);
|
||||
Q_assert(face != nullptr);
|
||||
|
||||
return face;
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ static void AddSun(const settings::worldspawn_keys &cfg, const qvec3d &sunvec, v
|
|||
sun.dirt = Dirt_ResolveFlag(cfg, dirtInt);
|
||||
sun.style = style;
|
||||
sun.suntexture = suntexture;
|
||||
sun.suntexture_value = img::find(suntexture);
|
||||
|
||||
// fmt::print( "sun is using vector {} {} {} light {} color {} {} {} anglescale {} dirt {} resolved to {}\n",
|
||||
// sun->sunvec[0], sun->sunvec[1], sun->sunvec[2], sun->sunlight.light,
|
||||
|
|
|
|||
|
|
@ -1620,11 +1620,9 @@ static void LightFace_Sky(const sun_t *sun, lightsurf_t *lightsurf, lightmapdict
|
|||
}
|
||||
|
||||
// check if we hit the wrong texture
|
||||
// TODO: this could be faster!
|
||||
if (!sun->suntexture.empty()) {
|
||||
const mface_t *face = rs.getPushedRayHitFace(j);
|
||||
const char *facetex = Face_TextureName(lightsurf->bsp, face);
|
||||
if (sun->suntexture != facetex) {
|
||||
if (sun->suntexture_value) {
|
||||
const triinfo *face = rs.getPushedRayHitFaceInfo(j);
|
||||
if (sun->suntexture_value != face->texture) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,16 +76,12 @@ uint32_t clamp_texcoord(vec_t in, uint32_t width)
|
|||
}
|
||||
}
|
||||
|
||||
qvec4b SampleTexture(const mface_t *face, const mbsp_t *bsp, const qvec3d &point)
|
||||
qvec4b SampleTexture(const mface_t *face, const mtexinfo_t *tex, const img::texture *texture, const mbsp_t *bsp, const qvec3d &point)
|
||||
{
|
||||
const auto *texture = Face_Texture(bsp, face);
|
||||
|
||||
if (texture == nullptr || !texture->meta.width) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const mtexinfo_t *tex = &bsp->texinfo[face->texinfo];
|
||||
|
||||
qvec2d texcoord = WorldToTexCoord(point, tex);
|
||||
|
||||
const uint32_t x = clamp_texcoord(texcoord[0], texture->meta.width);
|
||||
|
|
|
|||
|
|
@ -116,8 +116,37 @@ sceneinfo CreateGeometry(
|
|||
tri->v2 = Face_VertexAtIndex(bsp, face, 0);
|
||||
tri_index++;
|
||||
|
||||
s.triToFace.push_back(face);
|
||||
s.triToModelinfo.push_back(modelinfo);
|
||||
triinfo info;
|
||||
|
||||
info.face = face;
|
||||
info.modelinfo = modelinfo;
|
||||
info.texinfo = &bsp->texinfo[face->texinfo];
|
||||
|
||||
info.texture = Face_Texture(bsp, face);
|
||||
|
||||
info.shadowworldonly = modelinfo->shadowworldonly.boolValue();
|
||||
info.shadowself = modelinfo->shadowself.boolValue();
|
||||
info.switchableshadow = modelinfo->switchableshadow.boolValue();
|
||||
info.switchshadstyle = modelinfo->switchshadstyle.value();
|
||||
|
||||
info.alpha = Face_Alpha(modelinfo, face);
|
||||
|
||||
// mxd
|
||||
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
|
||||
const int surf_flags = Face_ContentsOrSurfaceFlags(bsp, face);
|
||||
info.is_fence = ((surf_flags & Q2_SURF_TRANSLUCENT) ==
|
||||
Q2_SURF_TRANSLUCENT); // KMQuake 2-specific. Use texture alpha chanel when both flags are set.
|
||||
info.is_glass = !info.is_fence && (surf_flags & Q2_SURF_TRANSLUCENT);
|
||||
if (info.is_glass) {
|
||||
info.alpha = (surf_flags & Q2_SURF_TRANS33 ? 0.33f : 0.66f);
|
||||
}
|
||||
} else {
|
||||
const char *name = Face_TextureName(bsp, face);
|
||||
info.is_fence = (name[0] == '{');
|
||||
info.is_glass = (info.alpha < 1.0f);
|
||||
}
|
||||
|
||||
s.triInfo.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -202,16 +231,10 @@ void ErrorCallback(void *userptr, const RTCError code, const char *str)
|
|||
fmt::print("RTC Error {}: {}\n", code, str);
|
||||
}
|
||||
|
||||
const mface_t *Embree_LookupFace(unsigned int geomID, unsigned int primID)
|
||||
const triinfo &Embree_LookupTriangleInfo(unsigned int geomID, unsigned int primID)
|
||||
{
|
||||
const sceneinfo &info = Embree_SceneinfoForGeomID(geomID);
|
||||
return info.triToFace.at(primID);
|
||||
}
|
||||
|
||||
const modelinfo_t *Embree_LookupModelinfo(unsigned int geomID, unsigned int primID)
|
||||
{
|
||||
const sceneinfo &info = Embree_SceneinfoForGeomID(geomID);
|
||||
return info.triToModelinfo.at(primID);
|
||||
return info.triInfo.at(primID);
|
||||
}
|
||||
|
||||
inline qvec3f Embree_RayEndpoint(RTCRayN *ray, const qvec3f &dir, size_t N, size_t i)
|
||||
|
|
@ -260,15 +283,16 @@ static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
|||
const unsigned rayIndex = rayID;
|
||||
|
||||
const modelinfo_t *source_modelinfo = rsi->self;
|
||||
const modelinfo_t *hit_modelinfo = Embree_LookupModelinfo(geomID, primID);
|
||||
if (!hit_modelinfo) {
|
||||
const triinfo &hit_triinfo = Embree_LookupTriangleInfo(geomID, primID);
|
||||
|
||||
if (!hit_triinfo.modelinfo) {
|
||||
// we hit a "skip" face with no associated model
|
||||
// reject hit (???)
|
||||
valid[i] = INVALID;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hit_modelinfo->shadowworldonly.boolValue()) {
|
||||
if (hit_triinfo.shadowworldonly) {
|
||||
// we hit "_shadowworldonly" "1" geometry. Ignore the hit unless we are from world.
|
||||
if (!source_modelinfo || !source_modelinfo->isWorld()) {
|
||||
// reject hit
|
||||
|
|
@ -277,20 +301,20 @@ static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
|||
}
|
||||
}
|
||||
|
||||
if (hit_modelinfo->shadowself.boolValue()) {
|
||||
if (hit_triinfo.shadowself) {
|
||||
// only casts shadows on itself
|
||||
if (source_modelinfo != hit_modelinfo) {
|
||||
if (source_modelinfo != hit_triinfo.modelinfo) {
|
||||
// reject hit
|
||||
valid[i] = INVALID;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (hit_modelinfo->switchableshadow.boolValue()) {
|
||||
if (hit_triinfo.switchableshadow) {
|
||||
// we hit a dynamic shadow caster. reject the hit, but store the
|
||||
// info about what we hit.
|
||||
|
||||
const int style = hit_modelinfo->switchshadstyle.value();
|
||||
const int style = hit_triinfo.switchshadstyle;
|
||||
|
||||
AddDynamicOccluderToRay(context, rayIndex, style);
|
||||
|
||||
|
|
@ -299,32 +323,16 @@ static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
|||
continue;
|
||||
}
|
||||
|
||||
float alpha = hit_triinfo.alpha;
|
||||
|
||||
// test fence textures and glass
|
||||
const mface_t *face = Embree_LookupFace(geomID, primID);
|
||||
float alpha = Face_Alpha(hit_modelinfo, face);
|
||||
|
||||
// mxd
|
||||
bool isFence, isGlass;
|
||||
if (bsp_static->loadversion->game->id == GAME_QUAKE_II) {
|
||||
const int surf_flags = Face_ContentsOrSurfaceFlags(bsp_static, face);
|
||||
isFence = ((surf_flags & Q2_SURF_TRANSLUCENT) ==
|
||||
Q2_SURF_TRANSLUCENT); // KMQuake 2-specific. Use texture alpha chanel when both flags are set.
|
||||
isGlass = !isFence && (surf_flags & Q2_SURF_TRANSLUCENT);
|
||||
if (isGlass)
|
||||
alpha = (surf_flags & Q2_SURF_TRANS33 ? 0.33f : 0.66f);
|
||||
} else {
|
||||
const char *name = Face_TextureName(bsp_static, face);
|
||||
isFence = (name[0] == '{');
|
||||
isGlass = (alpha < 1.0f);
|
||||
}
|
||||
|
||||
if (isFence || isGlass) {
|
||||
if (hit_triinfo.is_fence || hit_triinfo.is_glass) {
|
||||
qvec3f rayDir =
|
||||
qv::normalize(qvec3f{RTCRayN_dir_x(ray, N, i), RTCRayN_dir_y(ray, N, i), RTCRayN_dir_z(ray, N, i)});
|
||||
qvec3f hitpoint = Embree_RayEndpoint(ray, rayDir, N, i);
|
||||
const qvec4b sample = SampleTexture(face, bsp_static, hitpoint); // mxd. Palette index -> color_rgba
|
||||
const qvec4b sample = SampleTexture(hit_triinfo.face, hit_triinfo.texinfo, hit_triinfo.texture, bsp_static, hitpoint); // mxd. Palette index -> color_rgba
|
||||
|
||||
if (isGlass) {
|
||||
if (hit_triinfo.is_glass) {
|
||||
// hit glass...
|
||||
|
||||
// mxd. Adjust alpha by texture alpha?
|
||||
|
|
@ -347,7 +355,7 @@ static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (isFence) {
|
||||
if (hit_triinfo.is_fence) {
|
||||
if (sample[3] < 255) {
|
||||
// reject hit
|
||||
valid[i] = INVALID;
|
||||
|
|
@ -620,7 +628,7 @@ hitresult_t TestSky(const qvec3d &start, const qvec3d &dirn, const modelinfo_t *
|
|||
if (face_out) {
|
||||
if (hit_sky) {
|
||||
const sceneinfo &si = Embree_SceneinfoForGeomID(ray.hit.geomID);
|
||||
*face_out = si.triToFace.at(ray.hit.primID);
|
||||
*face_out = si.triInfo.at(ray.hit.primID).face;
|
||||
} else {
|
||||
*face_out = nullptr;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue