Light Linking: Select one of dedicated lights #107739
|
@ -8,6 +8,7 @@
|
|||
#include "kernel/integrator/shade_surface.h"
|
||||
#include "kernel/integrator/shadow_linking.h"
|
||||
#include "kernel/light/light.h"
|
||||
#include "kernel/sample/lcg.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -28,6 +29,11 @@ ccl_device bool shadow_linking_pick_light_intersection(KernelGlobals kg,
|
|||
const int last_object = INTEGRATOR_STATE(state, isect, object);
|
||||
const int last_type = INTEGRATOR_STATE(state, isect, type);
|
||||
|
||||
uint lcg_state = lcg_state_init(INTEGRATOR_STATE(state, path, rng_hash),
|
||||
INTEGRATOR_STATE(state, path, rng_offset),
|
||||
INTEGRATOR_STATE(state, path, sample),
|
||||
0x68bc21eb);
|
||||
|
||||
/* The lights_intersect() has a "refining" behavior: it chooses intersection closer to the
|
||||
* current intersection's distance. Hence initialize the fields which are accessed prior to
|
||||
* recording an intersection. */
|
||||
|
@ -36,22 +42,20 @@ ccl_device bool shadow_linking_pick_light_intersection(KernelGlobals kg,
|
|||
|
||||
// TODO: Support mesh emitters.
|
||||
|
||||
// TODO: Support multiple light sources.
|
||||
|
||||
// TODO: Distant lights.
|
||||
|
||||
// TODO: Only if ray is not fully occluded.
|
||||
|
||||
// TODO: What of the actual shadow ray hits the same light through a semi-transparent surface?
|
||||
|
||||
const int receiver_forward = light_link_receiver_forward(kg, state);
|
||||
const int num_hits = lights_intersect_shadow_linked(
|
||||
kg, ray, isect, last_prim, last_object, last_type, path_flag, receiver_forward, &lcg_state);
|
||||
|
||||
if (!lights_intersect_shadow_linked(
|
||||
kg, ray, isect, last_prim, last_object, last_type, path_flag, receiver_forward))
|
||||
{
|
||||
if (num_hits == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(state, shadow_link, dedicated_light_weight) = num_hits;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -82,7 +86,7 @@ ccl_device bool shadow_linking_intersect(KernelGlobals kg, IntegratorState state
|
|||
shadow_linking_store_last_primitives(state);
|
||||
|
||||
/* Write intersection result into global integrator state memory, so that the
|
||||
* shade_dedicated_light kernel can use it for calculation of the light sample, */
|
||||
* shade_dedicated_light kernel can use it for calculation of the light sample. */
|
||||
integrator_state_write_isect(state, &isect);
|
||||
|
||||
integrator_path_next(kg,
|
||||
|
|
|
@ -73,7 +73,8 @@ ccl_device void shadow_linking_shade(KernelGlobals kg, IntegratorState state)
|
|||
mis_weight = light_sample_mis_weight_forward_lamp(kg, state, path_flag, &ls, ray.P);
|
||||
}
|
||||
|
||||
const Spectrum bsdf_spectrum = light_eval * mis_weight;
|
||||
const Spectrum bsdf_spectrum = light_eval * mis_weight *
|
||||
INTEGRATOR_STATE(state, shadow_link, dedicated_light_weight);
|
||||
|
||||
shadow_linking_setup_ray_from_intersection(state, &ray, &isect);
|
||||
|
||||
|
|
|
@ -139,6 +139,7 @@ KERNEL_STRUCT_END(guiding)
|
|||
/******************************* Shadow linking *******************************/
|
||||
|
||||
KERNEL_STRUCT_BEGIN(shadow_link)
|
||||
KERNEL_STRUCT_MEMBER(shadow_link, float, dedicated_light_weight, KERNEL_FEATURE_SHADOW_LINKING)
|
||||
/* Copy of primitive and object from the last main path intersection. */
|
||||
KERNEL_STRUCT_MEMBER(shadow_link, int, last_isect_prim, KERNEL_FEATURE_SHADOW_LINKING)
|
||||
KERNEL_STRUCT_MEMBER(shadow_link, int, last_isect_object, KERNEL_FEATURE_SHADOW_LINKING)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "kernel/light/point.h"
|
||||
#include "kernel/light/spot.h"
|
||||
#include "kernel/light/triangle.h"
|
||||
#include "kernel/sample/lcg.h"
|
||||
|
||||
#include "kernel/sample/mapping.h"
|
||||
|
||||
|
@ -245,16 +246,23 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
|
|||
/* Intersect ray with individual light. */
|
||||
|
||||
template<bool is_main_path>
|
||||
ccl_device bool lights_intersect_impl(KernelGlobals kg,
|
||||
ccl_private const Ray *ccl_restrict ray,
|
||||
ccl_private Intersection *ccl_restrict isect,
|
||||
const int last_prim,
|
||||
const int last_object,
|
||||
const int last_type,
|
||||
const uint32_t path_flag,
|
||||
const uint8_t path_mnee,
|
||||
const int receiver_forward)
|
||||
ccl_device_forceinline int lights_intersect_impl(KernelGlobals kg,
|
||||
ccl_private const Ray *ccl_restrict ray,
|
||||
ccl_private Intersection *ccl_restrict isect,
|
||||
const int last_prim,
|
||||
const int last_object,
|
||||
const int last_type,
|
||||
const uint32_t path_flag,
|
||||
const uint8_t path_mnee,
|
||||
const int receiver_forward,
|
||||
ccl_private uint *lcg_state)
|
||||
{
|
||||
#ifdef __SHADOW_LINKING__
|
||||
const bool is_indirect_ray = !(path_flag & PATH_RAY_CAMERA);
|
||||
#endif
|
||||
|
||||
int num_hits = 0;
|
||||
|
||||
for (int lamp = 0; lamp < kernel_data.integrator.num_lights; lamp++) {
|
||||
const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp);
|
||||
|
||||
|
@ -290,7 +298,6 @@ ccl_device bool lights_intersect_impl(KernelGlobals kg,
|
|||
* lights. */
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_SHADOW_LINKING) {
|
||||
if (is_main_path) {
|
||||
const bool is_indirect_ray = !(path_flag & PATH_RAY_CAMERA);
|
||||
if (is_indirect_ray && kernel_data_fetch(lights, lamp).shadow_set_membership) {
|
||||
continue;
|
||||
}
|
||||
|
@ -299,7 +306,6 @@ ccl_device bool lights_intersect_impl(KernelGlobals kg,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __LIGHT_LINKING__
|
||||
|
@ -331,19 +337,39 @@ ccl_device bool lights_intersect_impl(KernelGlobals kg,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (t < isect->t &&
|
||||
!(last_prim == lamp && last_object == OBJECT_NONE && last_type == PRIMITIVE_LAMP))
|
||||
{
|
||||
isect->t = t;
|
||||
isect->u = u;
|
||||
isect->v = v;
|
||||
isect->type = PRIMITIVE_LAMP;
|
||||
isect->prim = lamp;
|
||||
isect->object = OBJECT_NONE;
|
||||
/* Avoid self-intersections. */
|
||||
if (last_prim == lamp && last_object == OBJECT_NONE && last_type == PRIMITIVE_LAMP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++num_hits;
|
||||
|
||||
#ifdef __SHADOW_LINKING__
|
||||
if (!is_main_path) {
|
||||
|
||||
/* The non-main rays are only raced by the dedicated light kernel, after the shadow linking
|
||||
* feature check. */
|
||||
kernel_assert(kernel_data.kernel_features & KERNEL_FEATURE_SHADOW_LINKING);
|
||||
|
||||
if ((isect->prim != PRIM_NONE) && (lcg_step_float(lcg_state) < 1.0f / num_hits)) {
|
||||
Sergey Sharybin
commented
I think this should actually be Edit: Sorry for the noise, was looking into the code while being a bit distracted by other tasks. it is actually probably correct, but need to review it with a bit more focused mind. I think this should actually be `lcg_step_float(lcg_state) > 1.0f / num_hits`
Edit: Sorry for the noise, was looking into the code while being a bit distracted by other tasks. it is actually probably correct, but need to review it with a bit more focused mind.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (t >= isect->t)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
isect->t = t;
|
||||
isect->u = u;
|
||||
isect->v = v;
|
||||
isect->type = PRIMITIVE_LAMP;
|
||||
isect->prim = lamp;
|
||||
isect->object = OBJECT_NONE;
|
||||
}
|
||||
|
||||
return isect->prim != PRIM_NONE;
|
||||
return num_hits;
|
||||
}
|
||||
|
||||
ccl_device bool lights_intersect(KernelGlobals kg,
|
||||
|
@ -358,18 +384,29 @@ ccl_device bool lights_intersect(KernelGlobals kg,
|
|||
const uint8_t path_mnee = INTEGRATOR_STATE(state, path, mnee);
|
||||
const int receiver_forward = light_link_receiver_forward(kg, state);
|
||||
|
||||
return lights_intersect_impl<true>(
|
||||
kg, ray, isect, last_prim, last_object, last_type, path_flag, path_mnee, receiver_forward);
|
||||
lights_intersect_impl<true>(kg,
|
||||
ray,
|
||||
isect,
|
||||
last_prim,
|
||||
last_object,
|
||||
last_type,
|
||||
path_flag,
|
||||
path_mnee,
|
||||
receiver_forward,
|
||||
nullptr);
|
||||
|
||||
return isect->prim != PRIM_NONE;
|
||||
}
|
||||
|
||||
ccl_device bool lights_intersect_shadow_linked(KernelGlobals kg,
|
||||
ccl_private const Ray *ccl_restrict ray,
|
||||
ccl_private Intersection *ccl_restrict isect,
|
||||
const int last_prim,
|
||||
const int last_object,
|
||||
const int last_type,
|
||||
const uint32_t path_flag,
|
||||
const int receiver_forward)
|
||||
ccl_device int lights_intersect_shadow_linked(KernelGlobals kg,
|
||||
ccl_private const Ray *ccl_restrict ray,
|
||||
ccl_private Intersection *ccl_restrict isect,
|
||||
const int last_prim,
|
||||
const int last_object,
|
||||
const int last_type,
|
||||
const uint32_t path_flag,
|
||||
const int receiver_forward,
|
||||
ccl_private uint *lcg_state)
|
||||
{
|
||||
return lights_intersect_impl<false>(kg,
|
||||
ray,
|
||||
|
@ -379,7 +416,8 @@ ccl_device bool lights_intersect_shadow_linked(KernelGlobals kg,
|
|||
last_type,
|
||||
path_flag,
|
||||
PATH_MNEE_NONE,
|
||||
receiver_forward);
|
||||
receiver_forward,
|
||||
lcg_state);
|
||||
}
|
||||
|
||||
/* Setup light sample from intersection. */
|
||||
|
|
Loading…
Reference in New Issue
CUDA 10 does not support C++17, so can't use
if constexpr
.Leaving it out should give the same result I think.