[Bf-blender-cvs] [ff4833a6b39] gsoc-2018-many-light-sampling: Cycles: Bug fixes

Erik Englesson noreply at git.blender.org
Fri Jul 13 13:57:52 CEST 2018


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);



More information about the Bf-blender-cvs mailing list