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

Reply via email to