[Bf-blender-cvs] [84fec215226] gsoc-2018-many-light-sampling: Cycles: Light tree instancing and energy fixes

Erik Englesson noreply at git.blender.org
Fri Aug 3 17:32:01 CEST 2018


Commit: 84fec21522616b93d7b4f7ee7563d9502fb79a32
Author: Erik Englesson
Date:   Sat Jul 28 16:34:44 2018 +0200
Branches: gsoc-2018-many-light-sampling
https://developer.blender.org/rB84fec21522616b93d7b4f7ee7563d9502fb79a32

Cycles: Light tree instancing and energy fixes

Instancing for mesh lights now works with the light tree.
The conversion from emission to luminance is now using
linear_rgb_to_gray() instead.

===================================================================

M	intern/cycles/kernel/kernel_emission.h
M	intern/cycles/kernel/kernel_light.h
M	intern/cycles/render/light.cpp
M	intern/cycles/render/light_tree.cpp
M	intern/cycles/render/light_tree.h
M	intern/cycles/util/util_color.h

===================================================================

diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 9d8e38dc458..a06250a515a 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -212,7 +212,7 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
 		/* multiple importance sampling, get triangle light pdf,
 		 * and compute weight with respect to BSDF pdf */
 		float pdf = triangle_light_pdf(kg, sd, t);
-		pdf *= light_distribution_pdf(kg, P, N, sd->prim, is_volume_boundary);
+		pdf *= light_distribution_pdf(kg, P, N, sd->prim, sd->object, is_volume_boundary);
 		float mis_weight = power_heuristic(bsdf_pdf, pdf);
 
 		return L*mis_weight;
@@ -281,7 +281,7 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg,
 			 * and compute weight with respect to BSDF pdf */
 
 			/* multiply with light picking probablity to pdf */
-			ls.pdf *= light_distribution_pdf(kg, ray->P, N, ~ls.lamp, is_inside_volume);
+			ls.pdf *= light_distribution_pdf(kg, ray->P, N, ~ls.lamp, -1, is_inside_volume);
 			float mis_weight = power_heuristic(state->ray_pdf, ls.pdf);
 			L *= mis_weight;
 		}
@@ -346,7 +346,7 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
 		 * direction, and compute weight with respect to BSDF pdf */
 		float pdf = background_light_pdf(kg, ray->P, ray->D);
 		int background_index = kernel_data.integrator.background_light_index;
-		pdf *= light_distribution_pdf(kg, ray->P, N, ~background_index, is_on_volume_boundary);
+		pdf *= light_distribution_pdf(kg, ray->P, N, ~background_index, -1, is_on_volume_boundary);
 		float mis_weight = power_heuristic(state->ray_pdf, pdf);
 
 		return L*mis_weight;
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 5a2facaa454..976dd68b5ae 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -1300,11 +1300,17 @@ ccl_device void light_bvh_sample(KernelGlobals *kg, float3 P, float3 N,
 
 /* converts from an emissive triangle index to the corresponding
  * light distribution index. */
-ccl_device int triangle_to_distribution(KernelGlobals *kg, int triangle_id)
+ccl_device int triangle_to_distribution(KernelGlobals *kg, int triangle_id,
+                                        int object_id)
 {
 	/* binary search to find triangle_id which then gives distribution_id */
 	/* equivalent to implementation of std::lower_bound */
 	/* todo: of complexity log(N) now. could be made constant with a hash table? */
+	/* __triangle_to_distribution is an array of uints of the format below:
+	 * [triangle_id0, object_id0, distribution_id0, triangle_id1,... ]
+	 * where e.g. [triangle_id0,object_id0] corresponds to distribution id
+	 * distribution_id0
+	 */
 	int first = 0;
 	int last = kernel_data.integrator.num_triangle_lights;
 	int count = last - first;
@@ -1312,7 +1318,7 @@ ccl_device int triangle_to_distribution(KernelGlobals *kg, int triangle_id)
 	while (count > 0) {
 		step = count / 2;
 		middle = first + step;
-		int triangle = kernel_tex_fetch(__triangle_to_distribution, middle*2);
+		int triangle = kernel_tex_fetch(__triangle_to_distribution, middle*3);
 		if (triangle < triangle_id) {
 			first = middle + 1;
 			count -= step + 1;
@@ -1321,9 +1327,18 @@ ccl_device int triangle_to_distribution(KernelGlobals *kg, int triangle_id)
 			count = step;
 	}
 
+	/* If instancing then we can have several triangles with the same triangle_id
+	 * so loop over object_id too. */
+	/* todo: do a binary search here too if many instances */
+	while(true){
+		int object = kernel_tex_fetch(__triangle_to_distribution, first*3+1);
+		if(object == object_id) break;
+		++first;
+	}
+
 	kernel_assert(kernel_tex_fetch(__triangle_to_distribution, first*2) == triangle_id);
 
-	return kernel_tex_fetch(__triangle_to_distribution, first*2+1);
+	return kernel_tex_fetch(__triangle_to_distribution, first*3+2);
 }
 
 /* computes the probability of picking a light in the given node_id */
@@ -1399,12 +1414,13 @@ ccl_device float light_bvh_pdf(KernelGlobals *kg, float3 P, float3 N,
 
 /* computes the the probability of picking the given light out of all lights */
 ccl_device float light_distribution_pdf(KernelGlobals *kg, float3 P, float3 N,
-                                        int prim_id, bool is_inside_volume)
+                                        int prim_id, int object_id,
+                                        bool is_inside_volume)
 {
 	/* convert from triangle/lamp to light distribution */
 	int distribution_id;
 	if(prim_id >= 0){ // Triangle_id = prim_id
-		distribution_id = triangle_to_distribution(kg, prim_id);
+		distribution_id = triangle_to_distribution(kg, prim_id, object_id);
 	} else { // Lamp
 		int lamp_id = -prim_id-1;
 		distribution_id = kernel_tex_fetch(__lamp_to_distribution, lamp_id);
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 69c0dbcd15e..0384a30759a 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -263,7 +263,7 @@ float LightManager::distant_lights_energy(const Scene *scene,
 		bool is_constant_emission = lamp->shader->is_constant_emission(&emission);
 		if(!is_constant_emission) continue; // TODO: Properly handle this case
 
-		luminance += rgb_to_luminance(emission);
+		luminance += scene->shader_manager->linear_rgb_to_gray(emission);
 	}
 
 
@@ -304,7 +304,7 @@ float LightManager::background_light_energy(Device *device,
 		shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
 		num_pixels += pixels.size();
 		for(int i = 0; i < pixels.size(); ++i){
-			average_luminance += rgb_to_luminance(pixels[i]);
+			average_luminance += scene->shader_manager->linear_rgb_to_gray(pixels[i]);
 		}
 
 		break;
@@ -404,7 +404,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 
 		/* create light BVH */
 		double time_start = time_dt();
-		LightTree lightBVH(emissivePrims, scene->objects, scene->lights, 64);
+		LightTree lightBVH(emissivePrims, scene->objects, scene->lights, scene, 64);
 		VLOG(1) << "Light BVH build time: " << time_dt() - time_start;
 
 		/* the light BVH reorders the primitives so update emissivePrims */
@@ -570,22 +570,23 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 	}
 
 	/* find mapping between triangle_id to distribution_id, used for MIS */
-	vector< std::pair<uint,uint> > tri_to_distr;
+	vector< std::tuple<uint,uint, uint> > tri_to_distr;
 	tri_to_distr.reserve(num_triangles);
 	for(int i = 0; i < emissivePrims.size(); ++i){
 		const Primitive& prim = emissivePrims[i];
 		if(prim.prim_id < 0) continue; // Skip lamps
-		tri_to_distr.push_back(std::make_pair( prim.prim_id, i ));
+		tri_to_distr.push_back(std::make_tuple(prim.prim_id, prim.object_id, i));
 	}
 
 	std::sort(tri_to_distr.begin(), tri_to_distr.end());
 
 	assert(num_triangles == tri_to_distr.size());
 	uint *triangle_to_distribution =
-	        dscene->triangle_to_distribution.alloc(num_triangles*2);
+	        dscene->triangle_to_distribution.alloc(num_triangles*3);
 	for(int i = 0; i < tri_to_distr.size(); ++i){
-		triangle_to_distribution[2*i  ] = tri_to_distr[i].first;
-		triangle_to_distribution[2*i+1] = tri_to_distr[i].second;
+		triangle_to_distribution[3*i  ] = std::get<0>(tri_to_distr[i]);
+		triangle_to_distribution[3*i+1] = std::get<1>(tri_to_distr[i]);
+		triangle_to_distribution[3*i+2] = std::get<2>(tri_to_distr[i]);
 	}
 
 	/* create light distribution in same order as the emissivePrims */
diff --git a/intern/cycles/render/light_tree.cpp b/intern/cycles/render/light_tree.cpp
index ad53b84f360..21bbc543044 100644
--- a/intern/cycles/render/light_tree.cpp
+++ b/intern/cycles/render/light_tree.cpp
@@ -31,8 +31,10 @@ CCL_NAMESPACE_BEGIN
 LightTree::LightTree(const vector<Primitive>& prims_,
                      const vector<Object*>& objects_,
                      const vector<Light*>& lights_,
+                     Scene* scene_,
                      const unsigned int maxPrimsInNode_)
-    :  objects(objects_), lights(lights_), maxPrimsInNode(maxPrimsInNode_)
+    :  objects(objects_), lights(lights_), maxPrimsInNode(maxPrimsInNode_),
+      scene(scene_)
 {
 
 	if (prims_.empty()) return;
@@ -66,6 +68,7 @@ LightTree::LightTree(const vector<Primitive>& prims_,
 		BoundBox bbox     = get_bbox(primitives[i]);
 		Orientation bcone = get_bcone(primitives[i]);
 		float energy      = get_energy(primitives[i]);
+
 		buildData.push_back(BVHPrimitiveInfo(i, bbox, bcone, energy));
 	}
 
@@ -143,8 +146,21 @@ BoundBox LightTree::get_bbox(const Primitive& prim)
 		const Mesh* mesh = object->mesh;
 		const int triangle_id = prim.prim_id - mesh->tri_offset;
 		const Mesh::Triangle triangle = mesh->get_triangle(triangle_id);
-		const float3 *vpos = &mesh->verts[0];
-		triangle.bounds_grow(vpos, bbox);
+
+		float3 p0 = mesh->verts[triangle.v[0]];
+		float3 p1 = mesh->verts[triangle.v[1]];
+		float3 p2 = mesh->verts[triangle.v[2]];
+
+		if(!mesh->transform_applied) {
+			const Transform& tfm = object->tfm;
+			p0 = transform_point(&tfm, p0);
+			p1 = transform_point(&tfm, p1);
+			p2 = transform_point(&tfm, p2);
+		}
+
+		bbox.grow(p0);
+		bbox.grow(p1);
+		bbox.grow(p2);
 	} else {
 		/* extract bounding box from lamp based on light type */
 		Light* lamp = lights[prim.lamp_id];
@@ -183,8 +199,26 @@ Orientation LightTree::get_bcone(const Primitive& prim){
 		const Mesh* mesh = object->mesh;
 		const int triangle_id = prim.prim_id - mesh->tri_offset;
 		const Mesh::Triangle triangle = mesh->get_triangle(triangle_id);
-		const float3 *vpos = &mesh->verts[0];
-		bcone.axis = triangle.compute_normal(vpos);
+
+		float3 p0 = mesh->verts[triangle.v[0]];
+		float3 p1 = mesh->verts[triangle.v[1]];
+		float3 p2 = mesh->verts[triangle.v[2]];
+
+		if(!mesh->transform_applied) {
+			const Transform& tfm = object->tfm;
+			p0 = transform_point(&tfm, p0);
+			p1 = transform_point(&tfm, p1);
+			p2 = transform_point(&tfm, p2);
+		}
+
+		float3 normal = make_float3(1.0f, 0.0f, 0.0f);
+		const float3 norm = cross(p1 - p0, p2 - p0);
+		const float normlen = len(norm);
+		if(normlen != 0.0f) {
+			normal = norm / norm

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list