37 return (distance_to_center_sq <= radius_sq) ?
39 safe_sqrtf(1.0f - (radius_sq / distance_to_center_sq));
46 const float3 unnormalized_v0 =
P - centroid;
47 const float3 unnormalized_v1 = unnormalized_v0 + D *
fminf(t, 1e12f);
55 const float dot_o0_a =
dot(o0, bcone_axis);
56 const float dot_o1_a =
dot(o1, bcone_axis);
58 const float cos_phi0 = dot_o0_a * inv_len;
60 return (dot_o1_a < 0 ||
dot(v0, v1) > cos_phi0) ? (dot_o0_a >
dot(v1, bcone_axis) ? v0 : v1) :
61 cos_phi0 * o0 + dot_o1_a * inv_len * o1;
66 return kemitter->light.id < 0;
85template<
bool in_volume_segment>
94#ifdef __OBJECT_MOTION__
101 if (in_volume_segment) {
119template<
bool in_volume_segment>
121 const bool has_transmission,
122 const float3 point_to_centroid,
123 const float cos_theta_u,
125 const float max_distance,
126 const float min_distance,
132 max_importance = 0.0f;
133 min_importance = 0.0f;
138 float cos_min_incidence_angle = 1.0f;
139 float cos_max_incidence_angle = 1.0f;
141 if (!in_volume_segment) {
143 const float cos_theta_i = has_transmission ?
fabsf(
dot(point_to_centroid,
N)) :
144 dot(point_to_centroid,
N);
148 cos_min_incidence_angle = cos_theta_i >= cos_theta_u ?
150 cos_theta_i * cos_theta_u + sin_theta_i * sin_theta_u;
156 if (!has_transmission && cos_min_incidence_angle < 0) {
161 cos_max_incidence_angle =
fmaxf(cos_theta_i * cos_theta_u - sin_theta_i * sin_theta_u, 0.0f);
165 if (
isequal(bcone.axis, -point_to_centroid)) {
177 const float cos_theta_minus_theta_u =
cos_theta * cos_theta_u +
sin_theta * sin_theta_u;
179 float cos_theta_o, sin_theta_o;
180 fast_sincosf(bcone.theta_o, &sin_theta_o, &cos_theta_o);
184 float cos_min_outgoing_angle;
185 if ((
cos_theta >= cos_theta_u) || (cos_theta_minus_theta_u >= cos_theta_o)) {
188 cos_min_outgoing_angle = 1.0f;
190 else if ((bcone.theta_o + bcone.theta_e >
M_PI_F) ||
191 (cos_theta_minus_theta_u >
cosf(bcone.theta_o + bcone.theta_e)))
196 const float sin_theta_minus_theta_u =
sin_from_cos(cos_theta_minus_theta_u);
197 cos_min_outgoing_angle = cos_theta_minus_theta_u * cos_theta_o +
198 sin_theta_minus_theta_u * sin_theta_o;
206 const float f_a = 1.0f;
208 max_importance =
fabsf(f_a * cos_min_incidence_angle * energy * cos_min_outgoing_angle *
209 (in_volume_segment ? theta_d / min_distance : 1.0f /
sqr(min_distance)));
212 if (in_volume_segment) {
213 min_importance = 0.0f;
218 float cos_max_outgoing_angle;
219 const float cos_theta_plus_theta_u =
cos_theta * cos_theta_u -
sin_theta * sin_theta_u;
220 if (bcone.theta_e - bcone.theta_o < 0 ||
cos_theta < 0 || cos_theta_u < 0 ||
221 cos_theta_plus_theta_u <
cosf(bcone.theta_e - bcone.theta_o))
223 min_importance = 0.0f;
226 const float sin_theta_plus_theta_u =
sin_from_cos(cos_theta_plus_theta_u);
227 cos_max_outgoing_angle = cos_theta_plus_theta_u * cos_theta_o -
228 sin_theta_plus_theta_u * sin_theta_o;
229 min_importance =
fabsf(f_a * cos_max_incidence_angle * energy * cos_max_outgoing_angle /
234template<
bool in_volume_segment>
243 centroid = klight->co;
245 switch (klight->type) {
247 dir = klight->spot.dir;
254 dir = klight->area.dir;
270 const int object = kemitter->mesh_light.object_id;
273 centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
277 if (is_front_only || is_back_only) {
296template<
bool in_volume_segment>
301 const bool has_transmission,
310 float cos_theta_u,
distance, theta_d;
312 point_to_centroid = -bcone.axis;
313 cos_theta_u =
fast_cosf(bcone.theta_o + bcone.theta_e);
323 const float3 centroid = 0.5f * (bbox.min + bbox.max);
325 if (in_volume_segment) {
327 const float closest_t =
dot(centroid -
P, D);
328 const float3 closest_point =
P + D *
clamp(closest_t, 0.0f, t);
330 distance =
len(centroid -
P - D * closest_t);
335 point_to_centroid = -
compute_v(centroid,
P, D, bcone.axis, t);
340 const float3 bbox_extent = bbox.max - centroid;
341 const bool bbox_is_visible = has_transmission |
347 if (!bbox_is_visible) {
356 distance =
fmaxf(0.5f *
len(centroid - bbox.max), distance);
373template<
bool in_volume_segment>
378 const bool has_transmission,
383 max_importance = 0.0f;
384 min_importance = 0.0f;
391 kemitter->mesh.node_id);
394 kg,
P, N_or_D, t, has_transmission, knode, max_importance, min_importance);
399 bcone.theta_o = kemitter->theta_o;
400 bcone.theta_e = kemitter->theta_e;
401 float cos_theta_u, theta_d = 1.0f;
403 float3 centroid, point_to_centroid, P_c =
P;
410 if (in_volume_segment) {
413 const float closest_t =
dot(centroid -
P, D);
414 P_c += D *
clamp(closest_t, 0.0f, t);
415 const float d =
len(centroid -
P - D * closest_t);
421 float energy = kemitter->energy;
424 kg, kemitter, centroid, P_c, N_or_D, bcone, cos_theta_u, distance, point_to_centroid);
429 switch (klight->type) {
433 klight, centroid, P_c, bcone, cos_theta_u, distance, point_to_centroid, energy);
437 klight, centroid, P_c, cos_theta_u, distance, point_to_centroid);
438 bcone.theta_o = 0.0f;
442 klight, centroid, P_c, N_or_D, bcone.axis, cos_theta_u, distance, point_to_centroid);
446 centroid, t, cos_theta_u, distance, point_to_centroid, theta_d);
450 centroid, bcone.theta_e, t, cos_theta_u, distance, point_to_centroid, theta_d);
457 is_visible |= has_transmission;
462 if (in_volume_segment) {
464 point_to_centroid = -
compute_v(centroid,
P, N_or_D, bcone.axis, t);
471 point_to_centroid = -bcone.axis;
489template<
bool in_volume_segment>
494 const bool has_transmission,
499 max_importance = 0.0f;
500 min_importance = 0.0f;
502 if (knode->num_emitters == 1) {
508 knode->leaf.first_emitter,
512 else if (knode->num_emitters != 0) {
514 kg,
P, N_or_D, t, has_transmission, knode, max_importance, min_importance);
521 const float current_weight,
527 if (!(current_weight > 0.0f)) {
530 total_weight += current_weight;
535 if (selected_index == -1) {
536 selected_index = current_index;
537 selected_weight = current_weight;
544 float thresh = current_weight / total_weight;
545 if (rand <= thresh) {
546 selected_index = current_index;
547 selected_weight = current_weight;
548 rand = rand / thresh;
551 rand = (rand - thresh) / (1.0f - thresh);
561template<
bool in_volume_segment>
567 const bool has_transmission,
571 float selected_importance[2] = {0.0f, 0.0f};
572 float total_importance[2] = {0.0f, 0.0f};
573 int selected_index = -1;
579 uint has_importance = 0;
581 const bool sample_max = (rand > 0.5f);
582 if (knode->num_emitters > 1) {
583 rand = rand * 2.0f -
float(sample_max);
586 for (
int i = 0; i < knode->num_emitters; i++) {
587 int current_index = knode->leaf.first_emitter + i;
591 kg,
P, N_or_D, t, has_transmission, current_index, importance[0], importance[1]);
594 importance[!sample_max],
596 selected_importance[!sample_max],
597 total_importance[!sample_max],
599 if (selected_index == current_index) {
600 selected_importance[sample_max] = importance[sample_max];
602 total_importance[sample_max] += importance[sample_max];
604 has_importance |= ((importance[0] > 0) << i);
607 if (!has_importance) {
611 if (total_importance[1] == 0.0f) {
614 selected_importance[1] = 1.0f;
619 for (
int i = 0; i < knode->num_emitters; i++) {
620 int current_index = knode->leaf.first_emitter + i;
622 float(has_importance & 1),
624 selected_importance[1],
627 has_importance >>= 1;
632 kg,
P, N_or_D, t, has_transmission, selected_index, selected_importance[0], discard);
636 *pdf_factor *= 0.5f * (selected_importance[0] / total_importance[0] +
637 selected_importance[1] / total_importance[1]);
646 *node_index = kemitter->mesh.node_id;
651 *node_index = knode->instance.reference;
655 return selected_index;
658template<
bool in_volume_segment>
663 const bool has_transmission,
664 const int left_index,
665 const int right_index,
671 float min_left_importance, max_left_importance, min_right_importance, max_right_importance;
673 kg,
P, N_or_D, t, has_transmission, left, max_left_importance, min_left_importance);
675 kg,
P, N_or_D, t, has_transmission, right, max_right_importance, min_right_importance);
677 const float total_max_importance = max_left_importance + max_right_importance;
678 if (total_max_importance == 0.0f) {
681 const float total_min_importance = min_left_importance + min_right_importance;
684 const float probability_max = max_left_importance / total_max_importance;
685 const float probability_min = total_min_importance > 0 ?
686 min_left_importance / total_min_importance :
687 0.5f * (
float(max_left_importance > 0) +
688 float(max_right_importance == 0.0f));
689 left_probability = 0.5f * (probability_max + probability_min);
696 const uint receiver_light_set =
700 return kernel_data.light_link_sets[receiver_light_set].light_tree_root;
708template<
bool in_volume_segment>
714 const int object_receiver,
715 const int shader_flags,
723 float pdf_leaf = 1.0f;
724 float pdf_selection = 1.0f;
725 int selected_emitter = -1;
727 float rand_selection = rand;
738 kg, rand_selection, local_P, N_or_D, t, has_transmission, &node_index, &pdf_selection);
740 if (selected_emitter < 0) {
744 if (node_index < 0) {
749 ls->object =
kernel_data_fetch(light_tree_emitters, selected_emitter).mesh.object_id;
754 const int left_index = knode->inner.left_child;
755 const int right_index = knode->inner.right_child;
759 kg, local_P, N_or_D, t, has_transmission, left_index, right_index, left_prob))
765 float total_prob = left_prob;
766 node_index = left_index;
768 right_index, 1.0f - left_prob, node_index, discard, total_prob, rand_selection);
769 pdf_leaf *= (node_index == left_index) ? left_prob : (1.0f - left_prob);
772 ls->emitter_id = selected_emitter;
773 ls->pdf_selection = pdf_selection * pdf_leaf;
779template<
bool in_volume_segment>
785 const int object_emitter,
786 const uint index_emitter,
787 const int object_receiver)
793 int subtree_root_index;
794 uint bit_trail, target_emitter;
802 subtree_root_index = kmesh->mesh.node_id;
805 bit_trail = kroot->bit_trail;
808 subtree_root_index = kroot->instance.reference;
812 subtree_root_index = -1;
813 bit_trail = kemitter->bit_trail;
814 target_emitter = index_emitter;
826 float target_max_importance = 0.0f;
827 float target_min_importance = 0.0f;
828 float total_max_importance = 0.0f;
829 float total_min_importance = 0.0f;
830 int num_has_importance = 0;
831 for (
int i = 0; i < knode->num_emitters; i++) {
832 const int emitter = knode->leaf.first_emitter + i;
833 float max_importance, min_importance;
835 kg,
P,
N, dt, has_transmission, emitter, max_importance, min_importance);
836 num_has_importance += (max_importance > 0);
837 if (emitter == target_emitter) {
838 target_max_importance = max_importance;
839 target_min_importance = min_importance;
841 total_max_importance += max_importance;
842 total_min_importance += min_importance;
845 if (target_max_importance > 0.0f) {
846 pdf *= 0.5f * (target_max_importance / total_max_importance +
847 (total_min_importance > 0 ? target_min_importance / total_min_importance :
848 1.0f / num_has_importance));
854 if (subtree_root_index != -1) {
859 node_index = subtree_root_index;
860 subtree_root_index = -1;
861 target_emitter = index_emitter;
862 bit_trail = kemitter->bit_trail;
871 const int left_index = knode->inner.left_child;
872 const int right_index = knode->inner.right_child;
876 kg,
P,
N, dt, has_transmission, left_index, right_index, left_prob))
882 const bool go_left = (bit_trail & 1) == 0;
885 node_index = go_left ? left_index : right_index;
886 pdf *= go_left ? left_prob : (1.0f - left_prob);
901 const int emitter_object,
902 const uint emitter_id,
903 const int object_receiver)
910 kg,
P, D, dt, path_flag, emitter_object, emitter_id, object_receiver);
914 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)
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define kernel_assert(cond)
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define ccl_device_inline
#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)
draw_view in_light_buf[] float
ccl_device_inline void triangle_vertices(KernelGlobals kg, int prim, float3 P[3])
@ OBJECT_INVERSE_TRANSFORM
ccl_device_inline Transform object_fetch_transform(KernelGlobals kg, int object, enum ObjectTransform type)
ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals kg, int object, 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)
struct BoundingCone { packed_float3 axis; float theta_o; float theta_e;} BoundingCone
@ SD_BSDF_HAS_TRANSMISSION
@ PATH_RAY_MIS_HAD_TRANSMISSION
@ PATH_RAY_VOLUME_SCATTER
@ EMISSION_SAMPLING_FRONT
@ SD_OBJECT_NEGATIVE_SCALE
@ SD_OBJECT_TRANSFORM_APPLIED
#define KERNEL_FEATURE_LIGHT_LINKING
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 BoundingCone bcone, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid)
ccl_device void fast_sincosf(float x, ccl_private float *sine, ccl_private float *cosine)
ccl_device float fast_acosf(float x)
ccl_device float fast_atan2f(float y, float x)
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 float cross(const float2 a, const float2 b)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline bool isequal(const float2 a, const float2 b)
float distance(float a, float 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 BoundingCone &bcone, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid, ccl_private float &energy)
CCL_NAMESPACE_BEGIN ccl_device float light_tree_cos_bound_subtended_angle(const BoundingBox bbox, const float3 centroid, const float3 P)
ccl_device_inline bool is_triangle(const ccl_global KernelLightTreeEmitter *kemitter)
ccl_device float3 compute_v(const float3 centroid, const float3 P, const float3 D, const float3 bcone_axis, const float t)
ccl_device void light_tree_emitter_importance(KernelGlobals kg, const float3 P, const float3 N_or_D, const float t, const bool has_transmission, int emitter_index, ccl_private float &max_importance, ccl_private float &min_importance)
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_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 bool compute_emitter_centroid_and_dir(KernelGlobals kg, ccl_global const KernelLightTreeEmitter *kemitter, const float3 P, ccl_private float3 ¢roid, ccl_private packed_float3 &dir)
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 BoundingCone 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_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)
ccl_device_inline uint popcount(uint x)
ccl_device_inline float sqr(float a)
ccl_device_inline float sin_from_cos(const float c)
ccl_device_inline float inversesqrtf(float f)
ccl_device_inline int clamp(int a, int mn, int mx)