From 1fbb1d8cf6ea9badd3361e4c533625f569d14734 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 9 Nov 2022 16:59:16 +0100 Subject: [PATCH 1/2] Fix T102214: inconsistenty between bake and render with invalid material index When the materal slot index on mesh faces exceeds the number of slots, rendering would use the last material slot while other operations like baking would fall back to the default material. Now consistently use the last material slot in such cases, since preserving backwards compatibility for rendering seems most important. And if there is one material slot, it's more useful to use that one rather than falling back to the default material. --- source/blender/blenkernel/intern/material.c | 47 +++++++++------------ source/blender/render/intern/bake.c | 6 ++- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 59530a6d6a6..796ed4f8316 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -653,38 +653,29 @@ Material **BKE_object_material_get_p(Object *ob, short act) /* if object cannot have material, (totcolp == NULL) */ totcolp = BKE_object_material_len_p(ob); - if (totcolp == NULL || ob->totcol == 0) { + if (totcolp == NULL || *totcolp == 0) { return NULL; } - /* return NULL for invalid 'act', can happen for mesh face indices */ - if (act > ob->totcol) { - return NULL; - } - if (act <= 0) { - if (act < 0) { - CLOG_ERROR(&LOG, "Negative material index!"); - } - return NULL; + /* Clamp to number of slots if index is out of range, same convention as used for rendering. */ + const int slot_index = clamp_i(act - 1, 0, *totcolp - 1); + + /* Fix inconsistency which may happen when library linked data reduces the number of + * slots but object was not updated. Ideally should be fixed elsewhere. */ + if (*totcolp < ob->totcol) { + ob->totcol = *totcolp; } - if (ob->matbits && ob->matbits[act - 1]) { /* in object */ - ma_p = &ob->mat[act - 1]; + if (slot_index < ob->totcol && ob->matbits && ob->matbits[slot_index]) { + /* Use object material slot. */ + ma_p = &ob->mat[slot_index]; } - else { /* in data */ - - /* check for inconsistency */ - if (*totcolp < ob->totcol) { - ob->totcol = *totcolp; - } - if (act > ob->totcol) { - act = ob->totcol; - } - + else { + /* Use data material slot. */ matarar = BKE_object_material_array_p(ob); if (matarar && *matarar) { - ma_p = &(*matarar)[act - 1]; + ma_p = &(*matarar)[slot_index]; } else { ma_p = NULL; @@ -717,17 +708,17 @@ static ID *get_evaluated_object_data_with_materials(Object *ob) 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) { + + if (tot_slots_data == 0) { return NULL; } + + /* Clamp to number of slots if index is out of range, same convention as used for rendering. */ + const int slot_index = clamp_i(act - 1, 0, tot_slots_data - 1); const int tot_slots_object = ob->totcol; Material ***materials_data_ptr = BKE_id_material_array_p(data); diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c index 9b56e18bb26..d9f7f9fa0af 100644 --- a/source/blender/render/intern/bake.c +++ b/source/blender/render/intern/bake.c @@ -747,6 +747,7 @@ void RE_bake_pixels_populate(Mesh *me, BKE_mesh_recalc_looptri(loops, polys, verts, me->totloop, me->totpoly, looptri); const int *material_indices = BKE_mesh_material_indices(me); + const int materials_num = targets->materials_num; for (int i = 0; i < tottri; i++) { const MLoopTri *lt = &looptri[i]; @@ -754,7 +755,10 @@ void RE_bake_pixels_populate(Mesh *me, bd.primitive_id = i; /* Find images matching this material. */ - Image *image = targets->material_to_image[material_indices ? material_indices[lt->poly] : 0]; + const int material_index = (material_indices && materials_num) ? + clamp_i(material_indices[lt->poly], 0, materials_num - 1) : + 0; + Image *image = targets->material_to_image[material_index]; for (int image_id = 0; image_id < targets->images_num; image_id++) { BakeImage *bk_image = &targets->images[image_id]; if (bk_image->image != image) { From 8232cf5287445d21b7d6effb3f0e1ffb6df09adf Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 9 Nov 2022 19:35:54 +0100 Subject: [PATCH 2/2] Fix T101669: Cycles artifacts in bump map baking After barycentric convention changes, the differentials used for bump mapping were wrong leading to artifacts with long thin triangles. --- intern/cycles/kernel/integrator/init_from_bake.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/intern/cycles/kernel/integrator/init_from_bake.h b/intern/cycles/kernel/integrator/init_from_bake.h index 667ba949760..cc3fbe3fe39 100644 --- a/intern/cycles/kernel/integrator/init_from_bake.h +++ b/intern/cycles/kernel/integrator/init_from_bake.h @@ -156,6 +156,13 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg, u = v; v = 1.0f - tmp - v; + const float tmpdx = dudx; + const float tmpdy = dudy; + dudx = dvdx; + dudy = dvdy; + dvdx = -tmpdx - dvdx; + dvdy = -tmpdy - dvdy; + /* Position and normal on triangle. */ const int object = kernel_data.bake.object_index; float3 P, Ng;