[Bf-blender-cvs] [6f2d885f7ed] gsoc-2018-many-light-sampling: Cleanup: Refactored code

Erik Englesson noreply at git.blender.org
Fri Jun 15 12:35:46 CEST 2018


Commit: 6f2d885f7edb360e21116b4d4c6496fe3f7b131e
Author: Erik Englesson
Date:   Thu Jun 14 15:24:32 2018 +0200
Branches: gsoc-2018-many-light-sampling
https://developer.blender.org/rB6f2d885f7edb360e21116b4d4c6496fe3f7b131e

Cleanup: Refactored code

Merged the device_update_tree_distribution()
and device_update_distribution() functions.

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

M	intern/cycles/render/light.cpp
M	intern/cycles/render/light.h

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

diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index d590472f92f..3ae25b7bb59 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -250,239 +250,7 @@ bool LightManager::object_usable_as_light(Object *object) {
 
 void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Scene *scene, Progress& progress)
 {
-	progress.set_status("Updating Lights", "Computing distribution");
-
-	/* count */
-	size_t num_lights = 0;
-	size_t num_portals = 0;
-	size_t num_background_lights = 0;
-	size_t num_triangles = 0;
-
-	bool background_mis = false;
-
-	foreach(Light *light, scene->lights) {
-		if(light->is_enabled) {
-			num_lights++;
-		}
-		if(light->is_portal) {
-			num_portals++;
-		}
-	}
-
-	foreach(Object *object, scene->objects) {
-		if(progress.get_cancel()) return;
-
-		if(!object_usable_as_light(object)) {
-			continue;
-		}
-		/* Count triangles. */
-		Mesh *mesh = object->mesh;
-		size_t mesh_num_triangles = mesh->num_triangles();
-		for(size_t i = 0; i < mesh_num_triangles; i++) {
-			int shader_index = mesh->shader[i];
-			Shader *shader = (shader_index < mesh->used_shaders.size())
-			                         ? mesh->used_shaders[shader_index]
-			                         : scene->default_surface;
-
-			if(shader->use_mis && shader->has_surface_emission) {
-				num_triangles++;
-			}
-		}
-	}
-
-	size_t num_distribution = num_triangles + num_lights;
-	VLOG(1) << "Total " << num_distribution << " of light distribution primitives.";
-
-	/* emission area */
-	KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
-	float totarea = 0.0f;
-
-	/* triangles */
-	size_t offset = 0;
-	int j = 0;
-
-	foreach(Object *object, scene->objects) {
-		if(progress.get_cancel()) return;
-
-		if(!object_usable_as_light(object)) {
-			j++;
-			continue;
-		}
-		/* Sum area. */
-		Mesh *mesh = object->mesh;
-		bool transform_applied = mesh->transform_applied;
-		Transform tfm = object->tfm;
-		int object_id = j;
-		int shader_flag = 0;
-
-		if(!(object->visibility & PATH_RAY_DIFFUSE)) {
-			shader_flag |= SHADER_EXCLUDE_DIFFUSE;
-			use_light_visibility = true;
-		}
-		if(!(object->visibility & PATH_RAY_GLOSSY)) {
-			shader_flag |= SHADER_EXCLUDE_GLOSSY;
-			use_light_visibility = true;
-		}
-		if(!(object->visibility & PATH_RAY_TRANSMIT)) {
-			shader_flag |= SHADER_EXCLUDE_TRANSMIT;
-			use_light_visibility = true;
-		}
-		if(!(object->visibility & PATH_RAY_VOLUME_SCATTER)) {
-			shader_flag |= SHADER_EXCLUDE_SCATTER;
-			use_light_visibility = true;
-		}
-
-		size_t mesh_num_triangles = mesh->num_triangles();
-		for(size_t i = 0; i < mesh_num_triangles; i++) {
-			int shader_index = mesh->shader[i];
-			Shader *shader = (shader_index < mesh->used_shaders.size())
-			                         ? mesh->used_shaders[shader_index]
-			                         : scene->default_surface;
-
-			if(shader->use_mis && shader->has_surface_emission) {
-				distribution[offset].totarea = totarea;
-				distribution[offset].prim = i + mesh->tri_offset;
-				distribution[offset].mesh_light.shader_flag = shader_flag;
-				distribution[offset].mesh_light.object_id = object_id;
-				offset++;
-
-				Mesh::Triangle t = mesh->get_triangle(i);
-				if(!t.valid(&mesh->verts[0])) {
-					continue;
-				}
-				float3 p1 = mesh->verts[t.v[0]];
-				float3 p2 = mesh->verts[t.v[1]];
-				float3 p3 = mesh->verts[t.v[2]];
-
-				if(!transform_applied) {
-					p1 = transform_point(&tfm, p1);
-					p2 = transform_point(&tfm, p2);
-					p3 = transform_point(&tfm, p3);
-				}
-
-				totarea += triangle_area(p1, p2, p3);
-			}
-		}
-
-		j++;
-	}
-
-	float trianglearea = totarea;
-
-	/* point lights */
-	float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
-	bool use_lamp_mis = false;
-
-	int light_index = 0;
-	foreach(Light *light, scene->lights) {
-		if(!light->is_enabled)
-			continue;
-		distribution[offset].totarea = totarea;
-		distribution[offset].prim = ~light_index;
-		distribution[offset].lamp.pad = 1.0f;
-		distribution[offset].lamp.size = light->size;
-		totarea += lightarea;
-
-		if(light->size > 0.0f && light->use_mis)
-			use_lamp_mis = true;
-		if(light->type == LIGHT_BACKGROUND) {
-			num_background_lights++;
-			background_mis = light->use_mis;
-		}
-
-		light_index++;
-		offset++;
-	}
-
-	/* normalize cumulative distribution functions */
-	distribution[num_distribution].totarea = totarea;
-	distribution[num_distribution].prim = 0.0f;
-	distribution[num_distribution].lamp.pad = 0.0f;
-	distribution[num_distribution].lamp.size = 0.0f;
-
-	if(totarea > 0.0f) {
-		for(size_t i = 0; i < num_distribution; i++)
-			distribution[i].totarea /= totarea;
-		distribution[num_distribution].totarea = 1.0f;
-	}
-
-	if(progress.get_cancel()) return;
-
-	/* update device */
-	KernelIntegrator *kintegrator = &dscene->data.integrator;
-	KernelFilm *kfilm = &dscene->data.film;
-	kintegrator->use_direct_light = (totarea > 0.0f);
-
-	if(kintegrator->use_direct_light) {
-		/* number of emissives */
-		kintegrator->num_distribution = num_distribution;
-
-		/* precompute pdfs */
-		kintegrator->pdf_triangles = 0.0f;
-		kintegrator->pdf_lights = 0.0f;
-
-		/* sample one, with 0.5 probability of light or triangle */
-		kintegrator->num_all_lights = num_lights;
-
-		if(trianglearea > 0.0f) {
-			kintegrator->pdf_triangles = 1.0f/trianglearea;
-			if(num_lights)
-				kintegrator->pdf_triangles *= 0.5f;
-		}
-
-		if(num_lights) {
-			kintegrator->pdf_lights = 1.0f/num_lights;
-			if(trianglearea > 0.0f)
-				kintegrator->pdf_lights *= 0.5f;
-		}
-
-		kintegrator->use_lamp_mis = use_lamp_mis;
-
-		/* bit of an ugly hack to compensate for emitting triangles influencing
-		 * amount of samples we get for this pass */
-		kfilm->pass_shadow_scale = 1.0f;
-
-		if(kintegrator->pdf_triangles != 0.0f)
-			kfilm->pass_shadow_scale *= 0.5f;
-
-		if(num_background_lights < num_lights)
-			kfilm->pass_shadow_scale *= (float)(num_lights - num_background_lights)/(float)num_lights;
-
-		/* CDF */
-		dscene->light_distribution.copy_to_device();
-
-		/* Portals */
-		if(num_portals > 0) {
-			kintegrator->portal_offset = light_index;
-			kintegrator->num_portals = num_portals;
-			kintegrator->portal_pdf = background_mis? 0.5f: 1.0f;
-		}
-		else {
-			kintegrator->num_portals = 0;
-			kintegrator->portal_offset = 0;
-			kintegrator->portal_pdf = 0.0f;
-		}
-	}
-	else {
-		dscene->light_distribution.free();
-
-		kintegrator->num_distribution = 0;
-		kintegrator->num_all_lights = 0;
-		kintegrator->pdf_triangles = 0.0f;
-		kintegrator->pdf_lights = 0.0f;
-		kintegrator->use_lamp_mis = false;
-		kintegrator->num_portals = 0;
-		kintegrator->portal_offset = 0;
-		kintegrator->portal_pdf = 0.0f;
-
-		kfilm->pass_shadow_scale = 1.0f;
-	}
-}
-
-/* TODO: Refactor the code here with the code in device_update_distribution */
-void LightManager::device_update_tree_distribution(Device *, DeviceScene *dscene, Scene *scene, Progress& progress)
-{
-    progress.set_status("Updating Lights", "Computing tree distribution");
+    progress.set_status("Updating Lights", "Computing distribution");
 
     /* count */
     size_t num_lights = 0;
@@ -492,14 +260,26 @@ void LightManager::device_update_tree_distribution(Device *, DeviceScene *dscene
 
     bool background_mis = false;
 
-    /* primitives array used for light BVH */
-    vector<Primitive> emissivePrims; // Cannot reserve here..?
+    /* The emissivePrims vector contains all emissive primitives in the scene,
+    * i.e., all mesh light triangles and all lamps. The order of the primitives
+    * in the vector is important since it has the same order as the
+    * light_distribution array.
+    *
+    * If using the light BVH then the order is important since the light BVH
+    * reordered the lights so lights in the same node are next to each other
+    * in memory.
+    *
+    * If NOT using the light BVH then the order is important since during
+    * sampling we assume all triangles are first in the array.
+    */
+    vector<Primitive> emissivePrims;
+    emissivePrims.reserve(scene->lights.size());
 
     int light_index = 0;
     foreach(Light *light, scene->lights) {
         if(light->is_enabled) {
-            num_lights++;
             emissivePrims.push_back(Primitive(~light_index,-1));
+            num_lights++;
             light_index++;
         }
         if(light->is_portal) {
@@ -536,62 +316,69 @@ void LightManager::device_update_tree_distribution(Device *, DeviceScene *dscene
     size_t num_distribution = num_triangles + num_lights;
     VLOG(1) << "Total " << num_distribution << " of light distribution primitives.";
 
-    /* create light BVH */
-    double time_start = time_dt();
-    LightTree lightBVH(emissivePrims, scene->objects, scene->lights, 1);
-    VLOG(1) << "Light BVH build time: " << time_dt() - time_start;
-    emissivePrims.clear();
-    if(progress.get_cancel()) return;
+    if (scene->integrator->use_light_bvh) {
 
-    /* create nodes */
-    const vector<CompactNode>& nodesVec = lightBVH.getNodes();
-    float4 *nodes = dscene->light_tree_nodes.alloc(nodesVec.size()*LIGHT_BVH_NODE_SIZE);
+        /* create light BVH */
+        double time_start = time_dt();
+        LightTree lightBVH(emissivePrims, scene->objects, scene->lights, 1);
+        VLOG(1) << "Light BVH build time: " << time_dt() - time_start;
+
+        /* the light BVH reorders the primitives so update emissivePrims */
+        const vector<Primitive>& orderedPrims = lightBVH.getPrimitives();
+        emissivePrims = orderedPrims;
+
+        if(progress.get_cancel()) return;
+
+        /* create nodes */
+        const vector<CompactNode>& nodesVec = lightBVH.getNodes();
+        float4 *nodes = dscene->light_tree_nodes.alloc(nodesVec.size()*LIGHT_BVH_NODE_SIZE);
+
+        /* convert each compact node into 4xfloat4
+         * 4 for energy, secondChildoffset, prim_id, nemitters
+         * 4 for bbox.min + bbox.max[0]
+         * 4 for bbox.max[1-2], theta_o, theta_e
+         * 4 for axis + 1 pad
+         */
+        size_t offset = 0;
+        foreach (CompactNode node, nodesVec){
+            nodes[offset].x = node.energy;
+            nodes[offset

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list