[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