Commit: 8b24cf8c83a124dbc367897db13799c36ff645f3 Author: Erik Englesson Date: Thu Jun 21 09:05:41 2018 +0200 Branches: gsoc-2018-many-light-sampling https://developer.blender.org/rB8b24cf8c83a124dbc367897db13799c36ff645f3
Cycles: Support for distant lights Distant lights are not put in the light BVH and are treated as a special case. Either we sample a light from the BVH or choose one of the distant lights. =================================================================== M intern/cycles/kernel/kernel_light.h M intern/cycles/kernel/kernel_types.h M intern/cycles/render/light.cpp M intern/cycles/render/light_tree.cpp =================================================================== diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 392690b6823..7623c6a7e3b 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -1093,11 +1093,30 @@ ccl_device void update_parent_node(KernelGlobals *kg, int node_offset, (*nemitters) = __float_as_int(node[3]); } +/* picks one of the distant lights and computes the probability of picking it */ +ccl_device void light_distant_sample(KernelGlobals *kg, float3 P, float *randu, + int *index, float *pdf){ + light_distribution_sample(kg, randu); // rescale random number + + /* choose one of the distant lights randomly */ + int num_distant = kernel_data.integrator.num_distant_lights; + int light = min((int)(*randu * (float)num_distant), num_distant-1); + + /* this assumes the distant lights are at the end of the distribution array */ + // TODO: have a distant lights offset into distribution array instead + int num_total_lights = kernel_data.integrator.num_distribution; + int distant_lights_offset = num_total_lights-num_distant; + + *index = light + distant_lights_offset; + *pdf = kernel_data.integrator.inv_num_distant_lights; +} + /* picks a light from the light BVH and returns its index and the probability of * picking this light. */ -ccl_device int light_bvh_sample(KernelGlobals *kg, float3 P, float randu, float *pdf_factor) +ccl_device void light_bvh_sample(KernelGlobals *kg, float3 P, float randu, + int *index, float *pdf_factor) { - int index = -1; + int sampled_index = -1; *pdf_factor = 1.0f; /* read in first part of root node of light BVH */ @@ -1110,11 +1129,11 @@ ccl_device int light_bvh_sample(KernelGlobals *kg, float3 P, float randu, float /* Found a leaf - Choose which light to use */ if(nemitters > 0){ // Found a leaf if(nemitters == 1){ - index = distribution_id; + sampled_index = distribution_id; } else { // Leaf with several lights. Pick one randomly. light_distribution_sample(kg, &randu); // TODO: Rescale random number in a better way int light = min((int)(randu* (float)nemitters), nemitters-1); - index = distribution_id +light; + sampled_index = distribution_id +light; *pdf_factor *= 1.0f / (float)nemitters; } break; @@ -1145,7 +1164,7 @@ ccl_device int light_bvh_sample(KernelGlobals *kg, float3 P, float randu, float } while(true); - return index; + *index = sampled_index; } /* converts from an emissive triangle index to the corresponding @@ -1235,14 +1254,20 @@ ccl_device float light_distribution_pdf(KernelGlobals *kg, float3 P, int prim_id } kernel_assert((distribution_id >= 0) && - (distribution_id < kernel_data.integrator.num_distribution)); + (distribution_id < kernel_data.integrator.num_distribution)); /* compute picking pdf for this light */ if (kernel_data.integrator.use_light_bvh){ // Find mapping from distribution_id to node_id int node_id = kernel_tex_fetch(__light_distribution_to_node, distribution_id); - return light_bvh_pdf(kg, P, node_id); + if(node_id==-1){ // Distant lights are not in any nodes + return (1.0f - kernel_data.integrator.bvh_sample_probability) * + kernel_data.integrator.inv_num_distant_lights; + } else { + return kernel_data.integrator.bvh_sample_probability * + light_bvh_pdf(kg, P, node_id); + } } else { const ccl_global KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution, distribution_id); @@ -1255,8 +1280,17 @@ ccl_device void light_distribution_sample(KernelGlobals *kg, float3 P, float *randu, int *index, float *pdf) { if (kernel_data.integrator.use_light_bvh){ - *index = light_bvh_sample(kg, P, *randu, pdf); - } else { + /* sample light BVH or distant lights */ + float bvh_sample_prob = kernel_data.integrator.bvh_sample_probability; + if(*randu <= bvh_sample_prob) { // Sample light BVH + light_bvh_sample(kg, P, *randu, index, pdf); + *pdf *= bvh_sample_prob; + } else { // Sample distant lights + light_distant_sample(kg, P, randu, index, pdf); + *pdf *= (1.0f - bvh_sample_prob); + } + + } else { // Sample light distribution CDF *index = light_distribution_sample(kg, randu); const ccl_global KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution, *index); @@ -1264,7 +1298,6 @@ ccl_device void light_distribution_sample(KernelGlobals *kg, float3 P, } } - /* picks a point on a light and computes the probability of picking this point*/ ccl_device_noinline bool light_sample(KernelGlobals *kg, float randu, diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 1ea51de6524..01835d20d54 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1307,6 +1307,9 @@ typedef struct KernelIntegrator { int num_all_lights; int num_light_nodes; int num_triangle_lights; + int num_distant_lights; + float inv_num_distant_lights; + float bvh_sample_probability; float pdf_triangles; float pdf_lights; float pdf_inv_totarea; @@ -1372,6 +1375,7 @@ typedef struct KernelIntegrator { int start_sample; int max_closures; + int pad; } KernelIntegrator; static_assert_align(KernelIntegrator, 16); diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 20587be4f75..da1b10e9ad3 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -256,6 +256,7 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce size_t num_lights = 0; size_t num_portals = 0; size_t num_background_lights = 0; + size_t num_distant_lights = 0; size_t num_triangles = 0; bool background_mis = false; @@ -367,6 +368,11 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce /* find mapping between distribution_id to node_id, used for MIS */ uint * distribution_to_node = dscene->light_distribution_to_node.alloc(num_distribution); + /* initialize indices to -1 to know which lights that are not in nodes */ + for(int i = 0; i < num_distribution; ++i){ + distribution_to_node[i] = -1; + } + for( int i = 0; i < nodesVec.size(); ++i){ const CompactNode& node = nodesVec[i]; if(node.nemitters == 0) continue; @@ -495,6 +501,8 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce if(light->type == LIGHT_BACKGROUND) { num_background_lights++; background_mis = light->use_mis; + } else if(light->type == LIGHT_DISTANT){ + num_distant_lights++; } } @@ -519,10 +527,6 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce kintegrator->use_light_bvh = scene->integrator->use_light_bvh; KernelFilm *kfilm = &dscene->data.film; kintegrator->use_direct_light = (totarea > 0.0f); - kintegrator->pdf_inv_totarea = 1.0f / totarea; - kintegrator->num_light_nodes = - dscene->light_tree_nodes.size() / LIGHT_BVH_NODE_SIZE; - kintegrator->num_triangle_lights = num_triangles; if(kintegrator->use_direct_light) { @@ -531,13 +535,22 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce dscene->light_distribution_to_node.copy_to_device(); dscene->lamp_to_distribution.copy_to_device(); dscene->triangle_to_distribution.copy_to_device(); + kintegrator->num_light_nodes = + dscene->light_tree_nodes.size() / LIGHT_BVH_NODE_SIZE; + kintegrator->bvh_sample_probability = + 1.0f - 0.5f * (float)num_distant_lights / (float)num_lights; /* number of emissives */ kintegrator->num_distribution = num_distribution; + kintegrator->num_triangle_lights = num_triangles; + kintegrator->num_distant_lights = num_distant_lights; + kintegrator->inv_num_distant_lights = 1.0f / (float)num_distant_lights; /* precompute pdfs */ kintegrator->pdf_triangles = 0.0f; kintegrator->pdf_lights = 0.0f; + kintegrator->pdf_inv_totarea = 1.0f / totarea; + /* sample one, with 0.5 probability of light or triangle */ kintegrator->num_all_lights = num_lights; @@ -594,6 +607,9 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce kintegrator->use_light_bvh = false; kintegrator->num_distribution = 0; kintegrator->num_all_lights = 0; + kintegrator->num_distant_lights = 0; + kintegrator->inv_num_distant_lights = 0.0f; + kintegrator->bvh_sample_probability = 0.0f; kintegrator->pdf_triangles = 0.0f; kintegrator->pdf_lights = 0.0f; kintegrator->use_lamp_mis = false; diff --git a/intern/cycles/render/light_tree.cpp b/intern/cycles/render/light_tree.cpp index e0578b65ba8..916a0d67403 100644 --- a/intern/cycles/render/light_tree.cpp +++ b/intern/cycles/render/light_tree.cpp @@ -37,13 +37,25 @@ LightTree::LightTree(const vector<Primitive>& prims_, if (prims_.empty()) return; - // Move all primitives into local primitives array + /* move all primitives except distant lights into local primitives array */ primitives.reserve(prims_.size()); + vector<Primitive> distant_lights; foreach(Primitive prim, prims_ ){ + + /* put distant lights into its own array */ + if (prim.prim_id < 0){ + int lamp_id = -prim.prim_id-1; + const Light *lamp = lights[lamp_id]; + if (lamp->type == LIGHT_DISTANT){ + distant_lights.push_back(prim); + continue; + } + } + primitives.push_back(prim); } - // Initialize buildData array + /* initialize buildData array */ vector<BVHPrimitiveInfo> buildData; buildData.reserve(primitives.size()); for(int i = 0; i < primitives.size(); ++i){ @@ -53,7 +65,7 @@ LightTree::LightTree(const vector<Primitive>& prims_, buildData.push_back(BVHPrimitiveInfo(i, bbox, bcone, energy)); } - // Recursively build BVH tree + /* recursively build BVH tree */ unsigned int totalNodes = 0; vector<Primitive> orderedPrims; orderedPrims.reserve(primitives.size()); @@ -65,9 +77,14 @@ LightTree::LightTree(const vector<Primitive>& prims_, orderedPrims.clear(); buildData.cle @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs