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>
308 const bool has_transmission,
321 point_to_centroid = -bcone.
axis;
339 if (in_volume_segment) {
341 const float closest_t =
dot(centroid -
P,
D);
342 const float3 closest_point =
P +
D *
clamp(closest_t, 0.0f, t);
354 const float3 bbox_extent = bbox.
max - centroid;
355 const bool bbox_is_visible = has_transmission |
361 if (!bbox_is_visible) {
387template<
bool in_volume_segment>
392 const bool has_transmission,
393 const int emitter_index,
397 max_importance = 0.0f;
398 min_importance = 0.0f;
405 kemitter->mesh.node_id);
408 kg,
P, N_or_D, t, has_transmission, knode, max_importance, min_importance);
413 bcone.
theta_o = kemitter->theta_o;
414 bcone.
theta_e = kemitter->theta_e;
416 float theta_d = 1.0f;
427 if (in_volume_segment) {
430 const float closest_t =
dot(centroid -
P,
D);
431 P_c +=
D *
clamp(closest_t, 0.0f, t);
432 const float d =
len(centroid -
P -
D * closest_t);
438 float energy = kemitter->energy;
441 kg, kemitter, centroid, P_c, N_or_D, bcone, cos_theta_u,
distance, point_to_centroid);
446 switch (klight->type) {
450 klight, centroid, P_c, bcone, cos_theta_u,
distance, point_to_centroid, energy);
454 klight, centroid, P_c, cos_theta_u,
distance, point_to_centroid);
459 klight, centroid, P_c, N_or_D, bcone.
axis, cos_theta_u,
distance, point_to_centroid);
463 centroid, t, cos_theta_u,
distance, point_to_centroid, theta_d);
467 centroid, bcone.
theta_e, t, cos_theta_u,
distance, point_to_centroid, theta_d);
474 is_visible |= has_transmission;
479 if (in_volume_segment) {
481 point_to_centroid = -
compute_v(centroid,
P, N_or_D, bcone.
axis, t);
488 point_to_centroid = -bcone.
axis;
506template<
bool in_volume_segment>
511 const bool has_transmission,
516 max_importance = 0.0f;
517 min_importance = 0.0f;
519 if (knode->num_emitters == 1) {
525 knode->leaf.first_emitter,
529 else if (knode->num_emitters != 0) {
531 kg,
P, N_or_D, t, has_transmission, knode, max_importance, min_importance);
538 const float current_weight,
544 if (!(current_weight > 0.0f)) {
547 total_weight += current_weight;
552 if (selected_index == -1) {
553 selected_index = current_index;
554 selected_weight = current_weight;
561 const float thresh = current_weight / total_weight;
562 if (rand <= thresh) {
563 selected_index = current_index;
564 selected_weight = current_weight;
565 rand = rand / thresh;
568 rand = (rand - thresh) / (1.0f - thresh);
578template<
bool in_volume_segment>
584 const bool has_transmission,
588 float selected_importance[2] = {0.0f, 0.0f};
589 float total_importance[2] = {0.0f, 0.0f};
590 int selected_index = -1;
596 uint has_importance = 0;
598 const bool sample_max = (rand > 0.5f);
599 if (knode->num_emitters > 1) {
600 rand = rand * 2.0f - float(sample_max);
603 for (
int i = 0;
i < knode->num_emitters;
i++) {
604 int current_index = knode->leaf.first_emitter +
i;
608 kg,
P, N_or_D, t, has_transmission, current_index, importance[0], importance[1]);
611 importance[!sample_max],
613 selected_importance[!sample_max],
614 total_importance[!sample_max],
616 if (selected_index == current_index) {
617 selected_importance[sample_max] = importance[sample_max];
619 total_importance[sample_max] += importance[sample_max];
621 has_importance |= ((importance[0] > 0) <<
i);
624 if (!has_importance) {
628 if (total_importance[1] == 0.0f) {
631 selected_importance[1] = 1.0f;
632 total_importance[1] = float(
popcount(has_importance));
636 for (
int i = 0;
i < knode->num_emitters;
i++) {
637 const int current_index = knode->leaf.first_emitter +
i;
639 float(has_importance & 1),
641 selected_importance[1],
644 has_importance >>= 1;
649 kg,
P, N_or_D, t, has_transmission, selected_index, selected_importance[0], discard);
653 *pdf_factor *= 0.5f * (selected_importance[0] / total_importance[0] +
654 selected_importance[1] / total_importance[1]);
663 *node_index = kemitter->mesh.node_id;
668 *node_index = knode->instance.reference;
672 return selected_index;
675template<
bool in_volume_segment>
680 const bool has_transmission,
681 const int left_index,
682 const int right_index,
688 float min_left_importance;
689 float max_left_importance;
690 float min_right_importance;
691 float max_right_importance;
693 kg,
P, N_or_D, t, has_transmission,
left, max_left_importance, min_left_importance);
695 kg,
P, N_or_D, t, has_transmission, right, max_right_importance, min_right_importance);
697 const float total_max_importance = max_left_importance + max_right_importance;
698 if (total_max_importance == 0.0f) {
701 const float total_min_importance = min_left_importance + min_right_importance;
704 const float probability_max = max_left_importance / total_max_importance;
705 const float probability_min = total_min_importance > 0 ?
706 min_left_importance / total_min_importance :
707 0.5f * (float(max_left_importance > 0) +
708 float(max_right_importance == 0.0f));
709 left_probability = 0.5f * (probability_max + probability_min);
716 const uint receiver_light_set =
720 return kernel_data.light_link_sets[receiver_light_set].light_tree_root;
728template<
bool in_volume_segment>
734 const int object_receiver,
735 const int shader_flags,
743 float pdf_leaf = 1.0f;
744 float pdf_selection = 1.0f;
745 int selected_emitter = -1;
747 float rand_selection = rand;
758 kg, rand_selection, local_P, N_or_D, t, has_transmission, &node_index, &pdf_selection);
760 if (selected_emitter < 0) {
764 if (node_index < 0) {
769 ls->object =
kernel_data_fetch(light_tree_emitters, selected_emitter).mesh.object_id;
774 const int left_index = knode->inner.left_child;
775 const int right_index = knode->inner.right_child;
779 kg, local_P, N_or_D, t, has_transmission, left_index, right_index, left_prob))
785 float total_prob = left_prob;
786 node_index = left_index;
788 right_index, 1.0f - left_prob, node_index, discard, total_prob, rand_selection);
789 pdf_leaf *= (node_index == left_index) ? left_prob : (1.0f - left_prob);
792 ls->emitter_id = selected_emitter;
793 ls->pdf_selection = pdf_selection * pdf_leaf;
799template<
bool in_volume_segment>
805 const int object_emitter,
806 const uint index_emitter,
807 const int object_receiver)
813 int subtree_root_index;
823 subtree_root_index = kmesh->mesh.node_id;
826 bit_trail = kroot->bit_trail;
829 subtree_root_index = kroot->instance.reference;
833 subtree_root_index = -1;
834 bit_trail = kemitter->bit_trail;
835 target_emitter = index_emitter;
847 float target_max_importance = 0.0f;
848 float target_min_importance = 0.0f;
849 float total_max_importance = 0.0f;
850 float total_min_importance = 0.0f;
851 int num_has_importance = 0;
852 for (
int i = 0;
i < knode->num_emitters;
i++) {
853 const int emitter = knode->leaf.first_emitter +
i;
854 float max_importance;
855 float min_importance;
857 kg,
P,
N, dt, has_transmission, emitter, max_importance, min_importance);
858 num_has_importance += (max_importance > 0);
859 if (emitter == target_emitter) {
860 target_max_importance = max_importance;
861 target_min_importance = min_importance;
863 total_max_importance += max_importance;
864 total_min_importance += min_importance;
867 if (target_max_importance > 0.0f) {
868 pdf *= 0.5f * (target_max_importance / total_max_importance +
869 (total_min_importance > 0 ? target_min_importance / total_min_importance :
870 1.0f / num_has_importance));
876 if (subtree_root_index != -1) {
881 node_index = subtree_root_index;
882 subtree_root_index = -1;
883 target_emitter = index_emitter;
884 bit_trail = kemitter->bit_trail;
891 const int left_index = knode->inner.left_child;
892 const int right_index = knode->inner.right_child;
896 kg,
P,
N, dt, has_transmission, left_index, right_index, left_prob))
902 const bool go_left = (bit_trail & 1) == 0;
905 node_index = go_left ? left_index : right_index;
906 pdf *= go_left ? left_prob : (1.0f - left_prob);
921 const int emitter_object,
922 const uint emitter_id,
923 const int object_receiver)
930 kg,
P,
D, dt, path_flag, emitter_object, emitter_id, object_receiver);
934 kg,
P,
N, 0.0f, path_flag, emitter_object, emitter_id, object_receiver);
MINLINE float safe_sqrtf(float a)
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 sqr(const float a)
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 void light_tree_node_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 int light_tree_root_node_index(KernelGlobals kg, const int object_receiver)