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 Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs