35 const float distance_to_center_sq =
len_squared(
P - centroid);
41 return (distance_to_center_sq <= radius_sq) ?
43 safe_sqrtf(1.0f - (radius_sq / distance_to_center_sq));
50 const float3 unnormalized_v0 =
P - centroid;
51 const float3 unnormalized_v1 = unnormalized_v0 +
D *
fminf(t, 1e12f);
60 const float dot_o0_a =
dot(o0, bcone_axis);
61 const float dot_o1_a =
dot(o1, bcone_axis);
63 const float cos_phi0 = dot_o0_a * inv_len;
65 return (dot_o1_a < 0 ||
dot(v0, v1) > cos_phi0) ? (dot_o0_a >
dot(v1, bcone_axis) ? v0 : v1) :
66 cos_phi0 * o0 + dot_o1_a * inv_len * o1;
71 return kemitter->light.id < 0;
90template<
bool in_volume_segment>
99#ifdef __OBJECT_MOTION__
106 if (in_volume_segment) {
124template<
bool in_volume_segment>
126 const bool has_transmission,
127 const float3 point_to_centroid,
128 const float cos_theta_u,
130 const float max_distance,
131 const float min_distance,
137 max_importance = 0.0f;
138 min_importance = 0.0f;
143 float cos_min_incidence_angle = 1.0f;
144 float cos_max_incidence_angle = 1.0f;
146 if (!in_volume_segment) {
148 const float cos_theta_i = has_transmission ?
fabsf(
dot(point_to_centroid,
N)) :
149 dot(point_to_centroid,
N);
153 cos_min_incidence_angle = cos_theta_i >= cos_theta_u ?
155 cos_theta_i * cos_theta_u + sin_theta_i * sin_theta_u;
161 if (!has_transmission && cos_min_incidence_angle < 0) {
166 cos_max_incidence_angle =
fmaxf(cos_theta_i * cos_theta_u - sin_theta_i * sin_theta_u, 0.0f);
183 const float cos_theta_minus_theta_u =
cos_theta * cos_theta_u +
sin_theta * sin_theta_u;
191 float cos_min_outgoing_angle;
192 if ((
cos_theta >= cos_theta_u) || (cos_theta_minus_theta_u >= cos_theta_o)) {
195 cos_min_outgoing_angle = 1.0f;
203 const float sin_theta_minus_theta_u =
sin_from_cos(cos_theta_minus_theta_u);
204 cos_min_outgoing_angle = cos_theta_minus_theta_u * cos_theta_o +
205 sin_theta_minus_theta_u * sin_theta_o;
213 const float f_a = 1.0f;
215 max_importance =
fabsf(f_a * cos_min_incidence_angle * energy * cos_min_outgoing_angle *
216 (in_volume_segment ? theta_d / min_distance : 1.0f /
sqr(min_distance)));
219 if (in_volume_segment) {
220 min_importance = 0.0f;
225 float cos_max_outgoing_angle;
226 const float cos_theta_plus_theta_u =
cos_theta * cos_theta_u -
sin_theta * sin_theta_u;
230 min_importance = 0.0f;
233 const float sin_theta_plus_theta_u =
sin_from_cos(cos_theta_plus_theta_u);
234 cos_max_outgoing_angle = cos_theta_plus_theta_u * cos_theta_o -
235 sin_theta_plus_theta_u * sin_theta_o;
236 min_importance =
fabsf(f_a * cos_max_incidence_angle * energy * cos_max_outgoing_angle /
241template<
bool in_volume_segment>
250 centroid = klight->co;
252 switch (klight->type) {
254 dir = klight->spot.dir;
261 dir = klight->area.dir;
277 const int object = kemitter->object_id;
280 centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
284 if (is_front_only || is_back_only) {
303template<
bool in_volume_segment>
307 const bool has_transmission,
320 point_to_centroid = -bcone.
axis;
338 if (in_volume_segment) {
340 const float closest_t =
dot(centroid -
P,
D);
341 const float3 closest_point =
P +
D *
clamp(closest_t, 0.0f, t);
363 const float3 bbox_extent = bbox.
max - centroid;
364 const bool bbox_is_visible = has_transmission |
370 if (!bbox_is_visible) {
396template<
bool in_volume_segment>
401 const bool has_transmission,
402 const int emitter_index,
406 max_importance = 0.0f;
407 min_importance = 0.0f;
414 kemitter->mesh.node_id);
417 P, N_or_D, t, has_transmission, knode, max_importance, min_importance);
422 bcone.
theta_o = kemitter->theta_o;
423 bcone.
theta_e = kemitter->theta_e;
425 float theta_d = 1.0f;
436 if (in_volume_segment) {
439 const float closest_t =
dot(centroid -
P,
D);
440 P_c +=
D *
clamp(closest_t, 0.0f, t);
441 const float d =
len(centroid -
P -
D * closest_t);
452 float energy = kemitter->energy;
455 kg, kemitter, centroid, P_c, N_or_D, bcone, cos_theta_u,
distance, point_to_centroid);
460 switch (klight->type) {
464 klight, centroid, P_c, bcone, cos_theta_u,
distance, point_to_centroid, energy);
468 klight, centroid, P_c, cos_theta_u,
distance, point_to_centroid);
473 klight, centroid, P_c, N_or_D, bcone.
axis, cos_theta_u,
distance, point_to_centroid);
477 centroid, t, cos_theta_u,
distance, point_to_centroid, theta_d);
481 centroid, bcone.
theta_e, t, cos_theta_u,
distance, point_to_centroid, theta_d);
488 is_visible |= has_transmission;
493 if (in_volume_segment) {
495 point_to_centroid = -
compute_v(centroid,
P, N_or_D, bcone.
axis, t);
502 point_to_centroid = -bcone.
axis;
520template<
bool in_volume_segment>
525 const bool has_transmission,
530 max_importance = 0.0f;
531 min_importance = 0.0f;
533 if (knode->num_emitters == 1) {
539 knode->leaf.first_emitter,
543 else if (knode->num_emitters != 0) {
545 P, N_or_D, t, has_transmission, knode, max_importance, min_importance);
552 const float current_weight,
558 if (!(current_weight > 0.0f)) {
561 total_weight += current_weight;
566 if (selected_index == -1) {
567 selected_index = current_index;
568 selected_weight = current_weight;
575 const float thresh = current_weight / total_weight;
576 if (rand <= thresh) {
577 selected_index = current_index;
578 selected_weight = current_weight;
579 rand = rand / thresh;
582 rand = (rand - thresh) / (1.0f - thresh);
592template<
bool in_volume_segment>
598 const bool has_transmission,
602 float selected_importance[2] = {0.0f, 0.0f};
603 float total_importance[2] = {0.0f, 0.0f};
604 int selected_index = -1;
610 uint has_importance = 0;
612 const bool sample_max = (rand > 0.5f);
613 if (knode->num_emitters > 1) {
614 rand = rand * 2.0f -
float(sample_max);
617 for (
int i = 0;
i < knode->num_emitters;
i++) {
618 int current_index = knode->leaf.first_emitter +
i;
622 kg,
P, N_or_D, t, has_transmission, current_index, importance[0], importance[1]);
625 importance[!sample_max],
627 selected_importance[!sample_max],
628 total_importance[!sample_max],
630 if (selected_index == current_index) {
631 selected_importance[sample_max] = importance[sample_max];
633 total_importance[sample_max] += importance[sample_max];
635 has_importance |= ((importance[0] > 0) <<
i);
638 if (!has_importance) {
642 if (total_importance[1] == 0.0f) {
645 selected_importance[1] = 1.0f;
650 for (
int i = 0;
i < knode->num_emitters;
i++) {
651 const int current_index = knode->leaf.first_emitter +
i;
653 float(has_importance & 1),
655 selected_importance[1],
658 has_importance >>= 1;
663 kg,
P, N_or_D, t, has_transmission, selected_index, selected_importance[0], discard);
667 *pdf_factor *= 0.5f * (selected_importance[0] / total_importance[0] +
668 selected_importance[1] / total_importance[1]);
677 *node_index = kemitter->mesh.node_id;
682 *node_index = knode->instance.reference;
686 return selected_index;
689template<
bool in_volume_segment>
694 const bool has_transmission,
695 const int left_index,
696 const int right_index,
702 float min_left_importance;
703 float max_left_importance;
704 float min_right_importance;
705 float max_right_importance;
707 kg,
P, N_or_D, t, has_transmission,
left, max_left_importance, min_left_importance);
709 kg,
P, N_or_D, t, has_transmission, right, max_right_importance, min_right_importance);
711 const float total_max_importance = max_left_importance + max_right_importance;
712 if (total_max_importance == 0.0f) {
715 const float total_min_importance = min_left_importance + min_right_importance;
718 const float probability_max = max_left_importance / total_max_importance;
719 const float probability_min = total_min_importance > 0 ?
720 min_left_importance / total_min_importance :
721 0.5f * (
float(max_left_importance > 0) +
722 float(max_right_importance == 0.0f));
723 left_probability = 0.5f * (probability_max + probability_min);
730 const uint receiver_light_set =
734 return kernel_data.light_link_sets[receiver_light_set].light_tree_root;
742template<
bool in_volume_segment>
748 const int object_receiver,
749 const int shader_flags,
757 float pdf_leaf = 1.0f;
758 float pdf_selection = 1.0f;
759 int selected_emitter = -1;
761 float rand_selection = rand;
772 kg, rand_selection, local_P, N_or_D, t, has_transmission, &node_index, &pdf_selection);
774 if (selected_emitter < 0) {
778 if (node_index < 0) {
783 ls->object =
kernel_data_fetch(light_tree_emitters, selected_emitter).mesh.object_id;
788 const int left_index = knode->inner.left_child;
789 const int right_index = knode->inner.right_child;
793 kg, local_P, N_or_D, t, has_transmission, left_index, right_index, left_prob))
799 float total_prob = left_prob;
800 node_index = left_index;
802 right_index, 1.0f - left_prob, node_index, discard, total_prob, rand_selection);
803 pdf_leaf *= (node_index == left_index) ? left_prob : (1.0f - left_prob);
806 ls->emitter_id = selected_emitter;
807 ls->pdf_selection = pdf_selection * pdf_leaf;
813template<
bool in_volume_segment>
819 const int object_emitter,
820 const uint index_emitter,
821 const int object_receiver)
827 int subtree_root_index;
837 subtree_root_index = kmesh->mesh.node_id;
840 bit_trail = kroot->bit_trail;
843 subtree_root_index = kroot->instance.reference;
847 subtree_root_index = -1;
848 bit_trail = kemitter->bit_trail;
849 target_emitter = index_emitter;
861 float target_max_importance = 0.0f;
862 float target_min_importance = 0.0f;
863 float total_max_importance = 0.0f;
864 float total_min_importance = 0.0f;
865 int num_has_importance = 0;
866 for (
int i = 0;
i < knode->num_emitters;
i++) {
867 const int emitter = knode->leaf.first_emitter +
i;
868 float max_importance;
869 float min_importance;
871 kg,
P,
N, dt, has_transmission, emitter, max_importance, min_importance);
872 num_has_importance += (max_importance > 0);
873 if (emitter == target_emitter) {
874 target_max_importance = max_importance;
875 target_min_importance = min_importance;
877 total_max_importance += max_importance;
878 total_min_importance += min_importance;
881 if (target_max_importance > 0.0f) {
882 pdf *= 0.5f * (target_max_importance / total_max_importance +
883 (total_min_importance > 0 ? target_min_importance / total_min_importance :
884 1.0f / num_has_importance));
890 if (subtree_root_index != -1) {
895 node_index = subtree_root_index;
896 subtree_root_index = -1;
897 target_emitter = index_emitter;
898 bit_trail = kemitter->bit_trail;
905 const int left_index = knode->inner.left_child;
906 const int right_index = knode->inner.right_child;
910 kg,
P,
N, dt, has_transmission, left_index, right_index, left_prob))
916 const bool go_left = (bit_trail & 1) == 0;
919 node_index = go_left ? left_index : right_index;
920 pdf *= go_left ? left_prob : (1.0f - left_prob);
935 const int emitter_object,
936 const uint emitter_id,
937 const int object_receiver)
944 kg,
P,
D, dt, path_flag, emitter_object, emitter_id, object_receiver);
948 kg,
P,
N, 0.0f, path_flag, emitter_object, emitter_id, object_receiver);
MINLINE float safe_sqrtf(float a)
MINLINE float safe_divide(float a, float b)
ccl_device_forceinline bool area_light_tree_parameters(const ccl_global KernelLight *klight, const float3 centroid, const float3 P, const float3 N, const float3 bcone_axis, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid)
ccl_device_inline float cos_theta(const float3 w)
ccl_device_inline float sin_theta(const float3 w)
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define kernel_assert(cond)
#define kernel_data_fetch(name, index)
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define KERNEL_FEATURE_LIGHT_LINKING
#define ccl_device_noinline
#define CCL_NAMESPACE_END
ccl_device_forceinline bool distant_light_tree_parameters(const float3 centroid, const float theta_e, const float t, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid, ccl_private float &theta_d)
ccl_device_inline void triangle_vertices(KernelGlobals kg, const int prim, float3 P[3])
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
constexpr T clamp(T, U, U) RET
float distance(VecOp< float, D >, VecOp< float, D >) RET
@ OBJECT_INVERSE_TRANSFORM
ccl_device_inline Transform object_fetch_transform(KernelGlobals kg, const int object, enum ObjectTransform type)
ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals kg, const int object, const float time, ccl_private Transform *itfm)
ccl_device_forceinline bool background_light_tree_parameters(const float3 centroid, const float t, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid, ccl_private float &theta_d)
@ SD_BSDF_HAS_TRANSMISSION
@ PATH_RAY_MIS_HAD_TRANSMISSION
@ PATH_RAY_VOLUME_SCATTER
@ EMISSION_SAMPLING_FRONT
@ SD_OBJECT_NEGATIVE_SCALE
@ SD_OBJECT_TRANSFORM_APPLIED
ccl_device_forceinline bool point_light_tree_parameters(const ccl_global KernelLight *klight, const float3 centroid, const float3 P, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid)
ccl_device_forceinline bool triangle_light_tree_parameters(KernelGlobals kg, const ccl_global KernelLightTreeEmitter *kemitter, const float3 centroid, const float3 P, const float3 N, const KernelBoundingCone bcone, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid)
ccl_device_inline float inversesqrtf(const float f)
ccl_device_inline float sin_from_cos(const float c)
ccl_device_inline uint popcount(const uint x)
ccl_device float fast_atan2f(const float y, const float x)
ccl_device float fast_acosf(const float x)
ccl_device void fast_sincosf(float x, ccl_private float *sine, ccl_private float *cosine)
ccl_device float fast_cosf(float x)
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
ccl_device_inline float2 normalize_len(const float2 a, ccl_private float *t)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline bool isequal(const float2 a, const float2 b)
ccl_device void make_orthonormals_tangent(const float3 N, const float3 T, ccl_private float3 *a, ccl_private float3 *b)
ccl_device_forceinline bool spot_light_tree_parameters(const ccl_global KernelLight *klight, const float3 centroid, const float3 P, const ccl_private KernelBoundingCone &bcone, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid, ccl_private float &energy)
ccl_device_inline bool is_triangle(const ccl_global KernelLightTreeEmitter *kemitter)
ccl_device void light_tree_emitter_importance(KernelGlobals kg, const float3 P, const float3 N_or_D, const float t, const bool has_transmission, const int emitter_index, ccl_private float &max_importance, ccl_private float &min_importance)
ccl_device float3 compute_v(const float3 centroid, const float3 P, const float3 D, const float3 bcone_axis, const float t)
ccl_device_inline bool is_light(const ccl_global KernelLightTreeEmitter *kemitter)
ccl_device int light_tree_cluster_select_emitter(KernelGlobals kg, ccl_private float &rand, ccl_private float3 &P, ccl_private float3 &N_or_D, ccl_private float &t, const bool has_transmission, ccl_private int *node_index, ccl_private float *pdf_factor)
ccl_device_noinline bool light_tree_sample(KernelGlobals kg, const float rand, const float3 P, float3 N_or_D, float t, const int object_receiver, const int shader_flags, ccl_private LightSample *ls)
ccl_device bool compute_emitter_centroid_and_dir(KernelGlobals kg, const ccl_global KernelLightTreeEmitter *kemitter, const float3 P, ccl_private float3 ¢roid, ccl_private packed_float3 &dir)
ccl_device_inline bool is_mesh(const ccl_global KernelLightTreeEmitter *kemitter)
ccl_device void sample_reservoir(const int current_index, const float current_weight, ccl_private int &selected_index, ccl_private float &selected_weight, ccl_private float &total_weight, ccl_private float &rand)
ccl_device void light_tree_to_local_space(KernelGlobals kg, const int object_id, ccl_private float3 &P, ccl_private float3 &N_or_D, ccl_private float &t)
ccl_device bool get_left_probability(KernelGlobals kg, const float3 P, const float3 N_or_D, const float t, const bool has_transmission, const int left_index, const int right_index, ccl_private float &left_probability)
ccl_device void light_tree_importance(const float3 N_or_D, const bool has_transmission, const float3 point_to_centroid, const float cos_theta_u, const KernelBoundingCone bcone, const float max_distance, const float min_distance, const float energy, const float theta_d, ccl_private float &max_importance, ccl_private float &min_importance)
CCL_NAMESPACE_BEGIN ccl_device float light_tree_cos_bound_subtended_angle(const KernelBoundingBox bbox, const float3 centroid, const float3 P)
ccl_device void light_tree_child_importance(KernelGlobals kg, const float3 P, const float3 N_or_D, const float t, const bool has_transmission, const ccl_global KernelLightTreeNode *knode, ccl_private float &max_importance, ccl_private float &min_importance)
ccl_device_inline bool is_leaf(const ccl_global KernelLightTreeNode *knode)
ccl_device float light_tree_pdf(KernelGlobals kg, float3 P, float3 N, const float dt, const int path_flag, const int object_emitter, const uint index_emitter, const int object_receiver)
ccl_device void light_tree_node_importance(const float3 P, const float3 N_or_D, const float t, const bool has_transmission, const ccl_global KernelLightTreeNode *knode, ccl_private float &max_importance, ccl_private float &min_importance)
ccl_device int light_tree_root_node_index(KernelGlobals kg, const int object_receiver)