Commit: ff4833a6b395eef84e2a60a32f934c2f3a0e7d63
Author: Erik Englesson
Date: Thu Jul 12 16:40:58 2018 +0200
Branches: gsoc-2018-many-light-sampling
https://developer.blender.org/rBff4833a6b395eef84e2a60a32f934c2f3a0e7d63
Cycles: Bug fixes
- Stopping recursive tree traversal if
negative PDFs are encountered.
- accum_light_tree_contribution() now
takes a scale factor as input which
is passed through to accum_light_contribution
- light_bvh_sample now changes randu. This
is similar to the other *_sample functions.
This fixed a bug where recursive traversal
with no splitting gave a different result
compared to just using light_sample.
===================================================================
M intern/cycles/kernel/kernel_light.h
M intern/cycles/kernel/kernel_path_surface.h
===================================================================
diff --git a/intern/cycles/kernel/kernel_light.h
b/intern/cycles/kernel/kernel_light.h
index 8346aea1386..73e12fe4824 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -1205,25 +1205,24 @@ ccl_device void light_background_sample(KernelGlobals
*kg, float3 P, float *rand
/* picks a light from the light BVH and returns its index and the probability
of
* picking this light. */
ccl_device void light_bvh_sample(KernelGlobals *kg, float3 P, float3 N,
- float randu, int *index, float *pdf_factor)
+ float *randu, int *index, float *pdf_factor)
{
int sampled_index = -1;
*pdf_factor = 1.0f;
- /* read in first part of root node of light BVH */
- int secondChildOffset, distribution_id, num_emitters;
- update_parent_node(kg, 0, &secondChildOffset, &distribution_id,
&num_emitters);
-
int offset = 0;
+ int secondChildOffset, distribution_id, num_emitters;
do{
+ /* read in first part of node of light BVH */
+ update_parent_node(kg, offset, &secondChildOffset,
&distribution_id, &num_emitters);
+
/* Found a leaf - Choose which light to use */
if(secondChildOffset == -1){ // Found a leaf
if(num_emitters == 1){
-
sampled_index = distribution_id;
} else { // Leaf with several lights. Pick one randomly.
- int light = min((int)(randu*
(float)num_emitters), num_emitters-1);
+ int light = min((int)(*randu *
(float)num_emitters), num_emitters-1);
sampled_index = distribution_id +light;
*pdf_factor *= 1.0f / (float)num_emitters;
}
@@ -1235,33 +1234,28 @@ ccl_device void light_bvh_sample(KernelGlobals *kg,
float3 P, float3 N,
int child_offsetR = 4*secondChildOffset;
float I_L = calc_node_importance(kg, P, N,
child_offsetL);
float I_R = calc_node_importance(kg, P, N,
child_offsetR);
- if( (I_L==0.0f) && (I_R == 0.0f)){
+ if((I_L == 0.0f) && (I_R == 0.0f)){
*pdf_factor = 0.0f;
break;
}
+
float P_L = I_L / ( I_L + I_R);
/* choose which node to go down */
- if(randu <= P_L){ // Going down left node
+ if(*randu <= P_L){ // Going down left node
/* rescale random number */
- randu = randu / P_L;
+ *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;
+ *randu = (*randu * (I_L + I_R) - I_L)/I_R;
offset = child_offsetR;
*pdf_factor *= 1.0f - P_L;
}
-
- /* update parent node info for next iteration */
- update_parent_node(kg, offset, &secondChildOffset,
- &distribution_id, &num_emitters);
}
-
-
} while(true);
*index = sampled_index;
@@ -1417,7 +1411,7 @@ ccl_device void light_distribution_sample(KernelGlobals
*kg, float3 P, float3 N,
float group_prob = kernel_tex_fetch(__light_group_sample_prob,
group);
if(group == LIGHTGROUP_TREE){
- light_bvh_sample(kg, P, N, *randu, index, pdf);
+ light_bvh_sample(kg, P, N, randu, index, pdf);
} else if(group == LIGHTGROUP_DISTANT) {
light_distant_sample(kg, P, randu, index, pdf);
} else if(group == LIGHTGROUP_BACKGROUND) {
diff --git a/intern/cycles/kernel/kernel_path_surface.h
b/intern/cycles/kernel/kernel_path_surface.h
index 77ca9f7e3d7..8e7697af2ea 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -121,7 +121,8 @@ ccl_device bool split(KernelGlobals *kg, float3 P, int
node_offset)
ccl_device void accum_light_tree_contribution(KernelGlobals *kg, float randu,
float randv, int offset,
float pdf_factor, bool can_split,
- float3 throughput, PathRadiance
*L,
+ float3 throughput, float
scale_factor,
+ PathRadiance *L,
ccl_addr_space PathState * state,
ShaderData *sd, ShaderData
*emission_sd,
int *num_lights,
@@ -139,7 +140,6 @@ ccl_device void accum_light_tree_contribution(KernelGlobals
*kg, float randu,
/* Found a leaf - Choose which light to use */
if(secondChildOffset == -1){ // Found a leaf
-
if(num_emitters == 1){
(*num_lights)++; // used for debugging purposes
// Distribution_id is the index
@@ -150,10 +150,7 @@ ccl_device void
accum_light_tree_contribution(KernelGlobals *kg, float randu,
/* combine pdfs */
ls.pdf *= pdf_factor;
- if(ls.pdf == 0.0f){
- return;
- }
-
+ if(ls.pdf <= 0.0f) return;
Ray light_ray;
BsdfEval L_light;
@@ -161,7 +158,8 @@ ccl_device void accum_light_tree_contribution(KernelGlobals
*kg, float randu,
float terminate = path_state_rng_light_termination(kg,
state);
accum_light_contribution(kg, sd, emission_sd, &ls,
state,
&light_ray, &L_light, L,
&is_lamp,
- terminate, throughput, 1.0f);
+ terminate, throughput,
scale_factor);
+
} // TODO: do else, i.e. with several lights per node
@@ -175,11 +173,15 @@ ccl_device void
accum_light_tree_contribution(KernelGlobals *kg, float randu,
if(can_split && split(kg, P, offset)){
/* go down both child nodes */
accum_light_tree_contribution(kg, randu, randv,
child_offsetL,
- pdf_factor, true,
throughput, L,
- state, sd, emission_sd,
num_lights, num_lights_fail);
+ pdf_factor, true,
throughput,
+ scale_factor, L, state,
sd,
+ emission_sd, num_lights,
+ num_lights_fail);
accum_light_tree_contribution(kg, randu, randv,
child_offsetR,
- pdf_factor, true,
throughput, L,
- state, sd, emission_sd,
num_lights, num_lights_fail);
+ pdf_factor, true,
throughput,
+ scale_factor, L, state,
sd,
+ emission_sd, num_lights,
+ num_lights_fail);
} else {
/* go down one of the child nodes */
@@ -187,13 +189,14 @@ ccl_device void
accum_light_tree_contribution(KernelGlobals *kg, float randu,
float I_L = calc_node_importance(kg, P, N,
child_offsetL);
float I_R = calc_node_importance(kg, P, N,
child_offsetR);
- if( (I_L == 0.0f) && (I_R == 0.0f) ){
+ if((I_L == 0.0f) && (I_R == 0.0f)){
(*num_lights_fail)++; // used for debugging
purposes
return;
}
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;
@@ -209,8 +212,9 @@ ccl_device void accum_light_tree_contribution(KernelGlobals
*kg, float randu,
}
accum_light_tree_contribution(kg, randu, randv, offset,
pdf_factor,
- false, throughput, L,
state, sd,
- emission_sd, num_lights,
num_lights_fail);
+ false, throughput,
scale_factor, L,
+ state, sd, emission_sd,
num_lights,
+ num_lights_fail);
}
}
}
@@ -257,8 +261,9 @@ ccl_device_noinline void
kernel_branched_path_surface_connect_light(
int num_lights = 0;
int num_lights_fail = 0;
accum_light_tree_contribution(kg, randu, randv, 0,
group_prob, true,
- throughput, L, state, sd,
emission_sd,
- &num_lights,
&num_lights_fail);
+ throughput,
num_samples_adjust, L, // todo: is num_samples_adjust correct here?
+ state, sd, emission_sd,
&num_lights,
+ &num_lights_fail);
/*
if(num_lights_fail > 1){ // Debug print
@@ -286,7 +291,7 @@ ccl_device_noinline void
kernel_branched_path_surface_connect_light(
/* combine pdfs */
ls.pdf *= group_prob;
- if(ls.pdf == 0.0f) return;
+ if(ls.pdf <= 0.0f) return;
/* accumulate the contribution of this distant/background light
to L */
float terminate = path_state_rng_light_termination(kg, state);
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs