Light linking: Support distant lights for shadow linking #107979
|
@ -42,8 +42,6 @@ ccl_device bool shadow_linking_pick_light_intersection(KernelGlobals kg,
|
|||
|
||||
// TODO: Support mesh emitters.
|
||||
|
||||
// TODO: Distant lights.
|
||||
|
||||
// TODO: Only if ray is not fully occluded.
|
||||
|
||||
const int receiver_forward = light_link_receiver_forward(kg, state);
|
||||
|
|
|
@ -138,10 +138,17 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
|
|||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Light linking. */
|
||||
|
||||
#ifdef __LIGHT_LINKING__
|
||||
if (!light_link_light_match(kg, light_link_receiver_forward(kg, state), lamp)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef __SHADOW_LINKING__
|
||||
if (kernel_data_fetch(lights, lamp).shadow_set_membership != LIGHT_LINK_MASK_ALL) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __MNEE__
|
||||
if (INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_CULL_LIGHT_CONNECTION) {
|
||||
|
|
|
@ -5,11 +5,44 @@
|
|||
|
||||
#include "kernel/integrator/path_state.h"
|
||||
#include "kernel/integrator/shade_surface.h"
|
||||
#include "kernel/light/distant.h"
|
||||
#include "kernel/light/light.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef __SHADOW_LINKING__
|
||||
|
||||
ccl_device_inline bool shadow_linking_light_sample_from_intersection(
|
||||
KernelGlobals kg,
|
||||
ccl_private const Intersection &ccl_restrict isect,
|
||||
ccl_private const Ray &ccl_restrict ray,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
{
|
||||
const int lamp = isect.prim;
|
||||
|
||||
const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp);
|
||||
const LightType type = LightType(klight->type);
|
||||
|
||||
if (type == LIGHT_DISTANT) {
|
||||
return distant_light_sample_from_intersection(kg, ray.D, lamp, ls);
|
||||
}
|
||||
|
||||
return light_sample_from_intersection(kg, &isect, ray.P, ray.D, ls);
|
||||
}
|
||||
|
||||
ccl_device_inline float shadow_linking_light_sample_mis_weight(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const uint32_t path_flag,
|
||||
const ccl_private LightSample *ls,
|
||||
const float3 P)
|
||||
{
|
||||
if (ls->type == LIGHT_DISTANT) {
|
||||
return light_sample_mis_weight_forward_distant(kg, state, path_flag, ls);
|
||||
}
|
||||
|
||||
return light_sample_mis_weight_forward_lamp(kg, state, path_flag, ls, P);
|
||||
}
|
||||
|
||||
/* Setup ray for the shadow path.
|
||||
* Expects that the current state of the ray is the one calculated by the surface bounce, and the
|
||||
* intersection corresponds to a point on an emitter. */
|
||||
|
@ -49,7 +82,7 @@ ccl_device void shadow_linking_shade(KernelGlobals kg, IntegratorState state)
|
|||
integrator_state_read_ray(state, &ray);
|
||||
|
||||
LightSample ls ccl_optional_struct_init;
|
||||
const bool use_light_sample = light_sample_from_intersection(kg, &isect, ray.P, ray.D, &ls);
|
||||
const bool use_light_sample = shadow_linking_light_sample_from_intersection(kg, isect, ray, &ls);
|
||||
if (!use_light_sample) {
|
||||
/* No light to be sampled, so no direct light contribution either. */
|
||||
return;
|
||||
|
@ -70,7 +103,7 @@ ccl_device void shadow_linking_shade(KernelGlobals kg, IntegratorState state)
|
|||
/* MIS weighting. */
|
||||
float mis_weight = 1.0f;
|
||||
if (!(path_flag & PATH_RAY_MIS_SKIP)) {
|
||||
mis_weight = light_sample_mis_weight_forward_lamp(kg, state, path_flag, &ls, ray.P);
|
||||
mis_weight = shadow_linking_light_sample_mis_weight(kg, state, path_flag, &ls, ray.P);
|
||||
}
|
||||
|
||||
const Spectrum bsdf_spectrum = light_eval * mis_weight *
|
||||
|
|
|
@ -20,10 +20,10 @@ ccl_device_forceinline bool shadow_linking_scene_need_shadow_ray(KernelGlobals k
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!kernel_data.integrator.use_light_mis) {
|
||||
/* No need to cast extra shadow linking path if there are no lights with MIS in the scene. */
|
||||
return false;
|
||||
}
|
||||
/* The distant lights might be using shadow linking, and they are not counted as
|
||||
* kernel_data.integrator.use_light_mis.
|
||||
* So there is a potential to avoid extra rays from being traced, but it requires more granular
|
||||
* flags set in the integrator. */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,39 @@ ccl_device_inline bool distant_light_sample(const ccl_global KernelLight *klight
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Special intersection check.
|
||||
* Returns true if the distant_light_sample_from_intersection() for this light would return true.
|
||||
*
|
||||
* The intersection parameters t, u, v are optimized for the shadow ray towards a dedicated light:
|
||||
* u = v = 0, t = FLT_MAX.
|
||||
*/
|
||||
ccl_device bool distant_light_intersect(const ccl_global KernelLight *klight,
|
||||
const ccl_private Ray *ccl_restrict ray,
|
||||
ccl_private float *t,
|
||||
ccl_private float *u,
|
||||
ccl_private float *v)
|
||||
{
|
||||
kernel_assert(klight->type == LIGHT_DISTANT);
|
||||
|
||||
if (klight->distant.radius == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const float3 lightD = klight->co;
|
||||
const float costheta = dot(-lightD, ray->D);
|
||||
const float cosangle = klight->distant.cosangle;
|
||||
|
||||
if (costheta < cosangle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*t = FLT_MAX;
|
||||
*u = 0.0f;
|
||||
*v = 0.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ccl_device bool distant_light_sample_from_intersection(KernelGlobals kg,
|
||||
const float3 ray_D,
|
||||
const int lamp,
|
||||
|
|
|
@ -335,6 +335,14 @@ ccl_device_forceinline int lights_intersect_impl(KernelGlobals kg,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if (type == LIGHT_DISTANT) {
|
||||
if (is_main_path) {
|
||||
|
||||
continue;
|
||||
}
|
||||
if (!distant_light_intersect(klight, ray, &t, &u, &v)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
|
@ -374,6 +382,8 @@ ccl_device_forceinline int lights_intersect_impl(KernelGlobals kg,
|
|||
return num_hits;
|
||||
}
|
||||
|
||||
/* Lights intersection for the main path.
|
||||
* Intersects spot, point, and area lights. */
|
||||
ccl_device bool lights_intersect(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private const Ray *ccl_restrict ray,
|
||||
|
@ -400,6 +410,8 @@ ccl_device bool lights_intersect(KernelGlobals kg,
|
|||
return isect->prim != PRIM_NONE;
|
||||
}
|
||||
|
||||
/* Lights intersection for the shadow linking.
|
||||
* Intersects spot, point, area, and distant lights. */
|
||||
ccl_device int lights_intersect_shadow_linked(KernelGlobals kg,
|
||||
ccl_private const Ray *ccl_restrict ray,
|
||||
ccl_private Intersection *ccl_restrict isect,
|
||||
|
|
Loading…
Reference in New Issue
Can't use constexpr.