[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