[Bf-blender-cvs] [b6b43390676] cycles-x: Cycles X: add camera visibility and shadow catcher options for lights

Brecht Van Lommel noreply at git.blender.org
Fri Aug 6 11:09:01 CEST 2021


Commit: b6b43390676cf7187cad20073e86c771bdd470db
Author: Brecht Van Lommel
Date:   Wed Aug 4 20:13:55 2021 +0200
Branches: cycles-x
https://developer.blender.org/rBb6b43390676cf7187cad20073e86c771bdd470db

Cycles X: add camera visibility and shadow catcher options for lights

* Camera visibility makes it so lights can be directly visible as objects
  in the scene. This is disabled by default but can be enabled now. Be
  aware that aliasing can be a problem with directly visible bright lights.
* The shadow catcher works similar to emissive triangles on meshes. It's
  useful when you for example use light objecs for the headlights of a car,
  where you want their reflection on the road to be composited in.

For performance, I saw no difference outside of timing noise.

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

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

M	intern/cycles/blender/blender_light.cpp
M	intern/cycles/kernel/integrator/integrator_intersect_closest.h
M	intern/cycles/kernel/integrator/integrator_shade_background.h
M	intern/cycles/kernel/kernel_light.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/render/light.cpp
M	intern/cycles/render/light.h

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

diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp
index a2f19f5fdf5..d842d1cf4a2 100644
--- a/intern/cycles/blender/blender_light.cpp
+++ b/intern/cycles/blender/blender_light.cpp
@@ -149,10 +149,12 @@ void BlenderSync::sync_light(BL::Object &b_parent,
 
   /* visibility */
   uint visibility = object_ray_visibility(b_ob);
+  light->set_use_camera((visibility & PATH_RAY_CAMERA) != 0);
   light->set_use_diffuse((visibility & PATH_RAY_DIFFUSE) != 0);
   light->set_use_glossy((visibility & PATH_RAY_GLOSSY) != 0);
   light->set_use_transmission((visibility & PATH_RAY_TRANSMIT) != 0);
   light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0);
+  light->set_is_shadow_catcher(b_ob.is_shadow_catcher());
 
   /* tag */
   light->tag_update(scene);
diff --git a/intern/cycles/kernel/integrator/integrator_intersect_closest.h b/intern/cycles/kernel/integrator/integrator_intersect_closest.h
index d92e097e783..34ca6814534 100644
--- a/intern/cycles/kernel/integrator/integrator_intersect_closest.h
+++ b/intern/cycles/kernel/integrator/integrator_intersect_closest.h
@@ -179,12 +179,15 @@ ccl_device void integrator_intersect_closest(INTEGRATOR_STATE_ARGS)
   }
 
   /* Light intersection for MIS. */
-  if (kernel_data.integrator.use_lamp_mis && !(INTEGRATOR_STATE(path, flag) & PATH_RAY_CAMERA)) {
+  if (kernel_data.integrator.use_lamp_mis) {
     /* NOTE: if we make lights visible to camera rays, we'll need to initialize
      * these in the path_state_init. */
     const int last_type = INTEGRATOR_STATE(isect, type);
+    const int path_flag = INTEGRATOR_STATE(path, flag);
 
-    hit = lights_intersect(kg, &ray, &isect, last_isect_prim, last_isect_object, last_type) || hit;
+    hit = lights_intersect(
+              kg, &ray, &isect, last_isect_prim, last_isect_object, last_type, path_flag) ||
+          hit;
   }
 
   /* Write intersection result into global integrator state memory. */
diff --git a/intern/cycles/kernel/integrator/integrator_shade_background.h b/intern/cycles/kernel/integrator/integrator_shade_background.h
index 4ff9b9e48bf..3c72251fa2f 100644
--- a/intern/cycles/kernel/integrator/integrator_shade_background.h
+++ b/intern/cycles/kernel/integrator/integrator_shade_background.h
@@ -149,6 +149,7 @@ ccl_device_inline void integrate_distant_lights(INTEGRATOR_STATE_ARGS,
              ((path_flag & (PATH_RAY_GLOSSY | PATH_RAY_REFLECT)) ==
               (PATH_RAY_GLOSSY | PATH_RAY_REFLECT))) ||
             ((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT)) ||
+            ((ls.shader & SHADER_EXCLUDE_CAMERA) && (path_flag & PATH_RAY_CAMERA)) ||
             ((ls.shader & SHADER_EXCLUDE_SCATTER) && (path_flag & PATH_RAY_VOLUME_SCATTER)))
           return;
       }
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index a653ff5b218..52f641634b9 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -50,9 +50,16 @@ ccl_device_inline bool light_sample(const KernelGlobals *kg,
                                     const float randu,
                                     const float randv,
                                     const float3 P,
+                                    const int path_flag,
                                     LightSample *ls)
 {
   const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
+  if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
+    if (klight->shader_id & SHADER_EXCLUDE_SHADOW_CATCHER) {
+      return false;
+    }
+  }
+
   LightType type = (LightType)klight->type;
   ls->type = type;
   ls->shader = klight->shader_id;
@@ -207,17 +214,32 @@ ccl_device bool lights_intersect(const KernelGlobals *ccl_restrict kg,
                                  Intersection *ccl_restrict isect,
                                  const int last_prim,
                                  const int last_object,
-                                 const int last_type)
+                                 const int last_type,
+                                 const int path_flag)
 {
   for (int lamp = 0; lamp < kernel_data.integrator.num_all_lights; lamp++) {
     const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
-    LightType type = (LightType)klight->type;
-    float t = 0.0f, u = 0.0f, v = 0.0f;
 
-    if (!(klight->shader_id & SHADER_USE_MIS)) {
-      continue;
+    if (path_flag & PATH_RAY_CAMERA) {
+      if (klight->shader_id & SHADER_EXCLUDE_CAMERA) {
+        continue;
+      }
+    }
+    else {
+      if (!(klight->shader_id & SHADER_USE_MIS)) {
+        continue;
+      }
+    }
+
+    if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
+      if (klight->shader_id & SHADER_EXCLUDE_SHADOW_CATCHER) {
+        continue;
+      }
     }
 
+    LightType type = (LightType)klight->type;
+    float t = 0.0f, u = 0.0f, v = 0.0f;
+
     if (type == LIGHT_POINT || type == LIGHT_SPOT) {
       /* Sphere light. */
       const float3 lightP = make_float3(klight->co[0], klight->co[1], klight->co[2]);
@@ -808,7 +830,7 @@ ccl_device_noinline bool light_distribution_sample(const KernelGlobals *kg,
     return false;
   }
 
-  return light_sample<in_volume_segment>(kg, lamp, randu, randv, P, ls);
+  return light_sample<in_volume_segment>(kg, lamp, randu, randv, P, path_flag, ls);
 }
 
 ccl_device_inline bool light_distribution_sample_from_volume_segment(const KernelGlobals *kg,
@@ -848,7 +870,7 @@ ccl_device_inline bool light_distribution_sample_new_position(const KernelGlobal
     return (ls->pdf > 0.0f);
   }
   else {
-    return light_sample<false>(kg, ls->lamp, randu, randv, P, ls);
+    return light_sample<false>(kg, ls->lamp, randu, randv, P, 0, ls);
   }
 }
 
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 6e65e9fdc34..d5468d8afce 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -419,8 +419,10 @@ typedef enum ShaderFlag {
   SHADER_EXCLUDE_TRANSMIT = (1 << 25),
   SHADER_EXCLUDE_CAMERA = (1 << 24),
   SHADER_EXCLUDE_SCATTER = (1 << 23),
+  SHADER_EXCLUDE_SHADOW_CATCHER = (1 << 22),
   SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE | SHADER_EXCLUDE_GLOSSY | SHADER_EXCLUDE_TRANSMIT |
-                        SHADER_EXCLUDE_CAMERA | SHADER_EXCLUDE_SCATTER),
+                        SHADER_EXCLUDE_CAMERA | SHADER_EXCLUDE_SCATTER |
+                        SHADER_EXCLUDE_SHADOW_CATCHER),
 
   SHADER_MASK = ~(SHADER_SMOOTH_NORMAL | SHADER_CAST_SHADOW | SHADER_AREA_LIGHT | SHADER_USE_MIS |
                   SHADER_EXCLUDE_ANY)
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 948325c25e9..746a6f785d6 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -129,6 +129,7 @@ NODE_DEFINE(Light)
 
   SOCKET_BOOLEAN(cast_shadow, "Cast Shadow", true);
   SOCKET_BOOLEAN(use_mis, "Use Mis", false);
+  SOCKET_BOOLEAN(use_camera, "Use Camera", true);
   SOCKET_BOOLEAN(use_diffuse, "Use Diffuse", true);
   SOCKET_BOOLEAN(use_glossy, "Use Glossy", true);
   SOCKET_BOOLEAN(use_transmission, "Use Transmission", true);
@@ -137,6 +138,7 @@ NODE_DEFINE(Light)
   SOCKET_INT(max_bounces, "Max Bounces", 1024);
   SOCKET_UINT(random_id, "Random ID", 0);
 
+  SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", true);
   SOCKET_BOOLEAN(is_portal, "Is Portal", false);
   SOCKET_BOOLEAN(is_enabled, "Is Enabled", true);
 
@@ -341,6 +343,9 @@ void LightManager::device_update_distribution(Device *,
     int object_id = j;
     int shader_flag = 0;
 
+    if (!(object->get_visibility() & PATH_RAY_CAMERA)) {
+      shader_flag |= SHADER_EXCLUDE_CAMERA;
+    }
     if (!(object->get_visibility() & PATH_RAY_DIFFUSE)) {
       shader_flag |= SHADER_EXCLUDE_DIFFUSE;
       use_light_visibility = true;
@@ -357,6 +362,9 @@ void LightManager::device_update_distribution(Device *,
       shader_flag |= SHADER_EXCLUDE_SCATTER;
       use_light_visibility = true;
     }
+    if (!(object->get_is_shadow_catcher())) {
+      shader_flag |= SHADER_EXCLUDE_SHADOW_CATCHER;
+    }
 
     size_t mesh_num_triangles = mesh->num_triangles();
     for (size_t i = 0; i < mesh_num_triangles; i++) {
@@ -749,6 +757,9 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
     if (!light->cast_shadow)
       shader_id &= ~SHADER_CAST_SHADOW;
 
+    if (!light->use_camera) {
+      shader_id |= SHADER_EXCLUDE_CAMERA;
+    }
     if (!light->use_diffuse) {
       shader_id |= SHADER_EXCLUDE_DIFFUSE;
       use_light_visibility = true;
@@ -765,6 +776,9 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
       shader_id |= SHADER_EXCLUDE_SCATTER;
       use_light_visibility = true;
     }
+    if (!light->is_shadow_catcher) {
+      shader_id |= SHADER_EXCLUDE_SHADOW_CATCHER;
+    }
 
     klights[light_index].type = light->light_type;
     klights[light_index].strength[0] = light->strength.x;
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index edf14dc5693..a5681db9f69 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -69,11 +69,13 @@ class Light : public Node {
 
   NODE_SOCKET_API(bool, cast_shadow)
   NODE_SOCKET_API(bool, use_mis)
+  NODE_SOCKET_API(bool, use_camera)
   NODE_SOCKET_API(bool, use_diffuse)
   NODE_SOCKET_API(bool, use_glossy)
   NODE_SOCKET_API(bool, use_transmission)
   NODE_SOCKET_API(bool, use_scatter)
 
+  NODE_SOCKET_API(bool, is_shadow_catcher)
   NODE_SOCKET_API(bool, is_portal)
   NODE_SOCKET_API(bool, is_enabled)



More information about the Bf-blender-cvs mailing list