[Bf-blender-cvs] [8d20d9d9eea] soc-2020-production-ready-light-tree: Initial attempt at splitting for volumes.
Sam Kottler
noreply at git.blender.org
Tue Aug 4 22:17:04 CEST 2020
Commit: 8d20d9d9eea981884bf1a2ee7de032391954ffaf
Author: Sam Kottler
Date: Tue Aug 4 15:15:52 2020 -0500
Branches: soc-2020-production-ready-light-tree
https://developer.blender.org/rB8d20d9d9eea981884bf1a2ee7de032391954ffaf
Initial attempt at splitting for volumes.
===================================================================
M intern/cycles/kernel/kernel_path_volume.h
===================================================================
diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index 83e1019a2f2..1b9a8006382 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -137,6 +137,212 @@ ccl_device_noinline_cpu bool kernel_path_volume_bounce(KernelGlobals *kg,
}
# if !defined(__SPLIT_KERNEL__) && (defined(__BRANCHED_PATH__) || defined(__VOLUME_DECOUPLED__))
+ccl_device void accum_light_tree_contribution_volume(KernelGlobals *kg,
+ float randu,
+ float randv,
+ int offset,
+ float pdf_factor,
+ bool can_split,
+ float3 throughput,
+ float scale_factor,
+ PathRadiance *L,
+ ccl_addr_space PathState *state,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ Ray *ray,
+ const VolumeSegment *segment)
+{
+ float3 P = sd->P_pick;
+ float3 N = sd->N_pick;
+ float t = sd->t_pick;
+
+ float time = sd->time;
+ int bounce = state->bounce;
+
+ float randu_stack[64];
+ float randv_stack[64];
+ int offset_stack[64];
+ float pdf_stack[64];
+
+ randu_stack[0] = randu;
+ randv_stack[0] = randv;
+ offset_stack[0] = offset;
+ pdf_stack[0] = pdf_factor;
+
+ int stack_idx = 0;
+
+ while (stack_idx > -1) {
+ randu = randu_stack[stack_idx];
+ randv = randv_stack[stack_idx];
+ offset = offset_stack[stack_idx];
+ pdf_factor = pdf_stack[stack_idx];
+ /* read in first part of node of light tree */
+ int right_child_offset, distribution_id, num_emitters;
+ update_node(kg, offset, &right_child_offset, &distribution_id, &num_emitters);
+
+ /* found a leaf */
+ if (right_child_offset == -1) {
+
+ /* if there are several emitters in this leaf then pick one of them */
+ if (num_emitters > 1) {
+
+ /* create and sample CDF without dynamic allocation.
+ * see comment in light_tree_sample() for this piece of code */
+ float sum = 0.0f;
+ for (int i = 0; i < num_emitters; ++i) {
+ sum += calc_light_importance(kg, t, P, N, offset, i);
+ }
+
+ if (sum == 0.0f) {
+ --stack_idx;
+ continue;
+ }
+
+ float sum_inv = 1.0f / sum;
+ float cdf_L = 0.0f;
+ float cdf_R = 0.0f;
+ float prob = 0.0f;
+ int light = num_emitters - 1;
+ for (int i = 1; i < num_emitters + 1; ++i) {
+ prob = calc_light_importance(kg, t, P, N, offset, i - 1) * sum_inv;
+ cdf_R = cdf_L + prob;
+ if (randu < cdf_R) {
+ light = i - 1;
+ break;
+ }
+
+ cdf_L = cdf_R;
+ }
+ distribution_id += light;
+ pdf_factor *= prob;
+
+ /* rescale random number */
+ randu = (randu - cdf_L) / (cdf_R - cdf_L);
+ }
+
+ /* pick a point on the chosen light(distribution_id) and calculate the
+ * probability of picking this point */
+ LightSample ls;
+ light_point_sample(kg, -1, randu, randv, time, P, bounce, distribution_id, &ls);
+
+ /* combine pdfs */
+ ls.pdf *= pdf_factor;
+
+ /* compute and accumulate the total contribution of this light */
+ Ray light_ray;
+ light_ray.t = 0.0f;
+# ifdef __OBJECT_MOTION__
+ light_ray.time = sd->time;
+# endif
+ float3 tp = throughput;
+ bool has_emission = false;
+ bool is_lamp = false;
+ BsdfEval L_light ccl_optional_struct_init;
+ /* sample position on volume segment */
+ float rphase = path_branched_rng_1D(
+ kg, state->rng_hash, state, distribution_id, 1.0f, PRNG_PHASE_CHANNEL);
+ float rscatter = path_branched_rng_1D(
+ kg, state->rng_hash, state, distribution_id, 1.0f, PRNG_SCATTER_DISTANCE);
+
+ VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
+ state,
+ ray,
+ sd,
+ &tp,
+ rphase,
+ rscatter,
+ segment,
+ (ls.t != FLT_MAX) ? &ls.P :
+ NULL,
+ false);
+ if (result == VOLUME_PATH_SCATTERED) {
+ light_point_sample(kg, -1, randu, randv, time, sd->P_pick, bounce, distribution_id, &ls);
+ if (ls.pdf <= 0.0f) {
+ --stack_idx;
+ continue;
+ }
+ /* sample random light */
+ float terminate = path_branched_rng_light_termination(
+ kg, state->rng_hash, state, distribution_id, 1.0f);
+ has_emission = direct_emission(
+ kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate);
+ }
+
+ /* trace shadow ray */
+ float3 shadow;
+
+ const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow);
+
+ if (has_emission && !blocked) {
+ /* accumulate */
+ path_radiance_accum_light(kg, L, state, tp, &L_light, shadow, 1.0f, is_lamp);
+ }
+
+ --stack_idx;
+ can_split = true;
+ continue;
+ }
+ else { // Interior node, choose which child(ren) to go down
+
+ int child_offsetL = offset + 4;
+ int child_offsetR = 4 * right_child_offset;
+
+ /* choose whether to go down both(split) or only one of the children */
+ if (can_split && split(kg, P, offset)) {
+ /* go down both child nodes */
+ //++stack_idx;
+ randu_stack[stack_idx] = randu;
+ randv_stack[stack_idx] = randv;
+ offset_stack[stack_idx] = child_offsetL;
+ pdf_stack[stack_idx] = pdf_factor;
+
+ ++stack_idx;
+ randu_stack[stack_idx] = randu;
+ randv_stack[stack_idx] = randv;
+ offset_stack[stack_idx] = child_offsetR;
+ pdf_stack[stack_idx] = pdf_factor;
+ }
+ else {
+ /* go down one of the child nodes */
+
+ /* evaluate the importance of each of the child nodes */
+ float I_L = calc_node_importance(kg, t, P, N, child_offsetL);
+ float I_R = calc_node_importance(kg, t, P, N, child_offsetR);
+
+ if ((I_L == 0.0f) && (I_R == 0.0f)) {
+ return;
+ }
+
+ /* calculate the probability of going down the left node */
+ float P_L = I_L / (I_L + I_R);
+
+ /* choose which node to go down */
+ if (randu <= P_L) { // Going down left node
+ /* rescale random number */
+ randu = randu / P_L;
+
+ offset = child_offsetL;
+ pdf_factor *= P_L;
+ }
+ else { // Going down right node
+ /* rescale random number */
+ randu = (randu * (I_L + I_R) - I_L) / I_R;
+
+ offset = child_offsetR;
+ pdf_factor *= 1.0f - P_L;
+ }
+
+ //++stack_idx;
+ can_split = false;
+ randu_stack[stack_idx] = randu;
+ randv_stack[stack_idx] = randv;
+ offset_stack[stack_idx] = offset;
+ pdf_stack[stack_idx] = pdf_factor;
+ }
+ }
+ }
+}
+
ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg,
ShaderData *sd,
ShaderData *emission_sd,
@@ -151,127 +357,227 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg,
BsdfEval L_light ccl_optional_struct_init;
bool use_light_tree = kernel_data.integrator.use_light_tree;
- int num_lights = 1;
- if (sample_all_lights && !use_light_tree) {
- num_lights = kernel_data.integrator.num_all_lights;
- if (kernel_data.integrator.pdf_triangles != 0.0f) {
- num_lights += 1;
+ if (use_light_tree) {
+ Ray light_ray;
+ bool is_lamp;
+
+ light_ray.t = 0.0f;
+# ifdef __OBJECT_MOTION__
+ light_ray.time = sd->time;
+# endif
+
+ int index;
+ float randu, randv;
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &randu, &randv);
+
+ /* sample light group distribution */
+ int group = light_group_distribution_sample(kg, &randu);
+ float group_prob = kernel_tex_fetch(__light_group_sample_prob, group);
+ float pdf = 1.0f;
+
+ if (group == LIGHTGROUP_TREE) {
+ /* accumulate contribution to L from potentially several lights */
+ accum_light_tree_contribution_volume(kg,
+ randu,
+ randv,
+ 0,
+ group_prob,
+ true,
+ throughput,
+ 1.0f,
+ L, // todo: is num_samples_adjust correct here?
+ state,
+ sd,
+ emission_sd,
+ ray,
+ segment);
+
+ /* have accumulated all the contributions so return */
+ return;
+ }
+ else if (group == LIGHTGROUP_DISTANT) {
+ /* pick a single distant light */
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list