light: support embree4 in addition to 3
This commit is contained in:
parent
d5ffbd9d33
commit
db0951dc40
|
|
@ -145,6 +145,11 @@ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15)
|
||||||
|
|
||||||
find_package(TBB REQUIRED)
|
find_package(TBB REQUIRED)
|
||||||
|
|
||||||
|
find_package(embree REQUIRED)
|
||||||
|
if (embree_VERSION_MAJOR EQUAL 4)
|
||||||
|
add_compile_definitions(HAVE_EMBREE4)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(TEST_QUAKE_MAP_EXPORT_DIR "" CACHE PATH "When running unit tests, export Quake maps to this directory (useful for testing in game)")
|
set(TEST_QUAKE_MAP_EXPORT_DIR "" CACHE PATH "When running unit tests, export Quake maps to this directory (useful for testing in game)")
|
||||||
set(TEST_QUAKE2_MAP_EXPORT_DIR "" CACHE PATH "When running unit tests, export Quake 2 maps to this directory (useful for testing in game)")
|
set(TEST_QUAKE2_MAP_EXPORT_DIR "" CACHE PATH "When running unit tests, export Quake 2 maps to this directory (useful for testing in game)")
|
||||||
set(TEST_HEXEN2_MAP_EXPORT_DIR "" CACHE PATH "When running unit tests, export Hexen 2 maps to this directory (useful for testing in game)")
|
set(TEST_HEXEN2_MAP_EXPORT_DIR "" CACHE PATH "When running unit tests, export Hexen 2 maps to this directory (useful for testing in game)")
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,13 @@ public:
|
||||||
inline void clearPushedRays() { _numrays = 0; }
|
inline void clearPushedRays() { _numrays = 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_EMBREE4
|
||||||
|
#include <embree4/rtcore.h>
|
||||||
|
#include <embree4/rtcore_ray.h>
|
||||||
|
#else
|
||||||
#include <embree3/rtcore.h>
|
#include <embree3/rtcore.h>
|
||||||
#include <embree3/rtcore_ray.h>
|
#include <embree3/rtcore_ray.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
extern RTCScene scene;
|
extern RTCScene scene;
|
||||||
|
|
||||||
|
|
@ -139,13 +144,22 @@ inline RTCRayHit SetupRay(unsigned rayindex, const qvec3d &start, const qvec3d &
|
||||||
|
|
||||||
class light_t;
|
class light_t;
|
||||||
|
|
||||||
struct ray_source_info : public RTCIntersectContext
|
struct ray_source_info : public
|
||||||
|
#ifdef HAVE_EMBREE4
|
||||||
|
RTCRayQueryContext
|
||||||
|
#else
|
||||||
|
RTCIntersectContext
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
raystream_embree_common_t *raystream; // may be null if this ray is not from a ray stream
|
raystream_embree_common_t *raystream; // may be null if this ray is not from a ray stream
|
||||||
const modelinfo_t *self;
|
const modelinfo_t *self;
|
||||||
int shadowmask;
|
int shadowmask;
|
||||||
|
|
||||||
ray_source_info(raystream_embree_common_t *raystream_, const modelinfo_t *self_, int shadowmask_);
|
ray_source_info(raystream_embree_common_t *raystream_, const modelinfo_t *self_, int shadowmask_);
|
||||||
|
#ifdef HAVE_EMBREE4
|
||||||
|
RTCIntersectArguments setup_intersection_arguments();
|
||||||
|
RTCOccludedArguments setup_occluded_arguments();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct triinfo
|
struct triinfo
|
||||||
|
|
@ -238,7 +252,14 @@ public:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ray_source_info ctx2(this, self, shadowmask);
|
ray_source_info ctx2(this, self, shadowmask);
|
||||||
|
|
||||||
|
#ifdef HAVE_EMBREE4
|
||||||
|
RTCIntersectArguments embree4_args = ctx2.setup_intersection_arguments();
|
||||||
|
for (int i = 0; i < _numrays; ++i)
|
||||||
|
rtcIntersect1(scene, &_rays[i], &embree4_args);
|
||||||
|
#else
|
||||||
rtcIntersect1M(scene, &ctx2, _rays.data(), _numrays, sizeof(_rays[0]));
|
rtcIntersect1M(scene, &ctx2, _rays.data(), _numrays, sizeof(_rays[0]));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline qvec3d getPushedRayDir(size_t j) { return {_rays[j].ray.dir_x, _rays[j].ray.dir_y, _rays[j].ray.dir_z}; }
|
inline qvec3d getPushedRayDir(size_t j) { return {_rays[j].ray.dir_x, _rays[j].ray.dir_y, _rays[j].ray.dir_z}; }
|
||||||
|
|
@ -312,7 +333,13 @@ public:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ray_source_info ctx2(this, self, shadowmask);
|
ray_source_info ctx2(this, self, shadowmask);
|
||||||
|
#ifdef HAVE_EMBREE4
|
||||||
|
RTCOccludedArguments embree4_args = ctx2.setup_occluded_arguments();
|
||||||
|
for (int i = 0; i < _numrays; ++i)
|
||||||
|
rtcOccluded1(scene, &_rays[i], &embree4_args);
|
||||||
|
#else
|
||||||
rtcOccluded1M(scene, &ctx2, _rays.data(), _numrays, sizeof(_rays[0]));
|
rtcOccluded1M(scene, &ctx2, _rays.data(), _numrays, sizeof(_rays[0]));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool getPushedRayOccluded(size_t j) { return (_rays[j].tfar < 0.0f); }
|
inline bool getPushedRayOccluded(size_t j) { return (_rays[j].tfar < 0.0f); }
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ set(LIGHT_SOURCES
|
||||||
surflight.cc
|
surflight.cc
|
||||||
${LIGHT_INCLUDES})
|
${LIGHT_INCLUDES})
|
||||||
|
|
||||||
FIND_PACKAGE(embree 3.0 REQUIRED)
|
|
||||||
|
|
||||||
if (embree_FOUND)
|
if (embree_FOUND)
|
||||||
MESSAGE(STATUS "Embree library found: ${EMBREE_LIBRARY}")
|
MESSAGE(STATUS "Embree library found: ${EMBREE_LIBRARY}")
|
||||||
INCLUDE_DIRECTORIES(${EMBREE_INCLUDE_DIRS})
|
INCLUDE_DIRECTORIES(${EMBREE_INCLUDE_DIRS})
|
||||||
|
|
|
||||||
|
|
@ -289,14 +289,13 @@ inline qvec3f Embree_RayEndpoint(RTCRayN *ray, const qvec3f &dir, size_t N, size
|
||||||
return org + (dir * tfar);
|
return org + (dir * tfar);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddGlassToRay(RTCIntersectContext *context, unsigned rayIndex, float opacity, const qvec3d &glasscolor);
|
static void AddGlassToRay(ray_source_info *context, unsigned rayIndex, float opacity, const qvec3d &glasscolor);
|
||||||
static void AddDynamicOccluderToRay(RTCIntersectContext *context, unsigned rayIndex, int style);
|
static void AddDynamicOccluderToRay(ray_source_info *context, unsigned rayIndex, int style);
|
||||||
|
|
||||||
// called to evaluate transparency
|
// called to evaluate transparency
|
||||||
static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
||||||
{
|
{
|
||||||
int *const valid = args->valid;
|
int *const valid = args->valid;
|
||||||
RTCIntersectContext *const context = args->context;
|
|
||||||
struct RTCRayN *const ray = args->ray;
|
struct RTCRayN *const ray = args->ray;
|
||||||
struct RTCHitN *const potentialHit = args->hit;
|
struct RTCHitN *const potentialHit = args->hit;
|
||||||
const unsigned int N = args->N;
|
const unsigned int N = args->N;
|
||||||
|
|
@ -304,7 +303,7 @@ static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
||||||
const int VALID = -1;
|
const int VALID = -1;
|
||||||
const int INVALID = 0;
|
const int INVALID = 0;
|
||||||
|
|
||||||
const ray_source_info *rsi = static_cast<const ray_source_info *>(context);
|
ray_source_info *rsi = static_cast<ray_source_info *>(args->context);
|
||||||
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
for (size_t i = 0; i < N; i++) {
|
||||||
if (valid[i] != VALID) {
|
if (valid[i] != VALID) {
|
||||||
|
|
@ -359,7 +358,7 @@ static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
||||||
|
|
||||||
const int style = hit_triinfo.switchshadstyle;
|
const int style = hit_triinfo.switchshadstyle;
|
||||||
|
|
||||||
AddDynamicOccluderToRay(context, rayIndex, style);
|
AddDynamicOccluderToRay(rsi, rayIndex, style);
|
||||||
|
|
||||||
// reject hit
|
// reject hit
|
||||||
valid[i] = INVALID;
|
valid[i] = INVALID;
|
||||||
|
|
@ -391,7 +390,7 @@ static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
||||||
// only pick up the color of the glass on the _exiting_ side of the glass.
|
// only pick up the color of the glass on the _exiting_ side of the glass.
|
||||||
// (we currently trace "backwards", from surface point --> light source)
|
// (we currently trace "backwards", from surface point --> light source)
|
||||||
if (raySurfaceCosAngle < 0) {
|
if (raySurfaceCosAngle < 0) {
|
||||||
AddGlassToRay(context, rayIndex, alpha, sample.xyz() * (1.0 / 255.0));
|
AddGlassToRay(rsi, rayIndex, alpha, sample.xyz() * (1.0 / 255.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// reject hit
|
// reject hit
|
||||||
|
|
@ -419,14 +418,13 @@ static void Embree_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
||||||
static void PerRay_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
static void PerRay_FilterFuncN(const struct RTCFilterFunctionNArguments *args)
|
||||||
{
|
{
|
||||||
int *const valid = args->valid;
|
int *const valid = args->valid;
|
||||||
RTCIntersectContext *const context = args->context;
|
|
||||||
struct RTCHitN *const potentialHit = args->hit;
|
struct RTCHitN *const potentialHit = args->hit;
|
||||||
const unsigned int N = args->N;
|
const unsigned int N = args->N;
|
||||||
|
|
||||||
const int VALID = -1;
|
const int VALID = -1;
|
||||||
const int INVALID = 0;
|
const int INVALID = 0;
|
||||||
|
|
||||||
auto *rsi = static_cast<const ray_source_info *>(context);
|
auto *rsi = static_cast<ray_source_info *>(args->context);
|
||||||
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
for (size_t i = 0; i < N; i++) {
|
||||||
if (valid[i] != VALID) {
|
if (valid[i] != VALID) {
|
||||||
|
|
@ -656,9 +654,16 @@ void Embree_TraceInit(const mbsp_t *bsp)
|
||||||
logging::funcprint("Embree version: {}.{}.{}\n", ver_maj, ver_min, ver_pat);
|
logging::funcprint("Embree version: {}.{}.{}\n", ver_maj, ver_min, ver_pat);
|
||||||
|
|
||||||
scene = rtcNewScene(device);
|
scene = rtcNewScene(device);
|
||||||
|
#ifdef HAVE_EMBREE4
|
||||||
|
// necessary for RTCOccludedArguments::filter and RTCIntersectArguments::filter
|
||||||
|
// to work, which we use (see: ray_source_info::setup_intersection_arguments() and
|
||||||
|
// ray_source_info::setup_occluded_arguments())
|
||||||
|
rtcSetSceneFlags(scene, RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS);
|
||||||
|
#else
|
||||||
// we're using RTCIntersectContext::filter so it's required that we set
|
// we're using RTCIntersectContext::filter so it's required that we set
|
||||||
// RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION
|
// RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION
|
||||||
rtcSetSceneFlags(scene, RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION);
|
rtcSetSceneFlags(scene, RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION);
|
||||||
|
#endif
|
||||||
rtcSetSceneBuildQuality(scene, RTC_BUILD_QUALITY_HIGH);
|
rtcSetSceneBuildQuality(scene, RTC_BUILD_QUALITY_HIGH);
|
||||||
skygeom = CreateGeometry(bsp, device, scene, skyfaces);
|
skygeom = CreateGeometry(bsp, device, scene, skyfaces);
|
||||||
solidgeom = CreateGeometry(bsp, device, scene, solidfaces);
|
solidgeom = CreateGeometry(bsp, device, scene, solidfaces);
|
||||||
|
|
@ -677,9 +682,8 @@ void Embree_TraceInit(const mbsp_t *bsp)
|
||||||
logging::print("\t{} shadow-casting skip faces\n", skipwindings.size());
|
logging::print("\t{} shadow-casting skip faces\n", skipwindings.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddGlassToRay(RTCIntersectContext *context, unsigned rayIndex, float opacity, const qvec3d &glasscolor)
|
static void AddGlassToRay(ray_source_info *ctx, unsigned rayIndex, float opacity, const qvec3d &glasscolor)
|
||||||
{
|
{
|
||||||
ray_source_info *ctx = static_cast<ray_source_info *>(context);
|
|
||||||
raystream_embree_common_t *rs = ctx->raystream;
|
raystream_embree_common_t *rs = ctx->raystream;
|
||||||
|
|
||||||
if (rs == nullptr) {
|
if (rs == nullptr) {
|
||||||
|
|
@ -698,9 +702,8 @@ static void AddGlassToRay(RTCIntersectContext *context, unsigned rayIndex, float
|
||||||
rs->_ray_glass_opacity[rayIndex] = opacity;
|
rs->_ray_glass_opacity[rayIndex] = opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddDynamicOccluderToRay(RTCIntersectContext *context, unsigned rayIndex, int style)
|
static void AddDynamicOccluderToRay(ray_source_info *ctx, unsigned rayIndex, int style)
|
||||||
{
|
{
|
||||||
ray_source_info *ctx = static_cast<ray_source_info *>(context);
|
|
||||||
raystream_embree_common_t *rs = ctx->raystream;
|
raystream_embree_common_t *rs = ctx->raystream;
|
||||||
|
|
||||||
if (rs != nullptr) {
|
if (rs != nullptr) {
|
||||||
|
|
@ -713,12 +716,51 @@ ray_source_info::ray_source_info(raystream_embree_common_t *raystream_, const mo
|
||||||
self(self_),
|
self(self_),
|
||||||
shadowmask(shadowmask_)
|
shadowmask(shadowmask_)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_EMBREE4
|
||||||
|
rtcInitRayQueryContext(this);
|
||||||
|
#else
|
||||||
rtcInitIntersectContext(this);
|
rtcInitIntersectContext(this);
|
||||||
|
|
||||||
flags = RTC_INTERSECT_CONTEXT_FLAG_COHERENT;
|
flags = RTC_INTERSECT_CONTEXT_FLAG_COHERENT;
|
||||||
|
|
||||||
if (shadowmask != CHANNEL_MASK_DEFAULT) {
|
if (shadowmask != CHANNEL_MASK_DEFAULT) {
|
||||||
// non-default shadow mask means we have to use the slow path
|
// non-default shadow mask means we have to use the slow path
|
||||||
filter = PerRay_FilterFuncN;
|
filter = PerRay_FilterFuncN;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_EMBREE4
|
||||||
|
RTCIntersectArguments ray_source_info::setup_intersection_arguments()
|
||||||
|
{
|
||||||
|
RTCIntersectArguments result;
|
||||||
|
|
||||||
|
rtcInitIntersectArguments(&result);
|
||||||
|
if (shadowmask != CHANNEL_MASK_DEFAULT) {
|
||||||
|
// non-default shadow mask means we have to use the slow path
|
||||||
|
result.filter = PerRay_FilterFuncN;
|
||||||
|
result.flags = static_cast<RTCRayQueryFlags>(result.flags |
|
||||||
|
RTC_RAY_QUERY_FLAG_INVOKE_ARGUMENT_FILTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.context = this;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTCOccludedArguments ray_source_info::setup_occluded_arguments()
|
||||||
|
{
|
||||||
|
RTCOccludedArguments result;
|
||||||
|
|
||||||
|
rtcInitOccludedArguments(&result);
|
||||||
|
if (shadowmask != CHANNEL_MASK_DEFAULT) {
|
||||||
|
// non-default shadow mask means we have to use the slow path
|
||||||
|
result.filter = PerRay_FilterFuncN;
|
||||||
|
result.flags = static_cast<RTCRayQueryFlags>(result.flags |
|
||||||
|
RTC_RAY_QUERY_FLAG_INVOKE_ARGUMENT_FILTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.context = this;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -19,7 +19,6 @@ add_executable(lightpreview
|
||||||
|
|
||||||
set_target_properties(lightpreview PROPERTIES WIN32_EXECUTABLE YES)
|
set_target_properties(lightpreview PROPERTIES WIN32_EXECUTABLE YES)
|
||||||
|
|
||||||
find_package(embree 3.0 REQUIRED)
|
|
||||||
INCLUDE_DIRECTORIES(${EMBREE_INCLUDE_DIRS})
|
INCLUDE_DIRECTORIES(${EMBREE_INCLUDE_DIRS})
|
||||||
|
|
||||||
# HACK: Windows embree .dll's from https://github.com/embree/embree/releases ship with a tbb12.dll
|
# HACK: Windows embree .dll's from https://github.com/embree/embree/releases ship with a tbb12.dll
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ add_executable(tests
|
||||||
benchmark.cc
|
benchmark.cc
|
||||||
test_bsputil.cc)
|
test_bsputil.cc)
|
||||||
|
|
||||||
find_package(embree 3.0 REQUIRED)
|
|
||||||
INCLUDE_DIRECTORIES(${EMBREE_INCLUDE_DIRS})
|
INCLUDE_DIRECTORIES(${EMBREE_INCLUDE_DIRS})
|
||||||
|
|
||||||
# HACK: Windows embree .dll's from https://github.com/embree/embree/releases ship with a tbb12.dll
|
# HACK: Windows embree .dll's from https://github.com/embree/embree/releases ship with a tbb12.dll
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue