[Bf-blender-cvs] [2221389d6e8] master: Bake: vertex color baking support for Cycles

Brecht Van Lommel noreply at git.blender.org
Thu Dec 24 12:41:48 CET 2020


Commit: 2221389d6e8e799ae1a001e4a3457fa5c3fd90fb
Author: Brecht Van Lommel
Date:   Wed Dec 23 21:03:00 2020 +0100
Branches: master
https://developer.blender.org/rB2221389d6e8e799ae1a001e4a3457fa5c3fd90fb

Bake: vertex color baking support for Cycles

In the Bake > Output panel, there is now a choice between Image Textures and
Vertex Colors. The active vertex color layer is used for baking. This works
with both existing per-corner and sculpt per-vertex vertex colors.

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

M	intern/cycles/blender/addon/ui.py
M	source/blender/editors/object/object_bake_api.c
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/RNA_enum_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 1bddacbb7a0..579f0c1b040 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1969,9 +1969,11 @@ class CYCLES_RENDER_PT_bake_output(CyclesButtonsPanel, Panel):
             if rd.bake_type == 'DISPLACEMENT':
                 layout.prop(rd, "use_bake_lores_mesh")
         else:
+            layout.prop(cbk, "target")
 
-            layout.prop(cbk, "margin")
-            layout.prop(cbk, "use_clear", text="Clear Image")
+            if cbk.target == 'IMAGE_TEXTURES':
+                layout.prop(cbk, "margin")
+                layout.prop(cbk, "use_clear", text="Clear Image")
 
 
 class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 2dba883d866..53dc10f8f15 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -83,6 +83,8 @@ typedef struct BakeAPIRender {
   ListBase selected_objects;
 
   /* Baking settings. */
+  eBakeTarget target;
+
   eScenePassType pass_type;
   int pass_filter;
   int margin;
@@ -416,7 +418,10 @@ static bool is_noncolor_pass(eScenePassType pass_type)
 }
 
 /* if all is good tag image and return true */
-static bool bake_object_check(ViewLayer *view_layer, Object *ob, ReportList *reports)
+static bool bake_object_check(ViewLayer *view_layer,
+                              Object *ob,
+                              const eBakeTarget target,
+                              ReportList *reports)
 {
   Base *base = BKE_view_layer_base_find(view_layer, ob);
 
@@ -442,67 +447,69 @@ static bool bake_object_check(ViewLayer *view_layer, Object *ob, ReportList *rep
     return false;
   }
 
-  for (int i = 0; i < ob->totcol; i++) {
-    bNodeTree *ntree = NULL;
-    bNode *node = NULL;
-    const int mat_nr = i + 1;
-    Image *image;
-    ED_object_get_active_image(ob, mat_nr, &image, NULL, &node, &ntree);
+  if (target == R_BAKE_TARGET_IMAGE_TEXTURES) {
+    for (int i = 0; i < ob->totcol; i++) {
+      bNodeTree *ntree = NULL;
+      bNode *node = NULL;
+      const int mat_nr = i + 1;
+      Image *image;
+      ED_object_get_active_image(ob, mat_nr, &image, NULL, &node, &ntree);
+
+      if (image) {
+        ImBuf *ibuf;
+
+        if (node) {
+          if (BKE_node_is_connected_to_output(ntree, node)) {
+            /* we don't return false since this may be a false positive
+             * this can't be RPT_ERROR though, otherwise it prevents
+             * multiple highpoly objects to be baked at once */
+            BKE_reportf(reports,
+                        RPT_INFO,
+                        "Circular dependency for image \"%s\" from object \"%s\"",
+                        image->id.name + 2,
+                        ob->id.name + 2);
+          }
+        }
 
-    if (image) {
-      ImBuf *ibuf;
+        void *lock;
+        ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
 
-      if (node) {
-        if (BKE_node_is_connected_to_output(ntree, node)) {
-          /* we don't return false since this may be a false positive
-           * this can't be RPT_ERROR though, otherwise it prevents
-           * multiple highpoly objects to be baked at once */
+        if (ibuf) {
+          BKE_image_release_ibuf(image, ibuf, lock);
+        }
+        else {
           BKE_reportf(reports,
-                      RPT_INFO,
-                      "Circular dependency for image \"%s\" from object \"%s\"",
+                      RPT_ERROR,
+                      "Uninitialized image \"%s\" from object \"%s\"",
                       image->id.name + 2,
                       ob->id.name + 2);
-        }
-      }
-
-      void *lock;
-      ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
 
-      if (ibuf) {
-        BKE_image_release_ibuf(image, ibuf, lock);
-      }
-      else {
-        BKE_reportf(reports,
-                    RPT_ERROR,
-                    "Uninitialized image \"%s\" from object \"%s\"",
-                    image->id.name + 2,
-                    ob->id.name + 2);
-
-        BKE_image_release_ibuf(image, ibuf, lock);
-        return false;
-      }
-    }
-    else {
-      Material *mat = BKE_object_material_get(ob, mat_nr);
-      if (mat != NULL) {
-        BKE_reportf(reports,
-                    RPT_INFO,
-                    "No active image found in material \"%s\" (%d) for object \"%s\"",
-                    mat->id.name + 2,
-                    i,
-                    ob->id.name + 2);
+          BKE_image_release_ibuf(image, ibuf, lock);
+          return false;
+        }
       }
       else {
-        BKE_reportf(reports,
-                    RPT_INFO,
-                    "No active image found in material slot (%d) for object \"%s\"",
-                    i,
-                    ob->id.name + 2);
+        Material *mat = BKE_object_material_get(ob, mat_nr);
+        if (mat != NULL) {
+          BKE_reportf(reports,
+                      RPT_INFO,
+                      "No active image found in material \"%s\" (%d) for object \"%s\"",
+                      mat->id.name + 2,
+                      i,
+                      ob->id.name + 2);
+        }
+        else {
+          BKE_reportf(reports,
+                      RPT_INFO,
+                      "No active image found in material slot (%d) for object \"%s\"",
+                      i,
+                      ob->id.name + 2);
+        }
+        continue;
       }
-      continue;
-    }
 
-    image->id.tag |= LIB_TAG_DOIT;
+      image->id.tag |= LIB_TAG_DOIT;
+    }
   }
 
   return true;
@@ -576,7 +583,8 @@ static bool bake_objects_check(Main *bmain,
                                Object *ob,
                                ListBase *selected_objects,
                                ReportList *reports,
-                               const bool is_selected_to_active)
+                               const bool is_selected_to_active,
+                               const eBakeTarget target)
 {
   CollectionPointerLink *link;
 
@@ -586,7 +594,7 @@ static bool bake_objects_check(Main *bmain,
   if (is_selected_to_active) {
     int tot_objects = 0;
 
-    if (!bake_object_check(view_layer, ob, reports)) {
+    if (!bake_object_check(view_layer, ob, target, reports)) {
       return false;
     }
 
@@ -620,7 +628,7 @@ static bool bake_objects_check(Main *bmain,
     }
 
     for (link = selected_objects->first; link; link = link->next) {
-      if (!bake_object_check(view_layer, link->ptr.data, reports)) {
+      if (!bake_object_check(view_layer, link->ptr.data, target, reports)) {
         return false;
       }
     }
@@ -895,6 +903,161 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr,
   return all_ok;
 }
 
+/* Vertex Color Bake Targets */
+
+static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, ReportList *reports)
+{
+  if (ob->type != OB_MESH) {
+    BKE_report(
+        reports, RPT_ERROR, "Vertex color baking not support with object types other than mesh");
+    return false;
+  }
+
+  Mesh *me = ob->data;
+  MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
+  MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
+  if (mcol == NULL && mloopcol == NULL) {
+    BKE_report(reports, RPT_ERROR, "No vertex colors layer found to bake to");
+    return false;
+  }
+
+  targets->images = MEM_callocN(sizeof(BakeImage), "BakeTargets.images");
+  targets->num_images = 1;
+
+  targets->material_to_image = MEM_callocN(sizeof(int) * ob->totcol,
+                                           "BakeTargets.material_to_image");
+  targets->num_materials = ob->totcol;
+
+  BakeImage *bk_image = &targets->images[0];
+  bk_image->width = me->totvert;
+  bk_image->height = 1;
+  bk_image->offset = 0;
+  bk_image->image = NULL;
+
+  targets->num_pixels = bk_image->width * bk_image->height;
+
+  return true;
+}
+
+static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets,
+                                                       Mesh *me,
+                                                       BakePixel *pixel_array)
+{
+  const int num_pixels = targets->num_pixels;
+
+  /* Initialize blank pixels. */
+  for (int i = 0; i < num_pixels; i++) {
+    BakePixel *pixel = &pixel_array[i];
+
+    pixel->primitive_id = -1;
+    pixel->object_id = 0;
+    pixel->du_dx = 0.0f;
+    pixel->du_dy = 0.0f;
+    pixel->dv_dx = 0.0f;
+    pixel->dv_dy = 0.0f;
+    pixel->uv[0] = 0.0f;
+    pixel->uv[1] = 0.0f;
+  }
+
+  /* Populate through adjacent triangles, first triangle wins. */
+  const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
+  MLoopTri *looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
+
+  BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
+
+  for (int i = 0; i < tottri; i++) {
+    const MLoopTri *lt = &looptri[i];
+
+    for (int j = 0; j < 3; j++) {
+      const unsigned int v = me->mloop[lt->tri[j]].v;
+      BakePixel *pixel = &pixel_array[v];
+
+      if (pixel->primitive_id != -1) {
+        continue;
+      }
+
+      pixel->primitive_id = i;
+
+      /* Barycentric coordinates, nudged a bit to avoid precision issues that
+       * may happen when exactly at the vertex coordinate. */
+      if (j == 0) {
+        pixel->uv[0] = 1.0f - FLT_EPSILON;
+        pixel->uv[1] = FLT_EPSILON / 2.0f;
+      }
+      else if (j == 1) {
+        pixel->uv[0] = FLT_EPSILON / 2.0f;
+        pixel->uv[1] = 1.0f - FLT_EPSILON;
+      }
+      else if (j == 2) {
+        pixel->uv[0] = FLT_EPSILON / 2.0f;
+        pixel->uv[1] = FLT_EPSILON / 2.0f;
+      }
+    }
+  }
+
+  MEM_freeN(looptri);
+}
+
+static void bake_result_to_rgba(float rgba[4], const float *result, const int num_channels)
+{
+  if (num_channels == 4) {
+    copy_v4_v4(rgba, result);
+  }
+  else if (num_channels == 3) {
+    copy_v3_v3(rgba, result);
+    rgba[3] = 1.0f;
+  }
+  else {
+    rgba[0] = result[0];
+    rgba[1] = result[0];
+    rgba[2] = result[0];
+    rgba[3] = 1.0f;
+  }
+}
+
+static bool bake_targets_ou

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list