[Bf-blender-cvs] [673ec13ffc5] soc-2022-many-lights-sampling: Add volume support
Weizhen Huang
noreply at git.blender.org
Wed Nov 9 13:16:51 CET 2022
Commit: 673ec13ffc5691543839f1f1a6950324459f3694
Author: Weizhen Huang
Date: Tue Nov 8 17:09:03 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB673ec13ffc5691543839f1f1a6950324459f3694
Add volume support
Differential Revision: https://developer.blender.org/D16422
===================================================================
M intern/cycles/kernel/integrator/shade_volume.h
M intern/cycles/kernel/light/sample.h
M intern/cycles/kernel/light/tree.h
===================================================================
diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h
index daaf480e8c1..5b5abe05720 100644
--- a/intern/cycles/kernel/integrator/shade_volume.h
+++ b/intern/cycles/kernel/integrator/shade_volume.h
@@ -697,7 +697,7 @@ ccl_device_forceinline bool integrate_volume_sample_light(
/* Sample position on a light. */
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
const uint bounce = INTEGRATOR_STATE(state, path, bounce);
- const float2 rand_light = path_state_rng_2D(kg, rng_state, PRNG_VOLUME_SEGMENT_LIGHT);
+ float2 rand_light = path_state_rng_2D(kg, rng_state, PRNG_VOLUME_SEGMENT_LIGHT);
if (!light_sample_from_volume_segment(kg,
rng_state,
@@ -740,7 +740,7 @@ ccl_device_forceinline void integrate_volume_direct_light(
/* Sample position on the same light again, now from the shading point where we scattered.
*
- * Note that this means we sample the light three twice when equiangular sampling is used.
+ * Note that this means we sample the light tree twice when equiangular sampling is used.
* We could consider sampling the light tree just once and use the same light position again.
*
* This would make the PDFs for MIS weights more complicated due to having to account for
diff --git a/intern/cycles/kernel/light/sample.h b/intern/cycles/kernel/light/sample.h
index 366deafb4d7..a9bb9bdbc44 100644
--- a/intern/cycles/kernel/light/sample.h
+++ b/intern/cycles/kernel/light/sample.h
@@ -322,7 +322,7 @@ ccl_device_inline float light_sample_mis_weight_nee(KernelGlobals kg,
ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
ccl_private const RNGState *rng_state,
- const float randu,
+ float randu,
const float randv,
const float time,
const float3 P,
@@ -332,29 +332,23 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
const uint32_t path_flag,
ccl_private LightSample *ls)
{
- /* TODO: implement light tree support. */
-#if 0
if (kernel_data.integrator.use_light_tree) {
- return light_tree_sample<true>(
- kg,
- rng_state,
- randu,
- randv,
- time,
- P,
- D,
- t,
- SD_BSDF_HAS_TRANSMISSION,
- bounce,
- path_flag,
- ls);
+ return light_tree_sample<true>(kg,
+ rng_state,
+ randu,
+ randv,
+ time,
+ P,
+ D,
+ t,
+ SD_BSDF_HAS_TRANSMISSION,
+ bounce,
+ path_flag,
+ ls);
}
else {
-#endif
- return light_distribution_sample<true>(kg, randu, randv, time, P, bounce, path_flag, ls);
-#if 0
+ return light_distribution_sample<true>(kg, randu, randv, time, P, bounce, path_flag, ls);
}
-#endif
}
ccl_device bool light_sample_from_position(KernelGlobals kg,
@@ -371,7 +365,7 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
{
if (kernel_data.integrator.use_light_tree) {
return light_tree_sample<false>(
- kg, rng_state, randu, randv, time, P, N, shader_flags, bounce, path_flag, ls);
+ kg, rng_state, randu, randv, time, P, N, 0, shader_flags, bounce, path_flag, ls);
}
else {
return light_distribution_sample<false>(kg, randu, randv, time, P, bounce, path_flag, ls);
diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index 4e9a560c10c..6e229a87957 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -40,13 +40,16 @@ ccl_device float light_tree_cos_bounding_box_angle(const float3 bbox_min,
/* 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. */
-ccl_device void light_tree_cluster_importance(const float3 N,
+template<bool in_volume_segment>
+ccl_device void light_tree_cluster_importance(const float3 N_or_D,
const bool has_transmission,
const float3 point_to_centroid,
+ /* point_to_centroid is unnormalized for volume */
const float cos_theta_u,
const float3 bcone_axis,
- const float inv_max_distance_squared,
- const float inv_min_distance_squared,
+ const float max_distance,
+ const float min_distance,
+ const float t,
const float theta_o,
const float theta_e,
const float energy,
@@ -56,22 +59,48 @@ ccl_device void light_tree_cluster_importance(const float3 N,
max_importance = 0.0f;
min_importance = 0.0f;
- const float cos_theta = dot(bcone_axis, -point_to_centroid);
- const float cos_theta_i = has_transmission ? fabsf(dot(point_to_centroid, N)) :
- dot(point_to_centroid, N);
- const float sin_theta_i = safe_sqrtf(1.0f - sqr(cos_theta_i));
+ float cos_theta, cos_theta_i, sin_theta_i;
+ float cos_min_outgoing_angle; /* minimum angle an emitter’s axis would form with the
+ direction to the shading point, cos(theta') in the paper */
+ float cos_min_incidence_angle = 1.0f; /* cos(theta_i') in the paper, omitted for volume */
const float sin_theta_u = safe_sqrtf(1.0f - sqr(cos_theta_u));
- /* cos_min_incidence_angle = cos(max{theta_i - theta_u, 0}), also cos(theta_i') in the paper*/
- const float cos_min_incidence_angle = cos_theta_i > cos_theta_u ?
- 1.0f :
- cos_theta_i * cos_theta_u + sin_theta_i * sin_theta_u;
- /* 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;
+ 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 {
+ const float3 N = N_or_D;
+
+ cos_theta = dot(bcone_axis, -point_to_centroid);
+ 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}), also 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;
+ /* 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 - theta_u) */
@@ -81,9 +110,6 @@ ccl_device void light_tree_cluster_importance(const float3 N,
float cos_theta_o, sin_theta_o;
fast_sincosf(theta_o, &sin_theta_o, &cos_theta_o);
- float cos_min_outgoing_angle; /* minimum angle an emitter’s normal would form with the direction
- to the shading point, cos(theta') in the paper */
-
if ((cos_theta > cos_theta_u) || (cos_theta_minus_theta_u > cos_theta_o)) {
/* theta - theta_o - theta_u < 0 */
kernel_assert((fast_acosf(cos_theta) - theta_o - fast_acosf(cos_theta_u)) < 5e-4f);
@@ -98,19 +124,23 @@ ccl_device void light_tree_cluster_importance(const float3 N,
sin_theta_minus_theta_u * sin_theta_o;
}
else {
+ /* cluster invisible */
return;
}
/* TODO: find a good approximation for f_a. */
const float f_a = 1.0f;
- max_importance = fabsf(f_a * cos_min_incidence_angle * energy * inv_min_distance_squared *
- cos_min_outgoing_angle);
+ /* 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 /
+ (in_volume_segment ? min_distance : sqr(min_distance)));
- if (inv_max_distance_squared == inv_min_distance_squ
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list