[Bf-blender-cvs] [8b24cf8c83a] gsoc-2018-many-light-sampling: Cycles: Support for distant lights
Erik Englesson
noreply at git.blender.org
Fri Jun 22 08:54:58 CEST 2018
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. @@
More information about the Bf-blender-cvs
mailing list