[Bf-blender-cvs] [fe8897ad4cd] soc-2022-many-lights-sampling: Cycles: support distant lights in tree
Jeffrey Liu
noreply at git.blender.org
Sat Jun 25 22:16:08 CEST 2022
Commit: fe8897ad4cdb2e9cbe25f3ecbd7289fffaa53b63
Author: Jeffrey Liu
Date: Sat Jun 25 16:00:31 2022 -0400
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rBfe8897ad4cdb2e9cbe25f3ecbd7289fffaa53b63
Cycles: support distant lights in tree
This is the initial support for sampling distant lights.
The heuristic needs to be adjusted but it works in basic cases.
===================================================================
M intern/cycles/kernel/data_arrays.h
M intern/cycles/kernel/light/light_tree.h
M intern/cycles/kernel/types.h
M intern/cycles/scene/light.cpp
M intern/cycles/scene/scene.cpp
M intern/cycles/scene/scene.h
===================================================================
diff --git a/intern/cycles/kernel/data_arrays.h b/intern/cycles/kernel/data_arrays.h
index 978e45f07b7..42e6e88509d 100644
--- a/intern/cycles/kernel/data_arrays.h
+++ b/intern/cycles/kernel/data_arrays.h
@@ -63,6 +63,7 @@ KERNEL_DATA_ARRAY(float2, light_background_conditional_cdf)
/* light tree */
KERNEL_DATA_ARRAY(KernelLightTreeNode, light_tree_nodes)
KERNEL_DATA_ARRAY(KernelLightTreeEmitter, light_tree_emitters)
+KERNEL_DATA_ARRAY(KernelLightTreeDistantEmitter, light_tree_distant_group)
/* particles */
KERNEL_DATA_ARRAY(KernelParticle, particles)
diff --git a/intern/cycles/kernel/light/light_tree.h b/intern/cycles/kernel/light/light_tree.h
index 788c2ccf90d..679dcda39f9 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -30,7 +30,7 @@ ccl_device float light_tree_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.
- * to-do: find a better way to handle this? */
+ * to-do: find a better way to handle this? or rename it to be more clear? */
ccl_device float light_tree_node_importance(const float3 P,
const float3 N,
const float3 bbox_min,
@@ -112,11 +112,10 @@ ccl_device float light_tree_cluster_importance(KernelGlobals kg,
P, N, bbox_min, bbox_max, bcone_axis, knode->theta_o, knode->theta_e, knode->energy);
}
-
/* to-do: for now, we're not going to worry about being in a volume for now,
* but this seems to be a good way to differentiate whether we're in a volume or not. */
template<bool in_volume_segment>
-ccl_device bool light_tree_sample(KernelGlobals kg,
+ccl_device int light_tree_sample(KernelGlobals kg,
ccl_private const RNGState *rng_state,
float randu,
const float randv,
@@ -186,11 +185,11 @@ ccl_device bool light_tree_sample(KernelGlobals kg,
emitter_cdf += emitter_pdf;
if (tree_u < emitter_cdf) {
*pdf_factor *= emitter_pdf;
- ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(light_distribution,
- prim_index);
+ ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(
+ light_distribution, prim_index);
- /* to-do: this is the same code as light_distribution_sample, except the index is determined differently.
- * Would it be better to refactor this into a separate function? */
+ /* to-do: this is the same code as light_distribution_sample, except the index is determined
+ * differently. Would it be better to refactor this into a separate function? */
const int prim = kdistribution->prim;
if (prim >= 0) {
@@ -224,6 +223,60 @@ ccl_device bool light_tree_sample(KernelGlobals kg,
return false;
}
+/* 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,
+ const int index)
+{
+ ccl_global const KernelLightTreeDistantEmitter *kdistant = &kernel_data_fetch(
+ light_tree_distant_group, index);
+ return kdistant->energy;
+}
+
+template<bool in_volume_segment>
+ccl_device int light_tree_sample_distant_lights(KernelGlobals kg,
+ ccl_private const RNGState *rng_state,
+ float randu,
+ const float randv,
+ const float time,
+ const float3 N,
+ const float3 P,
+ const int bounce,
+ const uint32_t path_flag,
+ ccl_private LightSample *ls,
+ float *pdf_factor)
+{
+ const int num_distant_lights = kernel_data.integrator.num_distant_lights;
+ float total_importance = 0.0f;
+ for (int i = 0; i < num_distant_lights; i++) {
+ total_importance += light_tree_distant_light_importance(kg, P, N, i);
+ }
+ const float inv_total_importance = 1 / total_importance;
+
+ float light_cdf = 0.0f;
+ float distant_u = path_state_rng_1D(kg, rng_state, 1);
+ for (int i = 0; i < num_distant_lights; i++) {
+ const float light_pdf = light_tree_distant_light_importance(kg, P, N, i) *
+ inv_total_importance;
+ light_cdf += light_pdf;
+ if (distant_u < light_cdf) {
+ *pdf_factor *= light_pdf;
+ ccl_global const KernelLightTreeDistantEmitter *kdistant = &kernel_data_fetch(
+ light_tree_distant_group, i);
+
+ const int lamp = -kdistant->prim_id - 1;
+
+ if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
+ return false;
+ }
+
+ return light_sample<in_volume_segment>(kg, lamp, randu, randv, P, path_flag, ls);
+ }
+ }
+}
+
ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
ccl_private const RNGState *rng_state,
float randu,
@@ -235,10 +288,40 @@ ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
const uint32_t path_flag,
ccl_private LightSample *ls)
{
- float pdf_factor;
- bool ret = light_tree_sample<false>(
- kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
- assert(pdf_factor != 0.0f);
+ const int num_distant_lights = kernel_data.integrator.num_distant_lights;
+ const int num_light_tree_prims = kernel_data.integrator.num_distribution - num_distant_lights;
+
+ float pdf_factor = 1.0f;
+ bool ret = false;
+ if (num_distant_lights == 0) {
+ ret = light_tree_sample<false>(
+ kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
+ }
+ else if (num_light_tree_prims == 0) {
+ ret = light_tree_sample_distant_lights<false>(
+ kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
+ }
+ else {
+ const ccl_global KernelLightTreeNode *knode = &kernel_data_fetch(light_tree_nodes, 0);
+ const float light_tree_importance = light_tree_cluster_importance(kg, P, N, knode);
+ const float distant_light_importance = light_tree_distant_light_importance(kg, P, N, num_distant_lights);
+
+ const float light_tree_probability = light_tree_importance /
+ (light_tree_importance +
+ distant_light_importance);
+
+ if (randu < light_tree_probability) {
+ ret = light_tree_sample<false>(
+ kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
+ pdf_factor *= light_tree_probability;
+ }
+ else {
+ ret = light_tree_sample_distant_lights<false>(
+ kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
+ pdf_factor *= (1 - light_tree_probability);
+ }
+ }
+
ls->pdf *= pdf_factor;
return ret;
}
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 474a6966ae5..09939ca074c 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -1239,6 +1239,7 @@ typedef struct KernelIntegrator {
int use_direct_light;
int num_distribution;
int num_all_lights;
+ int num_distant_lights;
float pdf_triangles;
float pdf_lights;
float light_inv_rr_threshold;
@@ -1303,7 +1304,7 @@ typedef struct KernelIntegrator {
float splitting_threshold;
/* padding */
- int pad1, pad2, pad3;
+ int pad1, pad2;
} KernelIntegrator;
static_assert_align(KernelIntegrator, 16);
@@ -1538,9 +1539,33 @@ typedef struct KernelLightTreeEmitter {
/* Energy. */
float energy;
+
+ /* prim_id denotes the location in the lights or triangles array. */
+ int prim_id;
+
+ /* Padding. */
+ int pad1, pad2, pad3;
} KernelLightTreeEmitter;
static_assert_align(KernelLightTreeEmitter, 16);
+typedef struct KernelLightTreeDistantEmitter {
+ /* Direction from world to light. */
+ float direction[3];
+
+ /* Size of light (in radians). */
+ float bounding_radius;
+
+ /* Energy. */
+ float energy;
+
+ /* Prim ID. */
+ int prim_id;
+
+ /* Padding. */
+ int pad1, pad2;
+} KernelLightTreeDistantEmitter;
+static_assert_align(KernelLightTreeDistantEmitter, 16);
+
typedef struct KernelParticle {
int index;
float age;
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index 97f0e98633f..a7b49bbff65 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -80,6 +80,35 @@ static void shade_background_pixels(Device *device,
});
}
+static float average_background_energy(Device *device,
+ DeviceScene *dscene,
+ Progress &progress,
+ Scene *scene,
+ Light *light)
+{
+ if (light->get_light_type() != LIGHT_BACKGROUND) {
+ assert(false);
+ }
+
+ /* get the resolution from the light's size (we stuff it in there) */
+ int2 res = make_int2(light->get_map_resolution(), light->get_map_resolution() / 2);
+ /* If it's still unknown, just use the default. */
+ if (res.x == 0 || res.y == 0) {
+ res = make_int2(1024, 512);
+ VLOG_INFO << "Setting World MIS resolution to default\n";
+ }
+
+ vector<float3> pixels;
+ shade_background_pixels(device, dscene, res.x, re
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list