[Bf-blender-cvs] [b475506cfbd] master: Cycles: add option to bake specular from active camera viewpoint

Phoenix Katsch noreply at git.blender.org
Mon Oct 3 22:07:48 CEST 2022


Commit: b475506cfbd35fe2d356ce43a6a3e1f93bd6602b
Author: Phoenix Katsch
Date:   Mon Oct 3 19:26:02 2022 +0200
Branches: master
https://developer.blender.org/rBb475506cfbd35fe2d356ce43a6a3e1f93bd6602b

Cycles: add option to bake specular from active camera viewpoint

Previously it would bake viewed from above the surface. The new option can be
useful when the baked result is meant to be viewed from a fixed viewpoint or
with limited camera motion.

Some effort is made to give a continuous reflection on parts of the surface
invisible to the camera, but this is necessarily only a rough approximation.

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

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

M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/camera.cpp
M	intern/cycles/kernel/integrator/init_from_bake.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/bake.cpp
M	intern/cycles/scene/bake.h
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_scene.c

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

diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 7036e58f6fb..f763fe0eb0b 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1880,6 +1880,12 @@ class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel):
             layout.prop(rd, "use_bake_multires")
             layout.prop(cscene, "bake_type")
 
+        if not rd.use_bake_multires and cscene.bake_type not in {
+                "AO", "POSITION", "NORMAL", "UV", "ROUGHNESS", "ENVIRONMENT"}:
+            row = layout.row()
+            row.prop(cbk, "view_from")
+            row.active = scene.camera is not None
+
 
 class CYCLES_RENDER_PT_bake_influence(CyclesButtonsPanel, Panel):
     bl_label = "Influence"
diff --git a/intern/cycles/blender/camera.cpp b/intern/cycles/blender/camera.cpp
index 6926c833096..d7def9fdb7c 100644
--- a/intern/cycles/blender/camera.cpp
+++ b/intern/cycles/blender/camera.cpp
@@ -2,6 +2,7 @@
  * Copyright 2011-2022 Blender Foundation */
 
 #include "scene/camera.h"
+#include "scene/bake.h"
 #include "scene/scene.h"
 
 #include "blender/sync.h"
@@ -592,6 +593,11 @@ void BlenderSync::sync_camera(BL::RenderSettings &b_render,
     blender_camera_from_object(&bcam, b_engine, b_ob);
     b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
     bcam.matrix = get_transform(b_ob_matrix);
+    scene->bake_manager->set_use_camera(b_render.bake().view_from() ==
+                                        BL::BakeSettings::view_from_ACTIVE_CAMERA);
+  }
+  else {
+    scene->bake_manager->set_use_camera(false);
   }
 
   /* sync */
diff --git a/intern/cycles/kernel/integrator/init_from_bake.h b/intern/cycles/kernel/integrator/init_from_bake.h
index eca2c0b9ffb..15968670ac2 100644
--- a/intern/cycles/kernel/integrator/init_from_bake.h
+++ b/intern/cycles/kernel/integrator/init_from_bake.h
@@ -210,8 +210,51 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
 
     /* Setup ray. */
     Ray ray ccl_optional_struct_init;
-    ray.P = P + N;
-    ray.D = -N;
+
+    if (kernel_data.bake.use_camera) {
+      float3 D = camera_direction_from_point(kg, P);
+
+      const float DN = dot(D, N);
+
+      /* Nudge camera direction, so that the faces facing away from the camera still have
+       * somewhat usable shading. (Otherwise, glossy faces would be simply black.)
+       *
+       * The surface normal offset affects smooth surfaces. Lower values will make
+       * smooth surfaces more faceted, but higher values may show up from the camera
+       * at grazing angles.
+       *
+       * This value can actually be pretty high before it's noticeably wrong. */
+      const float surface_normal_offset = 0.2f;
+
+      /* Keep the ray direction at least `surface_normal_offset` "above" the smooth normal. */
+      if (DN <= surface_normal_offset) {
+        D -= N * (DN - surface_normal_offset);
+        D = normalize(D);
+      }
+
+      /* On the backside, just lerp towards the surface normal for the ray direction,
+       * as DN goes from 0.0 to -1.0. */
+      if (DN <= 0.0f) {
+        D = normalize(mix(D, N, -DN));
+      }
+
+      /* We don't want to bake the back face, so make sure the ray direction never
+       * goes behind the geometry (flat) normal. This is a failsafe, and should rarely happen. */
+      const float true_normal_epsilon = 0.00001f;
+
+      if (dot(D, Ng) <= true_normal_epsilon) {
+        D -= Ng * (dot(D, Ng) - true_normal_epsilon);
+        D = normalize(D);
+      }
+
+      ray.P = P + D;
+      ray.D = -D;
+    }
+    else {
+      ray.P = P + N;
+      ray.D = -N;
+    }
+
     ray.tmin = 0.0f;
     ray.tmax = FLT_MAX;
     ray.time = 0.5f;
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index f81e7843629..1469d915d15 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -1160,7 +1160,7 @@ typedef struct KernelBake {
   int use;
   int object_index;
   int tri_offset;
-  int pad1;
+  int use_camera;
 } KernelBake;
 static_assert_align(KernelBake, 16);
 
diff --git a/intern/cycles/scene/bake.cpp b/intern/cycles/scene/bake.cpp
index 1947b9d71a4..768e723b587 100644
--- a/intern/cycles/scene/bake.cpp
+++ b/intern/cycles/scene/bake.cpp
@@ -16,6 +16,7 @@ CCL_NAMESPACE_BEGIN
 BakeManager::BakeManager()
 {
   need_update_ = true;
+  use_camera_ = false;
 }
 
 BakeManager::~BakeManager()
@@ -38,6 +39,14 @@ void BakeManager::set(Scene *scene, const std::string &object_name_)
   need_update_ = true;
 }
 
+void BakeManager::set_use_camera(const bool use_camera)
+{
+  if (use_camera_ != use_camera) {
+    use_camera_ = use_camera;
+    need_update_ = true;
+  }
+}
+
 void BakeManager::device_update(Device * /*device*/,
                                 DeviceScene *dscene,
                                 Scene *scene,
@@ -49,6 +58,8 @@ void BakeManager::device_update(Device * /*device*/,
   KernelBake *kbake = &dscene->data.bake;
   memset(kbake, 0, sizeof(*kbake));
 
+  kbake->use_camera = use_camera_;
+
   if (!object_name.empty()) {
     scoped_callback_timer timer([scene](double time) {
       if (scene->update_stats) {
diff --git a/intern/cycles/scene/bake.h b/intern/cycles/scene/bake.h
index 0d90ece5628..e3f3911ab05 100644
--- a/intern/cycles/scene/bake.h
+++ b/intern/cycles/scene/bake.h
@@ -20,6 +20,8 @@ class BakeManager {
   void set(Scene *scene, const std::string &object_name);
   bool get_baking() const;
 
+  void set_use_camera(bool use_camera);
+
   void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
   void device_free(Device *device, DeviceScene *dscene);
 
@@ -30,6 +32,7 @@ class BakeManager {
  private:
   bool need_update_;
   std::string object_name;
+  bool use_camera_;
 };
 
 CCL_NAMESPACE_END
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 80b1049ca23..2db81693f51 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -559,7 +559,8 @@ typedef struct BakeData {
   char target;
   char save_mode;
   char margin_type;
-  char _pad[5];
+  char view_from;
+  char _pad[4];
 
   struct Object *cage_object;
 } BakeData;
@@ -592,6 +593,12 @@ typedef enum eBakeSaveMode {
   R_BAKE_SAVE_EXTERNAL = 1,
 } eBakeSaveMode;
 
+/** #BakeData.view_from (char) */
+typedef enum eBakeViewFrom {
+  R_BAKE_VIEW_FROM_ABOVE_SURFACE = 0,
+  R_BAKE_VIEW_FROM_ACTIVE_CAMERA = 1,
+} eBakeViewFrom;
+
 /** #BakeData.pass_filter */
 typedef enum eBakePassFilter {
   R_BAKE_PASS_FILTER_NONE = 0,
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index da30b7f2136..fdf8be9cb33 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -476,6 +476,20 @@ const EnumPropertyItem rna_enum_bake_save_mode_items[] = {
     {0, NULL, 0, NULL, NULL},
 };
 
+const EnumPropertyItem rna_enum_bake_view_from_items[] = {
+    {R_BAKE_VIEW_FROM_ABOVE_SURFACE,
+     "ABOVE_SURFACE",
+     0,
+     "Above Surface",
+     "Cast rays from above the surface"},
+    {R_BAKE_VIEW_FROM_ACTIVE_CAMERA,
+     "ACTIVE_CAMERA",
+     0,
+     "Active Camera",
+     "Use the active camera's position to cast rays"},
+    {0, NULL, 0, NULL, NULL},
+};
+
 #define R_IMF_VIEWS_ENUM_IND \
   {R_IMF_VIEWS_INDIVIDUAL, \
    "INDIVIDUAL", \
@@ -5413,6 +5427,11 @@ static void rna_def_bake_data(BlenderRNA *brna)
   RNA_def_property_ui_text(prop, "Save Mode", "Where to save baked image textures");
   RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 
+  prop = RNA_def_property(srna, "view_from", PROP_ENUM, PROP_NONE);
+  RNA_def_property_enum_items(prop, rna_enum_bake_view_from_items);
+  RNA_def_property_ui_text(prop, "View From", "Source of reflection ray directions");
+  RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
   /* flags */
   prop = RNA_def_property(srna, "use_selected_to_active", PROP_BOOLEAN, PROP_NONE);
   RNA_def_property_boolean_sdna(prop, NULL, "flag", R_BAKE_TO_ACTIVE);



More information about the Bf-blender-cvs mailing list