[Bf-blender-cvs] [762aa998f3d] soc-2022-many-lights-sampling: Recompute theta_u from the point of theta_min for interior nodes in volume
Weizhen Huang
noreply at git.blender.org
Fri Nov 25 18:32:05 CET 2022
Commit: 762aa998f3d05958519124f1c11f2c74e6184f2f
Author: Weizhen Huang
Date: Fri Nov 25 18:30:44 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB762aa998f3d05958519124f1c11f2c74e6184f2f
Recompute theta_u from the point of theta_min for interior nodes in volume
===================================================================
M intern/cycles/kernel/light/tree.h
===================================================================
diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index fff73a1392c..17c1df99b34 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -38,6 +38,59 @@ ccl_device float light_tree_cos_bounding_box_angle(const float3 bbox_min,
return cos_theta_u;
}
+ccl_device_inline float sin_from_cos(const float c)
+{
+ return safe_sqrtf(1.0f - sqr(c));
+}
+
+/* Compute vector v as in Fig .8. P_v is the corresponding point along the ray ccl_device float3 */
+ccl_device float3 compute_v(const float3 centroid,
+ const float3 P,
+ const float3 D,
+ const float3 bcone_axis,
+ float t,
+ ccl_private float3 &P_v)
+{
+ t = fminf(t, 1e12f);
+
+ const float3 unnormalized_v0 = P - centroid;
+ float len_v0;
+ const float3 unnormalized_v1 = unnormalized_v0 + D * t;
+ const float3 v0 = normalize_len(unnormalized_v0, &len_v0);
+ const float3 v1 = normalize(unnormalized_v1);
+
+ const float3 o0 = v0;
+ float3 o1, o2;
+ make_orthonormals_tangent(o0, v1, &o1, &o2);
+
+ const float dot_o0_a = dot(o0, bcone_axis);
+ const float dot_o1_a = dot(o1, bcone_axis);
+ const float cos_phi0 = dot_o0_a / sqrtf(sqr(dot_o0_a) + sqr(dot_o1_a));
+
+ float3 v;
+ float t_v;
+ if (dot_o1_a < 0 || dot(v0, v1) > cos_phi0) {
+ if (dot_o0_a > dot(v1, bcone_axis)) {
+ v = v0;
+ t_v = 0.0f;
+ }
+ else {
+ v = v1;
+ t_v = t;
+ }
+ }
+ else {
+ const float sin_phi0 = sin_from_cos(cos_phi0);
+ v = cos_phi0 * o0 + sin_phi0 * o1;
+ const float cos_phi1 = dot(-v0, D);
+ const float sin_phi1 = sin_from_cos(cos_phi1);
+ /* sin(phi_0) / t_v = sin(phi_0 + phi_1) / len_v0 */
+ t_v = len_v0 / (cos_phi1 + cos_phi0 / sin_phi0 * sin_phi1);
+ }
+ P_v = P + D * t_v;
+ return v;
+}
+
/* This is the general function for calculating the importance of either a cluster or an emitter.
* Both of the specialized functions obtain the necessary data before calling this function. */
template<bool in_volume_segment>
@@ -68,47 +121,26 @@ ccl_device void light_tree_cluster_importance(const float3 N_or_D,
* `sample.h` */
const bool in_volume = (dot(N_or_D, N_or_D) < 5e-4f);
- if (in_volume_segment) {
- const float3 D = N_or_D;
- const float3 v0 = -normalize(point_to_centroid);
- const float3 v1 = normalize(-point_to_centroid + D * fminf(t, 1e12f));
-
- const float3 o0 = v0;
- float3 o1, o2;
- make_orthonormals_tangent(o0, v1, &o1, &o2);
-
- const float dot_o0_a = dot(o0, bcone_axis);
- const float dot_o1_a = dot(o1, bcone_axis);
- const float cos_phi0 = dot_o0_a / sqrtf(sqr(dot_o0_a) + sqr(dot_o1_a));
-
- /* Eq. (6) */
- cos_theta = (dot_o1_a < 0 || dot(v0, v1) > cos_phi0) ?
- fmaxf(dot_o0_a, dot(v1, bcone_axis)) : /* b_max */
- dot(bcone_axis, cos_phi0 * o0 + safe_sqrtf(1.0f - sqr(cos_phi0)) * o1);
- }
- else {
- cos_theta = dot(bcone_axis, -point_to_centroid);
- if (!in_volume) {
- const float3 N = N_or_D;
- cos_theta_i = has_transmission ? fabsf(dot(point_to_centroid, N)) :
- dot(point_to_centroid, N);
- sin_theta_i = safe_sqrtf(1.0f - sqr(cos_theta_i));
-
- /* cos_min_incidence_angle = cos(max{theta_i - theta_u, 0}) = cos(theta_i') in the paper */
- cos_min_incidence_angle = cos_theta_i > cos_theta_u ?
- 1.0f :
- cos_theta_i * cos_theta_u + sin_theta_i * sin_theta_u;
-
- /* cos_max_incidence_angle = cos(min{theta_i + theta_u, pi}) */
- cos_max_incidence_angle = fmaxf(cos_theta_i * cos_theta_u - sin_theta_i * sin_theta_u, 0.0f);
-
- /* If the node is guaranteed to be behind the surface we're sampling, and the surface is
- * opaque, then we can give the node an importance of 0 as it contributes nothing to the
- * surface. This is more accurate than the bbox test if we are calculating the importance of
- * an emitter with radius */
- if (!has_transmission && cos_min_incidence_angle < 0) {
- return;
- }
+ cos_theta = dot(bcone_axis, -point_to_centroid);
+ if (!in_volume_segment && !in_volume) {
+ const float3 N = N_or_D;
+ cos_theta_i = has_transmission ? fabsf(dot(point_to_centroid, N)) : dot(point_to_centroid, N);
+ sin_theta_i = safe_sqrtf(1.0f - sqr(cos_theta_i));
+
+ /* cos_min_incidence_angle = cos(max{theta_i - theta_u, 0}) = cos(theta_i') in the paper */
+ cos_min_incidence_angle = cos_theta_i > cos_theta_u ?
+ 1.0f :
+ cos_theta_i * cos_theta_u + sin_theta_i * sin_theta_u;
+
+ /* cos_max_incidence_angle = cos(min{theta_i + theta_u, pi}) */
+ cos_max_incidence_angle = fmaxf(cos_theta_i * cos_theta_u - sin_theta_i * sin_theta_u, 0.0f);
+
+ /* If the node is guaranteed to be behind the surface we're sampling, and the surface is
+ * opaque, then we can give the node an importance of 0 as it contributes nothing to the
+ * surface. This is more accurate than the bbox test if we are calculating the importance of
+ * an emitter with radius */
+ if (!has_transmission && cos_min_incidence_angle < 0) {
+ return;
}
}
@@ -290,11 +322,13 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
/* TODO: better measure for single emitter */
if (in_volume_segment) {
const float3 D = N_or_D;
- const float3 closest_point = P + distance * dot(point_to_centroid, D) * D;
+ const float3 closest_point = P + dot(centroid - P, D) * D;
/* minimal distance of the ray to the cluster */
min_distance = len(centroid - closest_point);
max_distance = min_distance;
- point_to_centroid = centroid - P;
+ float3 P_v;
+ float t_v;
+ point_to_centroid = -compute_v(centroid, P, D, bcone_axis, t, P_v);
}
light_tree_cluster_importance<in_volume_segment>(N_or_D,
@@ -367,10 +401,14 @@ ccl_device void light_tree_node_importance(KernelGlobals kg,
if (in_volume_segment) {
const float3 D = N_or_D;
- const float3 closest_point = P + distance * dot(point_to_centroid, D) * D;
+ const float3 closest_point = P + dot(centroid - P, D) * D;
/* minimal distance of the ray to the cluster */
distance = len(centroid - closest_point);
- point_to_centroid = centroid - P;
+ float3 P_v;
+ float t_v;
+ point_to_centroid = -compute_v(centroid, P, D, bcone_axis, t, P_v);
+ cos_theta_u = light_tree_cos_bounding_box_angle(
+ bbox_min, bbox_max, P_v, D, point_to_centroid, bbox_is_visible);
}
/* clamp distance to half the radius of the cluster when splitting is disabled */
distance = fmaxf(0.5f * len(centroid - bbox_max), distance);
More information about the Bf-blender-cvs
mailing list