[Bf-blender-cvs] [7b3c1a203ef] soc-2022-many-lights-sampling: Cycles: update distant light importance heuristics
Jeffrey Liu
noreply at git.blender.org
Sat Jul 9 22:01:42 CEST 2022
Commit: 7b3c1a203efdecf08d0aa041a76a984f2d72d870
Author: Jeffrey Liu
Date: Sat Jul 9 16:01:03 2022 -0400
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB7b3c1a203efdecf08d0aa041a76a984f2d72d870
Cycles: update distant light importance heuristics
===================================================================
M intern/cycles/kernel/light/light_tree.h
M intern/cycles/kernel/types.h
M intern/cycles/scene/light.cpp
===================================================================
diff --git a/intern/cycles/kernel/light/light_tree.h b/intern/cycles/kernel/light/light_tree.h
index 1b9e5d3806b..0ba28982e91 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -69,7 +69,7 @@ ccl_device float light_tree_node_importance(const float3 P,
}
/* to-do: find a good approximation for this value. */
- const float f_a = 1;
+ const float f_a = 1.0f;
float importance = f_a * cos_theta_i_prime * energy / distance_squared * cos_theta_prime;
return importance;
@@ -225,8 +225,6 @@ ccl_device int light_tree_sample(KernelGlobals kg,
return -1;
}
-/* to-do: assign relative importances for the background and distant lights.
- * Can we somehow adjust the importance measure to account for these as well? */
ccl_device float light_tree_distant_light_importance(KernelGlobals kg,
const float3 P,
const float3 N,
@@ -234,7 +232,28 @@ ccl_device float light_tree_distant_light_importance(KernelGlobals kg,
{
ccl_global const KernelLightTreeDistantEmitter *kdistant = &kernel_data_fetch(
light_tree_distant_group, index);
- return kdistant->energy;
+
+ if (kdistant->energy == 0.0f) {
+ return 0.0f;
+ }
+
+ const float3 light_axis = make_float3(
+ kdistant->direction[0], kdistant->direction[1], kdistant->direction[2]);
+ const float theta = fast_acosf(dot(N, light_axis));
+ const float theta_i_prime = theta - kdistant->bounding_radius;
+
+ float cos_theta_i_prime = 1;
+ if (theta_i_prime > M_PI_2_F) {
+ return 0.0f;
+ } else if (theta - kdistant->bounding_radius > 0) {
+ cos_theta_i_prime = fast_cosf(theta - kdistant->bounding_radius);
+ }
+
+ /* to-do: find a good value for this. */
+ const float f_a = 1.0f;
+ float importance = f_a * cos_theta_i_prime * kdistant->energy;
+
+ return importance;
}
template<bool in_volume_segment>
@@ -286,7 +305,16 @@ ccl_device int light_tree_sample_distant_lights(KernelGlobals kg,
/* We need to be able to find the probability of selecting a given light, for MIS. */
ccl_device float light_tree_pdf(KernelGlobals kg, const float3 P, const float3 N, const int prim)
{
- float pdf = kernel_data.integrator.pdf_light_tree;
+ float distant_light_importance = light_tree_distant_light_importance(
+ kg, P, N, kernel_data.integrator.num_distant_lights);
+ float light_tree_importance = 0.0f;
+ if (kernel_data.integrator.num_distribution > kernel_data.integrator.num_distant_lights) {
+ const ccl_global KernelLightTreeNode *kroot = &kernel_data_fetch(light_tree_nodes, 0);
+ light_tree_importance = light_tree_cluster_importance(kg, P, N, kroot);
+ }
+ const float total_group_importance = light_tree_importance + distant_light_importance;
+ assert(total_group_importance != 0.0f);
+ float pdf = light_tree_importance / total_group_importance;
const int emitter = (prim >= 0) ? kernel_data_fetch(triangle_to_tree, prim) :
kernel_data_fetch(light_to_tree, ~prim);
@@ -351,7 +379,16 @@ ccl_device float distant_lights_pdf(KernelGlobals kg,
const float3 N,
const int prim)
{
- float pdf = (1 - kernel_data.integrator.pdf_light_tree);
+ float distant_light_importance = light_tree_distant_light_importance(
+ kg, P, N, kernel_data.integrator.num_distant_lights);
+ float light_tree_importance = 0.0f;
+ if (kernel_data.integrator.num_distribution > kernel_data.integrator.num_distant_lights) {
+ const ccl_global KernelLightTreeNode *kroot = &kernel_data_fetch(light_tree_nodes, 0);
+ light_tree_importance = light_tree_cluster_importance(kg, P, N, kroot);
+ }
+ const float total_group_importance = light_tree_importance + distant_light_importance;
+ assert(total_group_importance != 0.0f);
+ float pdf = distant_light_importance / total_group_importance;
/* The light_to_tree array doubles as a lookup table for
* both the light tree as well as the distant lights group.*/
@@ -383,16 +420,31 @@ ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
const uint32_t path_flag,
ccl_private LightSample *ls)
{
+ float distant_light_importance = light_tree_distant_light_importance(
+ kg, P, N, kernel_data.integrator.num_distant_lights);
+ float light_tree_importance = 0.0f;
+ if (kernel_data.integrator.num_distribution > kernel_data.integrator.num_distant_lights) {
+ const ccl_global KernelLightTreeNode *kroot = &kernel_data_fetch(light_tree_nodes, 0);
+ light_tree_importance = light_tree_cluster_importance(kg, P, N, kroot);
+ }
+ const float total_importance = light_tree_importance + distant_light_importance;
+
+ if (total_importance == 0.0f) {
+ return false;
+ }
+
+ const float light_tree_probability = light_tree_importance / total_importance;
+
float pdf_factor = 1.0f;
bool ret;
float tree_u = path_state_rng_1D(kg, rng_state, 1);
- if (tree_u < kernel_data.integrator.pdf_light_tree) {
- pdf_factor *= kernel_data.integrator.pdf_light_tree;
+ if (tree_u < light_tree_probability) {
+ pdf_factor *= light_tree_probability;
ret = light_tree_sample<false>(
kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
}
else {
- pdf_factor *= (1 - kernel_data.integrator.pdf_light_tree);
+ pdf_factor *= (1 - light_tree_probability);
ret = light_tree_sample_distant_lights<false>(
kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
}
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 9def2e5690b..793b6d4c309 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -1303,12 +1303,11 @@ typedef struct KernelIntegrator {
int direct_light_sampling_type;
/* Light tree. */
- float pdf_light_tree;
int use_light_tree;
float splitting_threshold;
/* padding */
- int pad1;
+ int pad1, pad2;
} KernelIntegrator;
static_assert_align(KernelIntegrator, 16);
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index 6278e3efd93..15cbfc36d7a 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -389,7 +389,6 @@ void LightManager::device_update_distribution(Device *device,
size_t num_distribution = num_triangles + num_lights;
VLOG_INFO << "Total " << num_distribution << " of light distribution primitives.";
- float pdf_light_tree = 0.0f;
if (light_tree_enabled && num_distribution > 0) {
/* For now, we'll start with a smaller number of max lights in a node.
* More benchmarking is needed to determine what number works best. */
@@ -492,11 +491,15 @@ void LightManager::device_update_distribution(Device *device,
/* We also add distant lights to a separate group. */
KernelLightTreeDistantEmitter *light_tree_distant_group =
- dscene->light_tree_distant_group.alloc(num_distant_lights);
+ dscene->light_tree_distant_group.alloc(num_distant_lights + 1);
+
+ /* We use OrientationBounds here to */
+ OrientationBounds distant_light_bounds = OrientationBounds::empty;
float distant_light_energy = 0.0f;
for (int index = 0; index < num_distant_lights; index++) {
LightTreePrimitive prim = distant_lights[index];
Light *light = scene->lights[prim.lamp_id];
+ OrientationBounds light_bounds;
/* Lights in this group are either a background or distant light. */
light_tree_distant_group[index].prim_id = ~prim.prim_id;
@@ -506,30 +509,39 @@ void LightManager::device_update_distribution(Device *device,
energy = average_background_energy(device, dscene, progress, scene, light);
/* We can set an arbitrary direction for the background light. */
- light_tree_distant_group[index].direction[0] = 0.0f;
- light_tree_distant_group[index].direction[1] = 0.0f;
- light_tree_distant_group[index].direction[2] = 1.0f;
+ light_bounds.axis[0] = 0.0f;
+ light_bounds.axis[1] = 0.0f;
+ light_bounds.axis[2] = 1.0f;
/* to-do: this may depend on portal lights as well. */
- light_tree_distant_group[index].bounding_radius = M_PI_F;
+ light_bounds.theta_o = M_PI_F;
}
else {
energy = prim.calculate_energy(scene);
-
for (int i = 0; i < 3; i++) {
- light_tree_distant_group[index].direction[i] = -light->co[i];
+ light_bounds.axis[i] = -light->dir[i];
}
- light_tree_distant_group[index].bounding_radius = tanf(light->angle * 0.5f);
+ light_bounds.theta_o = tanf(light->angle * 0.5f);
+ }
+
+ distant_light_bounds = merge(distant_light_bounds, light_bounds);
+ for (int i = 0; i < 3; i++) {
+ light_tree_distant_group[index].direction[i] = light_bounds.axis[i];
}
+ light_tree_distant_group[index].bounding_radius = light_bounds.theta_o;
light_tree_distant_group[index].energy = energy;
light_array[~prim.prim_id] = index;
distant_light_energy += energy;
- }
+ }
- if (light_tree_energy > 0.0f) {
- pdf_light_tree = light_tree_energy / (light_tree_energy + distant_light_energy);
+ /* The net OrientationBounds contain bounding information about all the distant lights. */
+ light_tree_distant_group[num_distant_lights].prim_id = -1;
+ light_tree_distant_group[num_distant_lights].energy = distant_light_energy;
+ for (int i = 0; i < 3; i++) {
+ light_tree_distant_group[num_distant_lights].direction[i] = distant_light_bounds.axis[i];
}
+ light_tree_distant_group[num_distant_lights].bounding_radius = distant_light_bounds.theta_o;
dscene->light_tree_nodes.copy_to_device();
dscene->light_tree_emitters.copy_to_device();
@@ -688,7 +700,6 @@ void LightManager::device_update_distribution(Device *device,
/* pdf_lights is used when sampling lights, and assumes that
* the light has been sampled through the light distribution.
* Therefore, we override it for now a
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list