Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/light/tree.h
| Show First 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | ccl_device void light_tree_cluster_importance(const float3 N_or_D, | ||||
| /* TODO: find a good approximation for f_a. */ | /* TODO: find a good approximation for f_a. */ | ||||
| const float f_a = 1.0f; | const float f_a = 1.0f; | ||||
| /* TODO: also consider t (or theta_a, theta_b) for volume */ | /* TODO: also consider t (or theta_a, theta_b) for volume */ | ||||
| max_importance = fabsf(f_a * cos_min_incidence_angle * energy * cos_min_outgoing_angle / | max_importance = fabsf(f_a * cos_min_incidence_angle * energy * cos_min_outgoing_angle / | ||||
| (in_volume_segment ? min_distance : sqr(min_distance))); | (in_volume_segment ? min_distance : sqr(min_distance))); | ||||
| /* TODO: also min importance for volume? */ | /* TODO: also min importance for volume? */ | ||||
| if (max_distance == min_distance || in_volume_segment || in_volume) { | if (in_volume_segment || in_volume) { | ||||
| min_importance = max_importance; | min_importance = max_importance; | ||||
| return; | return; | ||||
| } | } | ||||
| /* compute mininum importance */ | /* compute mininum importance */ | ||||
| /* cos_max_incidence_angle = cos(min{theta_i + theta_u, pi}) */ | /* cos_max_incidence_angle = cos(min{theta_i + theta_u, pi}) */ | ||||
| const float cos_max_incidence_angle = fmaxf( | const float cos_max_incidence_angle = fmaxf( | ||||
| cos_theta_i * cos_theta_u - sin_theta_i * sin_theta_u, 0.0f); | cos_theta_i * cos_theta_u - sin_theta_i * sin_theta_u, 0.0f); | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters, | ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters, | ||||
| emitter_index); | emitter_index); | ||||
| float3 bcone_axis = make_float3(kemitter->bounding_cone_axis[0], | float3 bcone_axis = make_float3(kemitter->bounding_cone_axis[0], | ||||
| kemitter->bounding_cone_axis[1], | kemitter->bounding_cone_axis[1], | ||||
| kemitter->bounding_cone_axis[2]); | kemitter->bounding_cone_axis[2]); | ||||
| float theta_o = kemitter->theta_o; | float theta_o = kemitter->theta_o; | ||||
| float cos_theta_u, max_distance, min_distance; | float min_distance, distance; | ||||
| float max_distance = 0.0f; | |||||
| float cos_theta_u = 1.0f; | |||||
| float3 centroid, point_to_centroid; | float3 centroid, point_to_centroid; | ||||
| bool bbox_is_visible = has_transmission; | bool bbox_is_visible = has_transmission; | ||||
| const int prim = kemitter->prim_id; | const int prim = kemitter->prim_id; | ||||
| if (prim < 0) { | if (prim < 0) { | ||||
| const int lamp = -prim - 1; | const int lamp = -prim - 1; | ||||
| const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp); | const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp); | ||||
| centroid = make_float3(klight->co[0], klight->co[1], klight->co[2]); | centroid = make_float3(klight->co[0], klight->co[1], klight->co[2]); | ||||
| point_to_centroid = safe_normalize_len(centroid - P, &distance); | |||||
| if (klight->type == LIGHT_SPOT || klight->type == LIGHT_POINT) { | if (klight->type == LIGHT_SPOT || klight->type == LIGHT_POINT) { | ||||
| const float radius = klight->spot.radius; | const float radius = klight->spot.radius; | ||||
| float distance; | |||||
| point_to_centroid = safe_normalize_len(centroid - P, &distance); | |||||
| min_distance = distance; | min_distance = distance; | ||||
| max_distance = sqrtf(sqr(radius) + sqr(distance)); | max_distance = sqrtf(sqr(radius) + sqr(distance)); | ||||
| const float hypotenus = max_distance; | const float hypotenus = max_distance; | ||||
| cos_theta_u = distance / hypotenus; | cos_theta_u = distance / hypotenus; | ||||
| bbox_is_visible = true; /* will be tested later */ | bbox_is_visible = true; /* will be tested later */ | ||||
| } | } | ||||
| else { /* TODO: support area light */ | else { /* area light */ | ||||
| const float3 bbox_min = make_float3(kemitter->bounding_box_min[0], | const float3 extentu = make_float3( | ||||
| kemitter->bounding_box_min[1], | klight->area.extentu[0], klight->area.extentu[1], klight->area.extentu[2]); | ||||
| kemitter->bounding_box_min[2]); | const float3 extentv = make_float3( | ||||
| const float3 bbox_max = make_float3(kemitter->bounding_box_max[0], | klight->area.extentv[0], klight->area.extentv[1], klight->area.extentv[2]); | ||||
| kemitter->bounding_box_max[1], | for (int i = 0; i < 4; i++) { | ||||
| kemitter->bounding_box_max[2]); | const float3 corner = ((i & 1) - 0.5f) * extentu + 0.5f * ((i & 2) - 1) * extentv + | ||||
| centroid = 0.5f * (bbox_min + bbox_max); | centroid; | ||||
| float distance; | float distance_point_to_corner; | ||||
| point_to_centroid = normalize_len(centroid - P, &distance); | const float3 point_to_corner = safe_normalize_len(corner - P, &distance_point_to_corner); | ||||
| max_distance = distance; | cos_theta_u = fminf(cos_theta_u, dot(point_to_centroid, point_to_corner)); | ||||
| bbox_is_visible |= dot(point_to_corner, N_or_D) > 0; | |||||
| max_distance = fmaxf(max_distance, distance_point_to_corner); | |||||
| } | |||||
| /* TODO: a cheap substitute for minimal distance between point and primitive. Does it worth | |||||
| * the overhead to compute the accurate minimal distance? */ | |||||
| min_distance = distance; | min_distance = distance; | ||||
| cos_theta_u = light_tree_cos_bounding_box_angle( | |||||
| bbox_min, bbox_max, P, N_or_D, point_to_centroid, bbox_is_visible); | |||||
| } | } | ||||
| if (klight->type == LIGHT_POINT) { | if (klight->type == LIGHT_POINT) { | ||||
| bcone_axis = -point_to_centroid; /* disk oriented normal */ | bcone_axis = -point_to_centroid; /* disk oriented normal */ | ||||
| theta_o = 0.0f; | theta_o = 0.0f; | ||||
| } | } | ||||
| } | } | ||||
| else { /* TODO: support mesh light */ | else { /* mesh light */ | ||||
| const float3 bbox_min = make_float3(kemitter->bounding_box_min[0], | const int object = kemitter->mesh_light.object_id; | ||||
| kemitter->bounding_box_min[1], | float3 V[3]; | ||||
| kemitter->bounding_box_min[2]); | triangle_world_space_vertices(kg, object, prim, -1.0f, V); | ||||
| const float3 bbox_max = make_float3(kemitter->bounding_box_max[0], | /* TODO: store in KernelLightTreeEmitter */ | ||||
| kemitter->bounding_box_max[1], | centroid = (V[0] + V[1] + V[2]) / 3.f; | ||||
| kemitter->bounding_box_max[2]); | point_to_centroid = safe_normalize_len(centroid - P, &distance); | ||||
| centroid = 0.5f * (bbox_min + bbox_max); | for (int i = 0; i < 3; i++) { | ||||
| float distance; | const float3 corner = V[i]; | ||||
| point_to_centroid = normalize_len(centroid - P, &distance); | float distance_point_to_corner; | ||||
| max_distance = distance; | const float3 point_to_corner = safe_normalize_len(corner - P, &distance_point_to_corner); | ||||
| cos_theta_u = fminf(cos_theta_u, dot(point_to_centroid, point_to_corner)); | |||||
| bbox_is_visible |= dot(point_to_corner, N_or_D) > 0; | |||||
| max_distance = fmaxf(max_distance, distance_point_to_corner); | |||||
| } | |||||
| min_distance = distance; | min_distance = distance; | ||||
| cos_theta_u = light_tree_cos_bounding_box_angle( | |||||
| bbox_min, bbox_max, P, N_or_D, point_to_centroid, bbox_is_visible); | |||||
| } | } | ||||
| if (!bbox_is_visible) { | if (!bbox_is_visible) { | ||||
| max_importance = 0.0f; | max_importance = 0.0f; | ||||
| min_importance = 0.0f; | min_importance = 0.0f; | ||||
| return; | return; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 799 Lines • Show Last 20 Lines | |||||