[Bf-blender-cvs] [1a81d268a19] master: Materials: support changing materials during evaluation

Jacques Lucke noreply at git.blender.org
Wed May 19 10:26:41 CEST 2021


Commit: 1a81d268a19f2f1402f408ad1dadf92c7a399607
Author: Jacques Lucke
Date:   Wed May 19 10:23:09 2021 +0200
Branches: master
https://developer.blender.org/rB1a81d268a19f2f1402f408ad1dadf92c7a399607

Materials: support changing materials during evaluation

This commit allows that the evaluated geometry of an object has
different materials from the original geometry. This is needed
for geometry nodes.

The main thing that changes for render engines and exporters
is that the number of material slots on an object and its geometry
might not match anymore. For original data, the slot counts are
still equal, but not for evaluated data.

Accessing material slots though rna stays the same. The behavior
adapts automatically depending on whether the object is evaluated.

When accessing materials of an object through `BKE_object_material_*`
one has to use a new api for evaluated objects:
`BKE_object_material_get_eval` and `BKE_object_material_count_eval`.
In the future, the different behavior might be hidden behind a more
general C api, but that would require quite a few more changes.

The ground truth for the number of materials is the number of materials
on the geometry now. This is important in the current design, because
Eevee needs to know the number of materials just based on the mesh in
`mesh_render_mat_len_get` and similar places.

In a few places I had to add a special case for mesh edit mode to get it
to work properly. This is unfortunate, but I don't see a way around that
for now.

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

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

M	source/blender/blenkernel/BKE_material.h
M	source/blender/blenkernel/intern/material.c
M	source/blender/draw/engines/eevee/eevee_cryptomatte.c
M	source/blender/draw/engines/eevee/eevee_materials.c
M	source/blender/draw/engines/eevee/eevee_volumes.c
M	source/blender/draw/engines/gpencil/gpencil_cache_utils.c
M	source/blender/draw/engines/gpencil/gpencil_draw_data.c
M	source/blender/draw/engines/overlay/overlay_gpencil.c
M	source/blender/draw/engines/overlay/overlay_paint.c
M	source/blender/draw/engines/overlay/overlay_particle.c
M	source/blender/draw/engines/workbench/workbench_materials.c
M	source/blender/draw/engines/workbench/workbench_volume.c
M	source/blender/draw/intern/draw_cache_extract.h
M	source/blender/makesrna/intern/rna_object.c

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

diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 14ea50f808a..96aae2d2d42 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -105,6 +105,11 @@ struct Material *BKE_id_material_pop(struct Main *bmain,
                                      /* index is an int because of RNA. */
                                      int index);
 void BKE_id_material_clear(struct Main *bmain, struct ID *id);
+
+/* eval api */
+struct Material *BKE_object_material_get_eval(struct Object *ob, short act);
+int BKE_object_material_count_eval(struct Object *ob);
+
 /* rendering */
 
 void ramp_blend(int type, float r_col[3], const float fac, const float col[3]);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 37d47a984cc..73afea98163 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -77,6 +77,7 @@
 
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
 
 #include "GPU_material.h"
 
@@ -700,6 +701,73 @@ Material *BKE_object_material_get(Object *ob, short act)
   return ma_p ? *ma_p : NULL;
 }
 
+static ID *get_evaluated_object_data_with_materials(Object *ob)
+{
+  ID *data = ob->data;
+  /* Meshes in edit mode need special handling. */
+  if (ob->type == OB_MESH && ob->mode == OB_MODE_EDIT) {
+    Mesh *mesh = ob->data;
+    if (mesh->edit_mesh && mesh->edit_mesh->mesh_eval_final) {
+      data = &mesh->edit_mesh->mesh_eval_final->id;
+    }
+  }
+  return data;
+}
+
+/**
+ * On evaluated objects the number of materials on an object and its data might go out of sync.
+ * This is because during evaluation materials can be added/removed on the object data.
+ *
+ * For rendering or exporting we generally use the materials on the object data. However, some
+ * material indices might be overwritten by the object.
+ */
+Material *BKE_object_material_get_eval(Object *ob, short act)
+{
+  BLI_assert(DEG_is_evaluated_object(ob));
+  const int slot_index = act - 1;
+
+  if (slot_index < 0) {
+    return NULL;
+  }
+  ID *data = get_evaluated_object_data_with_materials(ob);
+  const short *tot_slots_data_ptr = BKE_id_material_len_p(data);
+  const int tot_slots_data = tot_slots_data_ptr ? *tot_slots_data_ptr : 0;
+  if (slot_index >= tot_slots_data) {
+    return NULL;
+  }
+  const int tot_slots_object = ob->totcol;
+
+  Material ***materials_data_ptr = BKE_id_material_array_p(data);
+  Material **materials_data = materials_data_ptr ? *materials_data_ptr : NULL;
+  Material **materials_object = ob->mat;
+
+  /* Check if slot is overwritten by object. */
+  if (slot_index < tot_slots_object) {
+    if (ob->matbits) {
+      if (ob->matbits[slot_index]) {
+        Material *material = materials_object[slot_index];
+        if (material != NULL) {
+          return material;
+        }
+      }
+    }
+  }
+  /* Otherwise use data from object-data. */
+  if (slot_index < tot_slots_data) {
+    Material *material = materials_data[slot_index];
+    return material;
+  }
+  return NULL;
+}
+
+int BKE_object_material_count_eval(Object *ob)
+{
+  BLI_assert(DEG_is_evaluated_object(ob));
+  ID *id = get_evaluated_object_data_with_materials(ob);
+  const short *len_p = BKE_id_material_len_p(id);
+  return len_p ? *len_p : 0;
+}
+
 Material *BKE_gpencil_material(Object *ob, short act)
 {
   Material *ma = BKE_object_material_get(ob, act);
diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c
index 70d48ea6040..7fe984b4397 100644
--- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c
+++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c
@@ -265,8 +265,7 @@ void EEVEE_cryptomatte_object_hair_cache_populate(EEVEE_Data *vedata,
                                                   Object *ob)
 {
   BLI_assert(ob->type == OB_HAIR);
-  Hair *hair = ob->data;
-  Material *material = hair->mat ? hair->mat[HAIR_MATERIAL_NR - 1] : NULL;
+  Material *material = BKE_object_material_get_eval(ob, HAIR_MATERIAL_NR);
   eevee_cryptomatte_hair_cache_populate(vedata, sldata, ob, NULL, NULL, material);
 }
 
@@ -291,8 +290,7 @@ void EEVEE_cryptomatte_particle_hair_cache_populate(EEVEE_Data *vedata,
         if (draw_as != PART_DRAW_PATH) {
           continue;
         }
-        Mesh *mesh = ob->data;
-        Material *material = part->omat - 1 < mesh->totcol ? NULL : mesh->mat[part->omat - 1];
+        Material *material = BKE_object_material_get_eval(ob, part->omat);
         eevee_cryptomatte_hair_cache_populate(vedata, sldata, ob, psys, md, material);
       }
     }
@@ -318,7 +316,7 @@ void EEVEE_cryptomatte_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *s
         if (geom == NULL) {
           continue;
         }
-        Material *material = BKE_object_material_get(ob, i + 1);
+        Material *material = BKE_object_material_get_eval(ob, i + 1);
         DRWShadingGroup *grp = eevee_cryptomatte_shading_group_create(
             vedata, sldata, ob, material, false);
         DRW_shgroup_call(grp, geom, ob);
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index a4325675ea9..d2e0c8308c5 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -723,7 +723,7 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot, bool holdou
   if (holdout) {
     return BKE_material_default_holdout();
   }
-  Material *ma = BKE_object_material_get(ob, slot + 1);
+  Material *ma = BKE_object_material_get_eval(ob, slot + 1);
   if (ma == NULL) {
     if (ob->type == OB_VOLUME) {
       ma = BKE_material_default_volume();
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 809d6010f10..eed36221fcb 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -501,7 +501,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
                                     Scene *scene,
                                     Object *ob)
 {
-  Material *ma = BKE_object_material_get(ob, 1);
+  Material *ma = BKE_object_material_get_eval(ob, 1);
 
   if (ma == NULL) {
     if (ob->type == OB_VOLUME) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index ee51b751187..adb70f97585 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -60,7 +60,8 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob)
 
   /* Check if any material with holdout flag enabled. */
   tgp_ob->do_mat_holdout = false;
-  for (int i = 0; i < ob->totcol; i++) {
+  const int tot_materials = BKE_object_material_count_eval(ob);
+  for (int i = 0; i < tot_materials; i++) {
     MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, i + 1);
     if (((gp_style != NULL) && (gp_style->flag & GP_MATERIAL_IS_STROKE_HOLDOUT)) ||
         ((gp_style->flag & GP_MATERIAL_IS_FILL_HOLDOUT))) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
index 526f553329e..e3e84dd4c8c 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -186,7 +186,7 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje
 {
   GPENCIL_MaterialPool *matpool = pd->last_material_pool;
 
-  int mat_len = max_ii(1, ob->totcol);
+  int mat_len = max_ii(1, BKE_object_material_count_eval(ob));
 
   bool reuse_matpool = matpool && ((matpool->used_count + mat_len) <= GP_MATERIAL_BUFFER_LEN);
 
diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c
index 891142fe0a2..aa26aa47faa 100644
--- a/source/blender/draw/engines/overlay/overlay_gpencil.c
+++ b/source/blender/draw/engines/overlay/overlay_gpencil.c
@@ -382,7 +382,7 @@ static void overlay_gpencil_draw_stroke_color_name(bGPDlayer *UNUSED(gpl),
                                                    void *thunk)
 {
   Object *ob = (Object *)thunk;
-  Material *ma = BKE_object_material_get(ob, gps->mat_nr + 1);
+  Material *ma = BKE_object_material_get_eval(ob, gps->mat_nr + 1);
   if (ma == NULL) {
     return;
   }
diff --git a/source/blender/draw/engines/overlay/overlay_paint.c b/source/blender/draw/engines/overlay/overlay_paint.c
index 89e724bcfcc..d52640ed174 100644
--- a/source/blender/draw/engines/overlay/overlay_paint.c
+++ b/source/blender/draw/engines/overlay/overlay_paint.c
@@ -48,7 +48,7 @@ static bool paint_object_is_rendered_transparent(View3D *v3d, Object *ob)
         v3d->shading.color_type == V3D_SHADING_MATERIAL_COLOR) {
       Mesh *me = ob->data;
       for (int i = 0; i < me->totcol; i++) {
-        Material *mat = me->mat[i];
+        Material *mat = BKE_object_material_get_eval(ob, i + 1);
         if (mat && mat->a < 1.0f) {
           return true;
         }
diff --git a/source/blender/draw/engines/overlay/overlay_particle.c b/source/blender/draw/engines/overlay/overlay_particle.c
index 71064e7ff47..5fa74a8c3a6 100644
--- a/source/blender/draw/engines/overlay/overlay_particle.c
+++ b/source/blender/draw/engines/overlay/overlay_particle.c
@@ -186,7 +186,7 @@ void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob)
       /* TODO(fclem): Here would be a good place for preemptive culling. */
 
       /* NOTE(fclem): Is color even useful in our modern context? */
-      Material *ma = BKE_object_material_get(ob, part->omat);
+      Material *ma = BKE_object_material_get_eval(ob, part->omat);
       float color[4] = {0.6f, 0.6f, 0.6f, part->draw_size};
       if (ma != NULL) {
         copy_v3_v3(color, &ma->r);
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
i

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list