[Bf-blender-cvs] [3642fba679c] soc-2022-many-lights-sampling: Fix: Cycles light tree triangle sampling

Jeffrey Liu noreply at git.blender.org
Fri Jul 1 17:06:03 CEST 2022


Commit: 3642fba679c1300d21524a2d645c88a622d42eab
Author: Jeffrey Liu
Date:   Fri Jul 1 11:01:02 2022 -0400
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB3642fba679c1300d21524a2d645c88a622d42eab

Fix: Cycles light tree triangle sampling

This currently reverts some of the distant light sampling changes,
so that I could isolate the issues with triangle light sampling.

The fix ensures that the light distribution still computes the correct
cdf (if needed), and removes the light tree kernel's dependency on the
light distribution. This also corrects the triangle PDFs.

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

M	intern/cycles/kernel/light/light_tree.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/light.cpp
M	intern/cycles/scene/light_tree.cpp

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

diff --git a/intern/cycles/kernel/light/light_tree.h b/intern/cycles/kernel/light/light_tree.h
index 679dcda39f9..9cf601407b7 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -185,16 +185,16 @@ ccl_device int light_tree_sample(KernelGlobals kg,
     emitter_cdf += emitter_pdf;
     if (tree_u < emitter_cdf) {
       *pdf_factor *= emitter_pdf;
-      ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(
-          light_distribution, prim_index);
+      ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(
+          light_tree_emitters, prim_index);
 
       /* to-do: this is the same code as light_distribution_sample, except the index is determined
        * differently. Would it be better to refactor this into a separate function? */
-      const int prim = kdistribution->prim;
+      const int prim = kemitter->prim_id;
 
       if (prim >= 0) {
         /* Mesh light. */
-        const int object = kdistribution->mesh_light.object_id;
+        const int object = kemitter->mesh_light.object_id;
 
         /* Exclude synthetic meshes from shadow catcher pass. */
         if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
@@ -202,9 +202,32 @@ ccl_device int light_tree_sample(KernelGlobals kg,
           return false;
         }
 
-        const int shader_flag = kdistribution->mesh_light.shader_flag;
+        const int shader_flag = kemitter->mesh_light.shader_flag;
         triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P);
         ls->shader |= shader_flag;
+
+        /* triangle_light sample also multiplies the pdf by the triangle's area
+         * because of the precomputed light distribution PDF.
+         * We need to reverse this because it's not needed here.*/
+        float area = 0.0f;
+
+        float3 V[3];
+        bool has_motion = triangle_world_space_vertices(kg, object, prim, time, V);
+
+        const float3 e0 = V[1] - V[0];
+        const float3 e1 = V[2] - V[0];
+        const float3 e2 = V[2] - V[1];
+
+        const float3 N0 = cross(e0, e1);
+        if (has_motion) {
+          /* get the center frame vertices, this is what the PDF was calculated from */
+          triangle_world_space_vertices(kg, object, prim, -1.0f, V);
+          area = triangle_area(V[0], V[1], V[2]);
+        }
+        else {
+          area = 0.5f * len(N0);
+        }
+        ls->pdf /= area;
         return (ls->pdf > 0.0f);
       }
 
@@ -225,6 +248,8 @@ ccl_device int light_tree_sample(KernelGlobals kg,
 
 /* to-do: assign relative importances for the background and distant lights.
  * Can we somehow adjust the importance measure to account for these as well? */
+
+/*
 ccl_device float light_tree_distant_light_importance(KernelGlobals kg,
                                                      const float3 P,
                                                      const float3 N,
@@ -276,6 +301,7 @@ ccl_device int light_tree_sample_distant_lights(KernelGlobals kg,
     }
   }
 }
+*/
 
 ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
                                                 ccl_private const RNGState *rng_state,
@@ -288,10 +314,15 @@ ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
                                                 const uint32_t path_flag,
                                                 ccl_private LightSample *ls)
 {
+  /*
   const int num_distant_lights = kernel_data.integrator.num_distant_lights;
   const int num_light_tree_prims = kernel_data.integrator.num_distribution - num_distant_lights;
+  */
 
   float pdf_factor = 1.0f;
+  bool ret = light_tree_sample<false>(
+        kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
+  /*
   bool ret = false;
   if (num_distant_lights == 0) {
     ret = light_tree_sample<false>(
@@ -321,6 +352,7 @@ ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
       pdf_factor *= (1 - light_tree_probability);
     }
   }
+  */
 
   ls->pdf *= pdf_factor;
   return ret;
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 09939ca074c..1fe450c3dec 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -1542,9 +1542,19 @@ typedef struct KernelLightTreeEmitter {
 
   /* prim_id denotes the location in the lights or triangles array. */
   int prim_id;
+  union {
+    struct {
+      int shader_flag;
+      int object_id;
+    } mesh_light;
+    struct {
+      float pad;
+      float size;
+    } lamp;
+  };
 
   /* Padding. */
-  int pad1, pad2, pad3;
+  int pad1;
 } KernelLightTreeEmitter;
 static_assert_align(KernelLightTreeEmitter, 16);
 
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index 298477e2d6d..c7f252d13f9 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -320,20 +320,23 @@ void LightManager::device_update_distribution(Device *device,
   int scene_light_index = 0;
   foreach (Light *light, scene->lights) {
     if (light->is_enabled) {
-      LightTreePrimitive light_prim;
-      light_prim.prim_id = ~device_light_index; /* -prim_id - 1 is a light source index. */
-      light_prim.lamp_id = scene_light_index;
-
-      /* Distant lights get added to a separate vector. */
-      if (light->light_type == LIGHT_DISTANT || light->light_type == LIGHT_BACKGROUND) {
-        distant_lights.push_back(light_prim);
-        num_distant_lights++;
-      }
-      else {
-        light_prims.push_back(light_prim);
+      if (light_tree_enabled) {
+        LightTreePrimitive light_prim;
+        light_prim.prim_id = ~device_light_index; /* -prim_id - 1 is a light source index. */
+        light_prim.lamp_id = scene_light_index;
+
+        /* Distant lights get added to a separate vector. */
+        if (light->light_type == LIGHT_DISTANT || light->light_type == LIGHT_BACKGROUND) {
+          distant_lights.push_back(light_prim);
+          num_distant_lights++;
+        }
+        else {
+          light_prims.push_back(light_prim);
+        }
+
+        device_light_index++;
       }
 
-      device_light_index++;
       num_lights++;
     }
     if (light->is_portal) {
@@ -344,17 +347,13 @@ void LightManager::device_update_distribution(Device *device,
   }
 
   /* Similarly, we also want to keep track of the index of triangles that are emissive. */
-  int device_triangle_index = 0;
+  int object_id = 0;
   foreach (Object *object, scene->objects) {
     if (progress.get_cancel())
       return;
 
-    /* Don't add any emissive triangles to the distribution if light tree is enabled. */
-    if (light_tree_enabled) {
-      continue;
-    }
-
     if (!object_usable_as_light(object)) {
+      object_id++;
       continue;
     }
 
@@ -368,26 +367,22 @@ void LightManager::device_update_distribution(Device *device,
                            scene->default_surface;
 
       if (shader->get_use_mis() && shader->has_surface_emission) {
-        /* to-do: for the light tree implementation, we eventually want to include emissive triangles.
-         * Right now, point lights are the main concern. */
-        LightTreePrimitive light_prim;
-        light_prim.prim_id = i + mesh->prim_offset;
-        light_prim.object_id = device_triangle_index;
-        light_prims.push_back(light_prim);
+        /* to-do: for the light tree implementation, we eventually want to include emissive
+         * triangles. Right now, point lights are the main concern. */
+        if (light_tree_enabled) {
+          LightTreePrimitive light_prim;
+          light_prim.prim_id = i + mesh->prim_offset;
+          light_prim.object_id = object_id;
+          light_prims.push_back(light_prim);
+        }
+        
         num_triangles++;
       }
     }
 
-    device_triangle_index++;
+    object_id++;
   }
 
-  size_t num_distribution = num_triangles + num_lights;
-  VLOG_INFO << "Total " << num_distribution << " of light distribution primitives.";
-
-  /* emission area */
-  KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
-  float totarea = 0.0f;
-
   if (light_tree_enabled) {
     /* For now, we'll start with a smaller number of max lights in a node.
      * More benchmarking is needed to determine what number works best. */
@@ -439,6 +434,38 @@ void LightManager::device_update_distribution(Device *device,
       light_tree_emitters[index].theta_e = bcone.theta_e;
 
       light_tree_emitters[index].prim_id = prim.prim_id;
+
+      if (prim.prim_id >= 0) {
+        light_tree_emitters[index].mesh_light.object_id = prim.object_id;
+
+        int shader_flag = 0;
+        Object *object = scene->objects[prim.object_id];
+        if (!(object->get_visibility() & PATH_RAY_CAMERA)) {
+          shader_flag |= SHADER_EXCLUDE_CAMERA;
+        }
+        if (!(object->get_visibility() & PATH_RAY_DIFFUSE)) {
+          shader_flag |= SHADER_EXCLUDE_DIFFUSE;
+        }
+        if (!(object->get_visibility() & PATH_RAY_GLOSSY)) {
+          shader_flag |= SHADER_EXCLUDE_GLOSSY;
+        }
+        if (!(object->get_visibility() & PATH_RAY_TRANSMIT)) {
+          shader_flag |= SHADER_EXCLUDE_TRANSMIT;
+        }
+        if (!(object->get_visibility() & PATH_RAY_VOLUME_SCATTER)) {
+          shader_flag |= SHADER_EXCLUDE_SCATTER;
+        }
+        if (!(object->get_is_shadow_catcher())) {
+          shader_flag |= SHADER_EXCLUDE_SHADOW_CATCHER;
+        }
+
+        light_tree_emitters[index].mesh_light.shader_flag = shader_flag;
+      }
+      else {
+        Light *lamp = scene->lights[prim.lamp_id];
+        light_tree_emitters[index].lamp.size = lamp->size;
+        light_tree_emitters[index].lamp.pad = 1.0f;
+      }
     }
     dscene->light_tree_emitters.copy_to_device();
 
@@ -489,38 +516,31 @@ void LightManager::device_update_distribution(Device *device,
 
     dscene->light_tree_distant_group.copy_to_device();
   }
-  
-  /* Add the distant lights to the distribution. */
-  foreach (LightTreePrimitive prim, distant_lights) {
-    light_prims.push_back(prim);
-  }
+
+  size_t num_distribution = num_triangles + num_lights;
+  VLOG_INFO << "Total " << num

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list