[Bf-blender-cvs] [bde57b3a858] soc-2022-many-lights-sampling: Adjust energy scaling for different light types

Weizhen Huang noreply at git.blender.org
Wed Nov 2 17:29:04 CET 2022


Commit: bde57b3a858c27a93ece6d1b02252132f34241e8
Author: Weizhen Huang
Date:   Wed Nov 2 16:06:12 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rBbde57b3a858c27a93ece6d1b02252132f34241e8

Adjust energy scaling for different light types

Differential Revision: https://developer.blender.org/D16368

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

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

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

diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index 9198aa82262..4e9a560c10c 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -945,8 +945,7 @@ ccl_device bool light_tree_sample(KernelGlobals kg,
                                   ccl_private LightSample *ls)
 {
   const bool has_transmission = (shader_flags & SD_BSDF_HAS_TRANSMISSION);
-  /* to-do: with weighted reservoir sampling, we can also try picking a sample from the distant
-   * light group and compare it to the sample from the light tree. */
+  /* TODO: add distant lights to light tree (as one child node of the root node) */
   float distant_light_importance = light_tree_distant_light_importance(
       kg, N, has_transmission, kernel_data.integrator.num_distant_lights);
   float light_tree_importance = 0.0f;
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index f7f3689d514..20650759c29 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -80,32 +80,6 @@ static void shade_background_pixels(Device *device,
       });
 }
 
-static float average_background_energy(
-    Device *device, DeviceScene *dscene, Progress &progress, Scene *scene, Light *light)
-{
-  if (light->get_light_type() != LIGHT_BACKGROUND) {
-    assert(false);
-  }
-
-  /* get the resolution from the light's size (we stuff it in there) */
-  int2 res = make_int2(light->get_map_resolution(), light->get_map_resolution() / 2);
-  /* If it's still unknown, just use the default. */
-  if (res.x == 0 || res.y == 0) {
-    res = make_int2(1024, 512);
-    VLOG_INFO << "Setting World MIS resolution to default\n";
-  }
-
-  vector<float3> pixels;
-  shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
-
-  float total_energy = 0.0f;
-  for (int i = 0; i < pixels.size(); i++) {
-    total_energy += scene->shader_manager->linear_rgb_to_gray(pixels[i]);
-  }
-
-  return total_energy / pixels.size();
-}
-
 /* Light */
 
 NODE_DEFINE(Light)
@@ -136,6 +110,7 @@ NODE_DEFINE(Light)
   SOCKET_FLOAT(spread, "Spread", M_PI_F);
 
   SOCKET_INT(map_resolution, "Map Resolution", 0);
+  SOCKET_FLOAT(average_radiance, "Average Radiance", 0.0f);
 
   SOCKET_FLOAT(spot_angle, "Spot Angle", M_PI_4_F);
   SOCKET_FLOAT(spot_smooth, "Spot Smooth", 0.0f);
@@ -304,8 +279,6 @@ void LightManager::device_update_distribution(Device *device,
   size_t num_triangles = 0;
   size_t total_triangles = 0;
 
-  bool background_mis = false;
-
   /* We want to add both lights and emissive triangles to this vector for light tree construction.
    */
   bool light_tree_enabled = scene->integrator->get_use_light_tree();
@@ -512,7 +485,7 @@ void LightManager::device_update_distribution(Device *device,
 
     /* We use OrientationBounds here to */
     OrientationBounds distant_light_bounds = OrientationBounds::empty;
-    float max_distant_light_energy = 0.0f;
+    light_tree_distant_group[num_distant_lights].energy = 0.f;
     for (int index = 0; index < num_distant_lights; index++) {
       LightTreePrimitive prim = distant_lights[index];
       Light *light = scene->lights[prim.lamp_id];
@@ -521,9 +494,10 @@ void LightManager::device_update_distribution(Device *device,
       /* Lights in this group are either a background or distant light. */
       light_tree_distant_group[index].prim_id = ~prim.prim_id;
 
-      float strength = 0.0f;
+      float energy = 0.0f;
       if (light->light_type == LIGHT_BACKGROUND) {
-        strength = average_background_energy(device, dscene, progress, scene, light);
+        /* integrate over cosine-weighted hemisphere */
+        energy = light->get_average_radiance() * M_PI_F;
 
         /* We can set an arbitrary direction for the background light. */
         light_bounds.axis[0] = 0.0f;
@@ -534,7 +508,8 @@ void LightManager::device_update_distribution(Device *device,
         light_bounds.theta_o = M_PI_F;
       }
       else {
-        strength = prim.calculate_energy(scene);
+        energy = prim.calculate_energy(scene);
+
         for (int i = 0; i < 3; i++) {
           light_bounds.axis[i] = -light->dir[i];
         }
@@ -546,21 +521,14 @@ void LightManager::device_update_distribution(Device *device,
         light_tree_distant_group[index].direction[i] = light_bounds.axis[i];
       }
       light_tree_distant_group[index].bounding_radius = light_bounds.theta_o;
-      /* We multiply the strength of distance lights by 4pi so it more closely matches the
-       * energy output of other light types.
-       * TODO: validate if this is correct*/
-      float energy = strength * M_4PI_F;
       light_tree_distant_group[index].energy = energy;
       light_array[~prim.prim_id] = index;
 
-      if (energy > max_distant_light_energy) {
-        max_distant_light_energy = energy;
-      }
+      light_tree_distant_group[num_distant_lights].energy += energy;
     }
 
     /* The net OrientationBounds contain bounding information about all the distant lights. */
     light_tree_distant_group[num_distant_lights].prim_id = -1;
-    light_tree_distant_group[num_distant_lights].energy = max_distant_light_energy;
     for (int i = 0; i < 3; i++) {
       light_tree_distant_group[num_distant_lights].direction[i] = distant_light_bounds.axis[i];
     }
@@ -679,7 +647,6 @@ void LightManager::device_update_distribution(Device *device,
       }
       else if (light->light_type == LIGHT_BACKGROUND) {
         num_background_lights++;
-        background_mis |= light->use_mis;
       }
 
       light_index++;
@@ -753,17 +720,7 @@ void LightManager::device_update_distribution(Device *device,
     /* Portals */
     if (num_portals > 0) {
       kbackground->portal_offset = light_index;
-      kbackground->num_portals = num_portals;
-      kbackground->portal_weight = 1.0f;
-    }
-    else {
-      kbackground->num_portals = 0;
-      kbackground->portal_offset = 0;
-      kbackground->portal_weight = 0.0f;
     }
-
-    /* Map */
-    kbackground->map_weight = background_mis ? 1.0f : 0.0f;
   }
   else {
     if (light_tree_enabled) {
@@ -782,12 +739,6 @@ void LightManager::device_update_distribution(Device *device,
     kintegrator->distribution_pdf_lights = 0.0f;
     kintegrator->use_lamp_mis = false;
 
-    kbackground->num_portals = 0;
-    kbackground->portal_offset = 0;
-    kbackground->portal_weight = 0.0f;
-    kbackground->sun_weight = 0.0f;
-    kbackground->map_weight = 0.0f;
-
     kfilm->pass_shadow_scale = 1.0f;
   }
 }
@@ -840,20 +791,30 @@ void LightManager::device_update_background(Device *device,
   KernelBackground *kbackground = &dscene->data.background;
   Light *background_light = NULL;
 
+  bool background_mis = false;
+  size_t num_portals = 0;
+
   /* find background light */
   foreach (Light *light, scene->lights) {
-    if (light->light_type == LIGHT_BACKGROUND) {
+    if (light->light_type == LIGHT_BACKGROUND && light->is_enabled) {
       background_light = light;
-      break;
+      background_mis |= light->use_mis;
+    }
+    if (light->is_portal) {
+      num_portals++;
     }
   }
 
+  kbackground->num_portals = num_portals;
+  kbackground->portal_offset = 0;
+  kbackground->portal_weight = num_portals > 0 ? 1.0f : 0.0f;
+  kbackground->map_weight = background_mis ? 1.0f : 0.0f;
+  kbackground->sun_weight = 0.0f;
+
   /* no background light found, signal renderer to skip sampling */
   if (!background_light || !background_light->is_enabled) {
     kbackground->map_res_x = 0;
     kbackground->map_res_y = 0;
-    kbackground->map_weight = 0.0f;
-    kbackground->sun_weight = 0.0f;
     kbackground->use_mis = (kbackground->portal_weight > 0.0f);
     return;
   }
@@ -974,6 +935,8 @@ void LightManager::device_update_background(Device *device,
   float cdf_total = marg_cdf[res.y - 1].y + marg_cdf[res.y - 1].x / res.y;
   marg_cdf[res.y].x = cdf_total;
 
+  background_light->set_average_radiance(cdf_total * M_PI_2_F);
+
   if (cdf_total > 0.0f)
     for (int i = 1; i < res.y; i++)
       marg_cdf[i].y /= cdf_total;
@@ -1263,16 +1226,16 @@ void LightManager::device_update(Device *device,
   if (progress.get_cancel())
     return;
 
-  device_update_distribution(device, dscene, scene, progress);
-  if (progress.get_cancel())
-    return;
-
   if (need_update_background) {
     device_update_background(device, dscene, scene, progress);
     if (progress.get_cancel())
       return;
   }
 
+  device_update_distribution(device, dscene, scene, progress);
+  if (progress.get_cancel())
+    return;
+
   device_update_ies(dscene);
   if (progress.get_cancel())
     return;
diff --git a/intern/cycles/scene/light.h b/intern/cycles/scene/light.h
index 4db4de10ec6..b747e793e8e 100644
--- a/intern/cycles/scene/light.h
+++ b/intern/cycles/scene/light.h
@@ -51,6 +51,7 @@ class Light : public Node {
   NODE_SOCKET_API(Transform, tfm)
 
   NODE_SOCKET_API(int, map_resolution)
+  NODE_SOCKET_API(float, average_radiance)
 
   NODE_SOCKET_API(float, spot_angle)
   NODE_SOCKET_API(float, spot_smooth)
diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp
index 775b4c0bc73..7fbaf9fb572 100644
--- a/intern/cycles/scene/light_tree.cpp
+++ b/intern/cycles/scene/light_tree.cpp
@@ -220,6 +220,13 @@ float LightTreePrimitive::calculate_energy(Scene *scene) const
   else {
     Light *lamp = scene->lights[lamp_id];
     strength = lamp->get_strength();
+    LightType type = lamp->get_light_type();
+    if (type == LIGHT_AREA) {
+      strength *= 0.25f; /* eval_fac scaling in `area.h` */
+    }
+    else if (type == LIGHT_SPOT || type == LIGHT_POINT) {
+      strength *= 0.25f * M_1_PI_F; /* eval_fac scaling in `spot.h` and `point.h` */
+    }
   }
 
   return fabsf(scene->shader_manager->linear_rgb_to_gray(strength));



More information about the Bf-blender-cvs mailing list