[Bf-blender-cvs] [5bae09c1c74] soc-2022-many-lights-sampling: Cycles: support spot and area lights in light tree

Jeffrey Liu noreply at git.blender.org
Sun Jun 19 08:10:40 CEST 2022


Commit: 5bae09c1c742c70162781a414ce8eba6b3d97a23
Author: Jeffrey Liu
Date:   Sun Jun 19 02:10:01 2022 -0400
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB5bae09c1c742c70162781a414ce8eba6b3d97a23

Cycles: support spot and area lights in light tree

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

M	intern/cycles/kernel/light/light_tree.h
M	intern/cycles/scene/light.cpp
M	intern/cycles/scene/light_tree.cpp
M	release/scripts/addons

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

diff --git a/intern/cycles/kernel/light/light_tree.h b/intern/cycles/kernel/light/light_tree.h
index 87c49ebc30c..1c9684e006c 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -84,28 +84,22 @@ ccl_device float light_tree_emitter_importance(KernelGlobals kg,
   if (prim >= 0) {
     /* to-do: handle case for mesh lights. */
   }
-  else {
-    const int lamp = -prim - 1;
-    const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
-    if (klight->type == LIGHT_POINT) {
-      const float radius = klight->spot.radius;
-      const float3 bbox_min = make_float3(
-          klight->co[0] - radius, klight->co[1] - radius, klight->co[2] - radius);
-      const float3 bbox_max = make_float3(
-          klight->co[0] + radius, klight->co[1] + radius, klight->co[2] + radius);
-      const float3 rgb_strength = make_float3(
-          klight->strength[0], klight->strength[1], klight->strength[2]);
-
-      /* to-do: only the radius and invarea from the spotlight properties is used for a point light,
-       * but we still need to choose an arbitrary direction. Maybe this can be replaced with something else? */
-      const float3 bcone_axis = make_float3(
-          klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
-
-      return light_tree_node_importance(
-          P, N, bbox_min, bbox_max, bcone_axis, M_PI_F, M_PI_2_F, linear_rgb_to_gray(kg, rgb_strength));
-    }
-  }
 
+  /* If we're not at a mesh light, then we should be at a point, spot, or area light. */
+  const int lamp = -prim - 1;
+  const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
+  const float radius = klight->spot.radius;
+  const float3 bbox_min = make_float3(
+      klight->co[0] - radius, klight->co[1] - radius, klight->co[2] - radius);
+  const float3 bbox_max = make_float3(
+      klight->co[0] + radius, klight->co[1] + radius, klight->co[2] + radius);
+  const float3 bcone_axis = make_float3(
+      klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
+  const float3 rgb_strength = make_float3(
+      klight->strength[0], klight->strength[1], klight->strength[2]);
+
+  return light_tree_node_importance(
+      P, N, bbox_min, bbox_max, bcone_axis, M_PI_F, M_PI_2_F, linear_rgb_to_gray(kg, rgb_strength));
 }
 
 ccl_device float light_tree_cluster_importance(KernelGlobals kg,
@@ -208,6 +202,7 @@ ccl_device bool light_tree_sample(KernelGlobals kg,
 
   /* We should never reach this point. */
   assert(false);
+  return false;
 }
 
 ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index 84c4f63a2fb..e9407554cbe 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -288,6 +288,7 @@ void LightManager::device_update_distribution(Device *,
   int scene_light_index = 0;
   foreach (Light *light, scene->lights) {
     if (light->is_enabled) {
+      /* to-do: make sure not to add background lights to the light tree once those scenes are tested. */
       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;
diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp
index d50f257e6c7..22930586d43 100644
--- a/intern/cycles/scene/light_tree.cpp
+++ b/intern/cycles/scene/light_tree.cpp
@@ -60,28 +60,93 @@ OrientationBounds merge(const OrientationBounds& cone_a,
 BoundBox LightTreePrimitive::calculate_bbox(Scene *scene) const
 {
   BoundBox bbox = BoundBox::empty;
-  Light *lamp = scene->lights[lamp_id];
-  /* A point light can emit light from any point within its radius. */
-  bbox.grow(lamp->get_co() - make_float3(lamp->get_size()));
-  bbox.grow(lamp->get_co() + make_float3(lamp->get_size()));
+
+  if (prim_id >= 0) {
+    /* to-do: handle mesh lights in the future. */
+  }
+  else {
+    Light *lamp = scene->lights[lamp_id];
+    LightType type = lamp->get_light_type();
+    const float3 center = lamp->get_co();
+    const float size = lamp->get_size();
+
+    if (type == LIGHT_POINT || type == LIGHT_SPOT) {
+      /* Point and spot lights can emit light from any point within its radius. */
+      const float3 radius = make_float3(size);
+      bbox.grow(center - radius);
+      bbox.grow(center + radius);
+    }
+    else if (type == LIGHT_AREA) {
+      /* For an area light, sizeu and sizev determine the 2 dimensions of the area light,
+       * while axisu and axisv determine the orientation of the 2 dimensions. 
+       * We want to add all 4 corners to our bounding box. */
+      const float3 half_extentu = 0.5 * lamp->get_sizeu() * lamp->get_axisu() * size;
+      const float3 half_extentv = 0.5 * lamp->get_sizev() * lamp->get_axisv() * size;
+
+      bbox.grow(center + half_extentu + half_extentv);
+      bbox.grow(center + half_extentu - half_extentv);
+      bbox.grow(center - half_extentu + half_extentv);
+      bbox.grow(center - half_extentu - half_extentv);
+    }
+    else {
+      /* This should never be reached during construction. */
+      assert(false);
+    }
+  }
+
   return bbox;
 }
 
 OrientationBounds LightTreePrimitive::calculate_bcone(Scene *scene) const
 {
-  OrientationBounds bcone;
-  Light *lamp = scene->lights[lamp_id];
-  bcone.axis = lamp->get_dir() / len(lamp->get_dir());
-  bcone.theta_o = M_PI_F;
-  bcone.theta_e = M_PI_2_F;
+  OrientationBounds bcone = OrientationBounds::empty;
+
+  if (prim_id >= 0) {
+    /* to-do: handle mesh lights in the future. */
+  }
+  else {
+    Light *lamp = scene->lights[lamp_id];
+    LightType type = lamp->get_light_type();
+
+    bcone.axis = normalize(lamp->get_dir());
+
+    if (type == LIGHT_POINT) {
+      bcone.theta_o = M_PI_F;
+      bcone.theta_e = M_PI_2_F;
+    }
+    else if (type == LIGHT_SPOT) {
+      bcone.theta_o = 0;
+      bcone.theta_e = lamp->get_spot_angle() * 0.5f;
+    }
+    else if (type == LIGHT_AREA) {
+      bcone.theta_o = 0;
+      bcone.theta_e = M_PI_2_F;
+    }
+    else {
+      /* This should never be reached during construction. */
+      assert(false);
+    }
+  }
+  
   return bcone;
 }
 
 float LightTreePrimitive::calculate_energy(Scene *scene) const
 {
-  Light *lamp = scene->lights[lamp_id];
-  /* Past GSoC work also divides this by pi, but will need to test which is more accurate. */
-  return scene->shader_manager->linear_rgb_to_gray(lamp->get_strength());
+  float3 strength = make_float3(0.0f);
+
+  if (prim_id >= 0) {
+    /* to-do: handle mesh lights in the future. */
+  }
+  else {
+    Light *lamp = scene->lights[lamp_id];
+    /* to-do: Past GSoC work also divides this by pi, but will need to test which is more accurate. 
+     * It seems like direction should be handled implicitly by the bounding cone, 
+     * by testing will provide more conclusive answers. */
+    strength = lamp->get_strength();
+  }
+
+  return scene->shader_manager->linear_rgb_to_gray(strength);
 }
 
 void LightTreeBuildNode::init_leaf(
diff --git a/release/scripts/addons b/release/scripts/addons
index bdf75cb276d..5902265f1e5 160000
--- a/release/scripts/addons
+++ b/release/scripts/addons
@@ -1 +1 @@
-Subproject commit bdf75cb276dfd3b5266c909de4c099c00c68a659
+Subproject commit 5902265f1e5aaeca3781ea15f994bdf0b3cb054d



More information about the Bf-blender-cvs mailing list