Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_image.h2
-rw-r--r--source/blender/blenkernel/intern/image.cc27
-rw-r--r--source/blender/editors/object/object_bake.c67
-rw-r--r--source/blender/editors/object/object_bake_api.c138
-rw-r--r--source/blender/render/RE_bake.h7
-rw-r--r--source/blender/render/RE_texture_margin.h11
-rw-r--r--source/blender/render/intern/bake.c49
-rw-r--r--source/blender/render/intern/multires_bake.c193
-rw-r--r--source/blender/render/intern/texture_margin.cc38
9 files changed, 316 insertions, 216 deletions
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index fff3b2a8f89..42d0e66cf49 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -414,6 +414,8 @@ int BKE_image_get_tile_from_pos(struct Image *ima,
const float uv[2],
float r_uv[2],
float r_ofs[2]);
+void BKE_image_get_tile_uv(const struct Image *ima, const int tile_number, float r_uv[2]);
+
/**
* Return the tile_number for the closest UDIM tile.
*/
diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc
index 53ec148fd2d..dfa820519a5 100644
--- a/source/blender/blenkernel/intern/image.cc
+++ b/source/blender/blenkernel/intern/image.cc
@@ -829,10 +829,7 @@ ImageTile *BKE_image_get_tile_from_iuser(Image *ima, const ImageUser *iuser)
return BKE_image_get_tile(ima, image_get_tile_number_from_iuser(ima, iuser));
}
-int BKE_image_get_tile_from_pos(struct Image *ima,
- const float uv[2],
- float r_uv[2],
- float r_ofs[2])
+int BKE_image_get_tile_from_pos(Image *ima, const float uv[2], float r_uv[2], float r_ofs[2])
{
float local_ofs[2];
if (r_ofs == nullptr) {
@@ -860,6 +857,18 @@ int BKE_image_get_tile_from_pos(struct Image *ima,
return tile_number;
}
+void BKE_image_get_tile_uv(const Image *ima, const int tile_number, float r_uv[2])
+{
+ if (ima->source != IMA_SRC_TILED) {
+ zero_v2(r_uv);
+ }
+ else {
+ const int tile_index = tile_number - 1001;
+ r_uv[0] = static_cast<float>(tile_index % 10);
+ r_uv[1] = static_cast<float>(tile_index / 10);
+ }
+}
+
int BKE_image_find_nearest_tile(const Image *image, const float co[2])
{
const float co_floor[2] = {floorf(co[0]), floorf(co[1])};
@@ -868,17 +877,15 @@ int BKE_image_find_nearest_tile(const Image *image, const float co[2])
int tile_number_best = -1;
LISTBASE_FOREACH (const ImageTile *, tile, &image->tiles) {
- const int tile_index = tile->tile_number - 1001;
- /* Coordinates of the current tile. */
- const float tile_index_co[2] = {static_cast<float>(tile_index % 10),
- static_cast<float>(tile_index / 10)};
+ float uv_offset[2];
+ BKE_image_get_tile_uv(image, tile->tile_number, uv_offset);
- if (equals_v2v2(co_floor, tile_index_co)) {
+ if (equals_v2v2(co_floor, uv_offset)) {
return tile->tile_number;
}
/* Distance between co[2] and UDIM tile. */
- const float dist_sq = len_squared_v2v2(tile_index_co, co);
+ const float dist_sq = len_squared_v2v2(uv_offset, co);
if (dist_sq < dist_best_sq) {
dist_best_sq = dist_sq;
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index d469efbd0a1..1483c24ac70 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -172,28 +172,35 @@ static bool multiresbake_check(bContext *C, wmOperator *op)
ok = false;
}
else {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
+ iuser.tile = tile->tile_number;
- if (!ibuf) {
- BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
- ok = false;
- }
- else {
- if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
- ok = false;
- }
+ if (!ibuf) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Baking should happen to image with image buffer");
- if (ibuf->rect_float && !(ELEM(ibuf->channels, 0, 4))) {
ok = false;
}
-
- if (!ok) {
- BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type");
+ else {
+ if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
+ ok = false;
+ }
+
+ if (ibuf->rect_float && !(ELEM(ibuf->channels, 0, 4))) {
+ ok = false;
+ }
+
+ if (!ok) {
+ BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type");
+ }
}
- }
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
}
}
}
@@ -274,21 +281,27 @@ static void clear_single_image(Image *image, ClearFlag flag)
const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};
if ((image->id.tag & LIB_TAG_DOIT) == 0) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+ LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
+ iuser.tile = tile->tile_number;
- if (flag == CLEAR_TANGENT_NORMAL) {
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
- }
- else if (flag == CLEAR_DISPLACEMENT) {
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
- }
- else {
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
- }
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, NULL);
- image->id.tag |= LIB_TAG_DOIT;
+ if (flag == CLEAR_TANGENT_NORMAL) {
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
+ }
+ else if (flag == CLEAR_DISPLACEMENT) {
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
+ }
+ else {
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+ }
+
+ image->id.tag |= LIB_TAG_DOIT;
- BKE_image_release_ibuf(image, ibuf, NULL);
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
}
}
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 4ec8b7a05d5..a7379d7e492 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -19,6 +19,7 @@
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
+#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -165,6 +166,7 @@ static void bake_update_image(ScrArea *area, Image *image)
}
static bool write_internal_bake_pixels(Image *image,
+ const int image_tile_number,
BakePixel pixel_array[],
float *buffer,
const int width,
@@ -174,7 +176,8 @@ static bool write_internal_bake_pixels(Image *image,
const bool is_clear,
const bool is_noncolor,
Mesh const *mesh_eval,
- char const *uv_layer)
+ char const *uv_layer,
+ const float uv_offset[2])
{
ImBuf *ibuf;
void *lock;
@@ -182,7 +185,10 @@ static bool write_internal_bake_pixels(Image *image,
char *mask_buffer = NULL;
const size_t pixels_num = (size_t)width * (size_t)height;
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
+ iuser.tile = image_tile_number;
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
if (!ibuf) {
return false;
@@ -270,7 +276,7 @@ static bool write_internal_bake_pixels(Image *image,
/* margins */
if (margin > 0) {
- RE_bake_margin(ibuf, mask_buffer, margin, margin_type, mesh_eval, uv_layer);
+ RE_bake_margin(ibuf, mask_buffer, margin, margin_type, mesh_eval, uv_layer, uv_offset);
}
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
@@ -303,10 +309,8 @@ static void bake_targets_refresh(BakeTargets *targets)
if (ima) {
BKE_image_partial_update_mark_full_update(ima);
- LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
- BKE_image_free_gputextures(ima);
- DEG_id_tag_update(&ima->id, 0);
- }
+ BKE_image_free_gputextures(ima);
+ DEG_id_tag_update(&ima->id, 0);
}
}
}
@@ -321,7 +325,8 @@ static bool write_external_bake_pixels(const char *filepath,
ImageFormatData *im_format,
const bool is_noncolor,
Mesh const *mesh_eval,
- char const *uv_layer)
+ char const *uv_layer,
+ const float uv_offset[2])
{
ImBuf *ibuf = NULL;
bool ok = false;
@@ -378,7 +383,7 @@ static bool write_external_bake_pixels(const char *filepath,
mask_buffer = MEM_callocN(sizeof(char) * pixels_num, "Bake Mask");
RE_bake_mask_fill(pixel_array, pixels_num, mask_buffer);
- RE_bake_margin(ibuf, mask_buffer, margin, margin_type, mesh_eval, uv_layer);
+ RE_bake_margin(ibuf, mask_buffer, margin, margin_type, mesh_eval, uv_layer, uv_offset);
if (mask_buffer) {
MEM_freeN(mask_buffer);
@@ -467,7 +472,6 @@ static bool bake_object_check(ViewLayer *view_layer,
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)) {
@@ -482,21 +486,27 @@ static bool bake_object_check(ViewLayer *view_layer,
}
}
- void *lock;
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+ LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
+ iuser.tile = tile->tile_number;
- 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);
+ void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, &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;
+ BKE_image_release_ibuf(image, ibuf, lock);
+ return false;
+ }
}
}
else {
@@ -687,36 +697,35 @@ static bool bake_targets_init_image_textures(const BakeAPIRender *bkr,
}
}
- /* Over-allocate in case there is more materials than images. */
+ /* Allocate material mapping. */
targets->materials_num = materials_num;
- targets->images = MEM_callocN(sizeof(BakeImage) * targets->materials_num, "BakeTargets.images");
- targets->material_to_image = MEM_callocN(sizeof(int) * targets->materials_num,
+ targets->material_to_image = MEM_callocN(sizeof(Image *) * targets->materials_num,
"BakeTargets.material_to_image");
/* Error handling and tag (in case multiple materials share the same image). */
BKE_main_id_tag_idcode(bkr->main, ID_IM, LIB_TAG_DOIT, false);
+ targets->images = NULL;
+
for (int i = 0; i < materials_num; i++) {
Image *image;
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
- /* Some materials have no image, we just ignore those cases. */
- if (image == NULL) {
- targets->material_to_image[i] = -1;
- }
- else if (image->id.tag & LIB_TAG_DOIT) {
- for (int j = 0; j < i; j++) {
- if (targets->images[j].image == image) {
- targets->material_to_image[i] = j;
- break;
- }
+ targets->material_to_image[i] = image;
+
+ /* Some materials have no image, we just ignore those cases.
+ * Also setup each image only once. */
+ if (image && !(image->id.tag & LIB_TAG_DOIT)) {
+ LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+ /* Add bake image. */
+ targets->images = MEM_recallocN(targets->images,
+ sizeof(BakeImage) * (targets->images_num + 1));
+ targets->images[targets->images_num].image = image;
+ targets->images[targets->images_num].tile_number = tile->tile_number;
+ targets->images_num++;
}
- }
- else {
- targets->material_to_image[i] = targets->images_num;
- targets->images[targets->images_num].image = image;
+
image->id.tag |= LIB_TAG_DOIT;
- targets->images_num++;
}
}
@@ -735,13 +744,19 @@ static bool bake_targets_init_internal(const BakeAPIRender *bkr,
/* Saving to image datablocks. */
for (int i = 0; i < targets->images_num; i++) {
BakeImage *bk_image = &targets->images[i];
+
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
+ iuser.tile = bk_image->tile_number;
+
void *lock;
- ImBuf *ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(bk_image->image, &iuser, &lock);
if (ibuf) {
bk_image->width = ibuf->x;
bk_image->height = ibuf->y;
bk_image->offset = targets->pixels_num;
+ BKE_image_get_tile_uv(bk_image->image, bk_image->tile_number, bk_image->uv_offset);
targets->pixels_num += (size_t)ibuf->x * (size_t)ibuf->y;
}
@@ -768,6 +783,7 @@ static bool bake_targets_output_internal(const BakeAPIRender *bkr,
for (int i = 0; i < targets->images_num; i++) {
BakeImage *bk_image = &targets->images[i];
const bool ok = write_internal_bake_pixels(bk_image->image,
+ bk_image->tile_number,
pixel_array + bk_image->offset,
targets->result +
bk_image->offset * targets->channels_num,
@@ -778,7 +794,8 @@ static bool bake_targets_output_internal(const BakeAPIRender *bkr,
bkr->is_clear,
targets->is_noncolor,
mesh_eval,
- bkr->uv_layer);
+ bkr->uv_layer,
+ bk_image->uv_offset);
/* might be read by UI to set active image for display */
bake_update_image(bkr->area, bk_image->image);
@@ -815,7 +832,6 @@ static bool bake_targets_init_external(const BakeAPIRender *bkr,
bk_image->width = bkr->width;
bk_image->height = bkr->height;
bk_image->offset = targets->pixels_num;
- bk_image->image = NULL;
targets->pixels_num += (size_t)bkr->width * (size_t)bkr->height;
@@ -827,7 +843,7 @@ static bool bake_targets_init_external(const BakeAPIRender *bkr,
if (!bkr->is_split_materials) {
/* saving a single image */
for (int i = 0; i < targets->materials_num; i++) {
- targets->material_to_image[i] = 0;
+ targets->material_to_image[i] = targets->images[0].image;
}
}
@@ -865,25 +881,26 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr,
}
if (bkr->is_split_materials) {
- if (bk_image->image) {
- BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
+ if (ob_eval->mat[i]) {
+ BLI_path_suffix(name, FILE_MAX, ob_eval->mat[i]->id.name + 2, "_");
+ }
+ else if (mesh_eval->mat[i]) {
+ BLI_path_suffix(name, FILE_MAX, mesh_eval->mat[i]->id.name + 2, "_");
}
else {
- if (ob_eval->mat[i]) {
- BLI_path_suffix(name, FILE_MAX, ob_eval->mat[i]->id.name + 2, "_");
- }
- else if (mesh_eval->mat[i]) {
- BLI_path_suffix(name, FILE_MAX, mesh_eval->mat[i]->id.name + 2, "_");
- }
- else {
- /* if everything else fails, use the material index */
- char tmp[5];
- sprintf(tmp, "%d", i % 1000);
- BLI_path_suffix(name, FILE_MAX, tmp, "_");
- }
+ /* if everything else fails, use the material index */
+ char tmp[5];
+ sprintf(tmp, "%d", i % 1000);
+ BLI_path_suffix(name, FILE_MAX, tmp, "_");
}
}
+ if (bk_image->tile_number) {
+ char tmp[FILE_MAX];
+ SNPRINTF(tmp, "%d", bk_image->tile_number);
+ BLI_path_suffix(name, FILE_MAX, tmp, "_");
+ }
+
/* save it externally */
const bool ok = write_external_bake_pixels(name,
pixel_array + bk_image->offset,
@@ -896,7 +913,8 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr,
&bake->im_format,
targets->is_noncolor,
mesh_eval,
- bkr->uv_layer);
+ bkr->uv_layer,
+ bk_image->uv_offset);
if (!ok) {
BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
diff --git a/source/blender/render/RE_bake.h b/source/blender/render/RE_bake.h
index da48599fdf9..56c66df5925 100644
--- a/source/blender/render/RE_bake.h
+++ b/source/blender/render/RE_bake.h
@@ -19,6 +19,8 @@ extern "C" {
typedef struct BakeImage {
struct Image *image;
+ int tile_number;
+ float uv_offset[2];
int width;
int height;
size_t offset;
@@ -30,7 +32,7 @@ typedef struct BakeTargets {
int images_num;
/* Lookup table from Material number to BakeImage. */
- int *material_to_image;
+ struct Image **material_to_image;
int materials_num;
/* Pixel buffer to bake to. */
@@ -104,7 +106,8 @@ void RE_bake_margin(struct ImBuf *ibuf,
int margin,
char margin_type,
struct Mesh const *me,
- char const *uv_layer);
+ char const *uv_layer,
+ const float uv_offset[2]);
void RE_bake_normal_world_to_object(const BakePixel pixel_array[],
size_t pixels_num,
diff --git a/source/blender/render/RE_texture_margin.h b/source/blender/render/RE_texture_margin.h
index 85bd06b9940..0c91abeaddd 100644
--- a/source/blender/render/RE_texture_margin.h
+++ b/source/blender/render/RE_texture_margin.h
@@ -25,13 +25,18 @@ struct Mesh;
* \param me: the mesh to use the polygons of.
* \param uv_layer: The UV layer to use.
*/
-void RE_generate_texturemargin_adjacentfaces(
- struct ImBuf *ibuf, char *mask, const int margin, struct Mesh const *me, char const *uv_layer);
+void RE_generate_texturemargin_adjacentfaces(struct ImBuf *ibuf,
+ char *mask,
+ const int margin,
+ struct Mesh const *me,
+ char const *uv_layer,
+ const float uv_offset[2]);
void RE_generate_texturemargin_adjacentfaces_dm(struct ImBuf *ibuf,
char *mask,
const int margin,
- struct DerivedMesh *dm);
+ struct DerivedMesh *dm,
+ const float uv_offset[2]);
#ifdef __cplusplus
}
diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c
index 69235fb6cb1..5953c0f0f8f 100644
--- a/source/blender/render/intern/bake.c
+++ b/source/blender/render/intern/bake.c
@@ -146,12 +146,13 @@ void RE_bake_margin(ImBuf *ibuf,
const int margin,
const char margin_type,
Mesh const *me,
- char const *uv_layer)
+ char const *uv_layer,
+ const float uv_offset[2])
{
/* margin */
switch (margin_type) {
case R_BAKE_ADJACENT_FACES:
- RE_generate_texturemargin_adjacentfaces(ibuf, mask, margin, me, uv_layer);
+ RE_generate_texturemargin_adjacentfaces(ibuf, mask, margin, me, uv_layer, uv_offset);
break;
default:
/* fall through */
@@ -746,30 +747,36 @@ void RE_bake_pixels_populate(Mesh *me,
for (int i = 0; i < tottri; i++) {
const MLoopTri *lt = &looptri[i];
const MPoly *mp = &me->mpoly[lt->poly];
- float vec[3][2];
- int mat_nr = mp->mat_nr;
- int image_id = targets->material_to_image[mat_nr];
- if (image_id < 0) {
- continue;
- }
-
- bd.bk_image = &targets->images[image_id];
bd.primitive_id = i;
- for (int a = 0; a < 3; a++) {
- const float *uv = mloopuv[lt->tri[a]].uv;
+ /* Find images matching this material. */
+ Image *image = targets->material_to_image[mp->mat_nr];
+ for (int image_id = 0; image_id < targets->images_num; image_id++) {
+ BakeImage *bk_image = &targets->images[image_id];
+ if (bk_image->image != image) {
+ continue;
+ }
- /* NOTE(campbell): workaround for pixel aligned UVs which are common and can screw up our
- * intersection tests where a pixel gets in between 2 faces or the middle of a quad,
- * camera aligned quads also have this problem but they are less common.
- * Add a small offset to the UVs, fixes bug T18685. */
- vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f);
- vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f);
- }
+ /* Compute triangle vertex UV coordinates. */
+ float vec[3][2];
+ for (int a = 0; a < 3; a++) {
+ const float *uv = mloopuv[lt->tri[a]].uv;
+
+ /* NOTE(campbell): workaround for pixel aligned UVs which are common and can screw up our
+ * intersection tests where a pixel gets in between 2 faces or the middle of a quad,
+ * camera aligned quads also have this problem but they are less common.
+ * Add a small offset to the UVs, fixes bug T18685. */
+ vec[a][0] = (uv[0] - bk_image->uv_offset[0]) * (float)bk_image->width - (0.5f + 0.001f);
+ vec[a][1] = (uv[1] - bk_image->uv_offset[1]) * (float)bk_image->height - (0.5f + 0.002f);
+ }
- bake_differentials(&bd, vec[0], vec[1], vec[2]);
- zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
+ /* Rasterize triangle. */
+ bd.bk_image = bk_image;
+ bake_differentials(&bd, vec[0], vec[1], vec[2]);
+ zspan_scanconvert(
+ &bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
+ }
}
for (int i = 0; i < targets->images_num; i++) {
diff --git a/source/blender/render/intern/multires_bake.c b/source/blender/render/intern/multires_bake.c
index 33d961c027d..f93397eedab 100644
--- a/source/blender/render/intern/multires_bake.c
+++ b/source/blender/render/intern/multires_bake.c
@@ -51,7 +51,7 @@ typedef void (*MPassKnownData)(DerivedMesh *lores_dm,
const int x,
const int y);
-typedef void *(*MInitBakeData)(MultiresBakeRender *bkr, Image *ima);
+typedef void *(*MInitBakeData)(MultiresBakeRender *bkr, ImBuf *ibuf);
typedef void (*MFreeBakeData)(void *bake_data);
typedef struct MultiresBakeResult {
@@ -64,6 +64,7 @@ typedef struct {
MPoly *mpoly;
MLoop *mloop;
MLoopUV *mloopuv;
+ float uv_offset[2];
const MLoopTri *mlooptri;
float *pvtangent;
const float (*precomputed_normals)[3];
@@ -91,7 +92,6 @@ typedef struct {
typedef struct {
float *heights;
- Image *ima;
DerivedMesh *ssdm;
const int *orig_index_mp_to_orig;
} MHeightBakeData;
@@ -148,7 +148,8 @@ static void init_bake_rast(MBakeRast *bake_rast,
static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
{
- const float st[2] = {(x + 0.5f) / data->w, (y + 0.5f) / data->h};
+ const float st[2] = {(x + 0.5f) / data->w + data->uv_offset[0],
+ (y + 0.5f) / data->h + data->uv_offset[1]};
const float *st0, *st1, *st2;
const float *tang0, *tang1, *tang2;
float no0[3], no1[3], no2[3];
@@ -395,8 +396,12 @@ static void *do_multires_bake_thread(void *data_v)
data->tri_index = tri_index;
- bake_rasterize(
- bake_rast, mloopuv[lt->tri[0]].uv, mloopuv[lt->tri[1]].uv, mloopuv[lt->tri[2]].uv);
+ float uv[3][2];
+ sub_v2_v2v2(uv[0], mloopuv[lt->tri[0]].uv, data->uv_offset);
+ sub_v2_v2v2(uv[1], mloopuv[lt->tri[1]].uv, data->uv_offset);
+ sub_v2_v2v2(uv[2], mloopuv[lt->tri[2]].uv, data->uv_offset);
+
+ bake_rasterize(bake_rast, uv[0], uv[1], uv[2]);
/* tag image buffer for refresh */
if (data->ibuf->rect_float) {
@@ -447,6 +452,8 @@ static void init_ccgdm_arrays(DerivedMesh *dm)
static void do_multires_bake(MultiresBakeRender *bkr,
Image *ima,
+ ImageTile *tile,
+ ImBuf *ibuf,
bool require_tangent,
MPassKnownData passKnownData,
MInitBakeData initBakeData,
@@ -462,7 +469,6 @@ static void do_multires_bake(MultiresBakeRender *bkr,
MultiresBakeThread *handles;
MultiresBakeQueue queue;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
MVert *mvert = dm->getVertArray(dm);
MPoly *mpoly = dm->getPolyArray(dm);
MLoop *mloop = dm->getLoopArray(dm);
@@ -511,7 +517,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
/* all threads shares the same custom bake data */
if (initBakeData) {
- bake_data = initBakeData(bkr, ima);
+ bake_data = initBakeData(bkr, ibuf);
}
if (tot_thread > 1) {
@@ -539,6 +545,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
handle->data.mvert = mvert;
handle->data.vert_normals = vert_normals;
handle->data.mloopuv = mloopuv;
+ BKE_image_get_tile_uv(ima, tile->tile_number, handle->data.uv_offset);
handle->data.mlooptri = mlooptri;
handle->data.mloop = mloop;
handle->data.pvtangent = pvtangent;
@@ -590,8 +597,6 @@ static void do_multires_bake(MultiresBakeRender *bkr,
MEM_freeN(handles);
BKE_id_free(NULL, temp_mesh);
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
}
}
@@ -758,10 +763,9 @@ static void interp_barycentric_mlooptri(DerivedMesh *dm,
/* **************** Displacement Baker **************** */
-static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
+static void *init_heights_data(MultiresBakeRender *bkr, ImBuf *ibuf)
{
MHeightBakeData *height_data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
DerivedMesh *lodm = bkr->lores_dm;
BakeImBufuserData *userdata = ibuf->userdata;
@@ -772,7 +776,6 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData");
- height_data->ima = ima;
height_data->heights = userdata->displacement_buffer;
if (!bkr->use_lores_mesh) {
@@ -794,8 +797,6 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
return (void *)height_data;
}
@@ -903,7 +904,7 @@ static void apply_heights_callback(DerivedMesh *lores_dm,
/* **************** Normal Maps Baker **************** */
-static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
+static void *init_normal_data(MultiresBakeRender *bkr, ImBuf *UNUSED(ibuf))
{
MNormalBakeData *normal_data;
DerivedMesh *lodm = bkr->lores_dm;
@@ -1099,7 +1100,7 @@ static void create_ao_raytree(MultiresBakeRender *bkr, MAOBakeData *ao_data)
RE_rayobject_done(raytree);
}
-static void *init_ao_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
+static void *init_ao_data(MultiresBakeRender *bkr, ImBuf *UNUSED(ibuf))
{
MAOBakeData *ao_data;
DerivedMesh *lodm = bkr->lores_dm;
@@ -1313,8 +1314,12 @@ static void apply_ao_callback(DerivedMesh *lores_dm,
/* ******$***************** Post processing ************************* */
-static void bake_ibuf_filter(
- ImBuf *ibuf, char *mask, const int margin, const char margin_type, DerivedMesh *dm)
+static void bake_ibuf_filter(ImBuf *ibuf,
+ char *mask,
+ const int margin,
+ const char margin_type,
+ DerivedMesh *dm,
+ const float uv_offset[2])
{
/* must check before filtering */
const bool is_new_alpha = (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf);
@@ -1322,7 +1327,7 @@ static void bake_ibuf_filter(
if (margin) {
switch (margin_type) {
case R_BAKE_ADJACENT_FACES:
- RE_generate_texturemargin_adjacentfaces_dm(ibuf, mask, margin, dm);
+ RE_generate_texturemargin_adjacentfaces_dm(ibuf, mask, margin, dm, uv_offset);
break;
default:
/* fall through */
@@ -1427,38 +1432,54 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
for (link = bkr->image.first; link; link = link->next) {
Image *ima = (Image *)link->data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ibuf->x > 0 && ibuf->y > 0) {
- BakeImBufuserData *userdata = MEM_callocN(sizeof(BakeImBufuserData),
- "MultiresBake userdata");
- userdata->mask_buffer = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask");
- ibuf->userdata = userdata;
-
- switch (bkr->mode) {
- case RE_BAKE_NORMALS:
- do_multires_bake(
- bkr, ima, true, apply_tangmat_callback, init_normal_data, free_normal_data, result);
- break;
- case RE_BAKE_DISPLACEMENT:
- do_multires_bake(bkr,
- ima,
- false,
- apply_heights_callback,
- init_heights_data,
- free_heights_data,
- result);
- break;
-/* TODO: restore ambient occlusion baking support. */
+
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
+ iuser.tile = tile->tile_number;
+
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+
+ if (ibuf->x > 0 && ibuf->y > 0) {
+ BakeImBufuserData *userdata = MEM_callocN(sizeof(BakeImBufuserData),
+ "MultiresBake userdata");
+ userdata->mask_buffer = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask");
+ ibuf->userdata = userdata;
+
+ switch (bkr->mode) {
+ case RE_BAKE_NORMALS:
+ do_multires_bake(bkr,
+ ima,
+ tile,
+ ibuf,
+ true,
+ apply_tangmat_callback,
+ init_normal_data,
+ free_normal_data,
+ result);
+ break;
+ case RE_BAKE_DISPLACEMENT:
+ do_multires_bake(bkr,
+ ima,
+ tile,
+ ibuf,
+ false,
+ apply_heights_callback,
+ init_heights_data,
+ free_heights_data,
+ result);
+ break;
+ /* TODO: restore ambient occlusion baking support. */
#if 0
- case RE_BAKE_AO:
- do_multires_bake(bkr, ima, false, apply_ao_callback, init_ao_data, free_ao_data, result);
- break;
+ case RE_BAKE_AO:
+ do_multires_bake(bkr, ima, tile, ibuf, false, apply_ao_callback, init_ao_data, free_ao_data, result);
+ break;
#endif
+ }
}
- }
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
ima->id.tag |= LIB_TAG_DOIT;
}
@@ -1471,48 +1492,62 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
for (link = bkr->image.first; link; link = link->next) {
Image *ima = (Image *)link->data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- BakeImBufuserData *userdata = (BakeImBufuserData *)ibuf->userdata;
- if (ibuf->x <= 0 || ibuf->y <= 0) {
- continue;
- }
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
+ iuser.tile = tile->tile_number;
- if (use_displacement_buffer) {
- bake_ibuf_normalize_displacement(ibuf,
- userdata->displacement_buffer,
- userdata->mask_buffer,
- result->height_min,
- result->height_max);
- }
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ BakeImBufuserData *userdata = (BakeImBufuserData *)ibuf->userdata;
- bake_ibuf_filter(
- ibuf, userdata->mask_buffer, bkr->bake_margin, bkr->bake_margin_type, bkr->lores_dm);
+ if (ibuf->x <= 0 || ibuf->y <= 0) {
+ continue;
+ }
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- BKE_image_mark_dirty(ima, ibuf);
+ if (use_displacement_buffer) {
+ bake_ibuf_normalize_displacement(ibuf,
+ userdata->displacement_buffer,
+ userdata->mask_buffer,
+ result->height_min,
+ result->height_max);
+ }
- if (ibuf->rect_float) {
- ibuf->userflags |= IB_RECT_INVALID;
- }
+ float uv_offset[2];
+ BKE_image_get_tile_uv(ima, tile->tile_number, uv_offset);
- if (ibuf->mipmap[0]) {
- ibuf->userflags |= IB_MIPMAP_INVALID;
- imb_freemipmapImBuf(ibuf);
- }
+ bake_ibuf_filter(ibuf,
+ userdata->mask_buffer,
+ bkr->bake_margin,
+ bkr->bake_margin_type,
+ bkr->lores_dm,
+ uv_offset);
+
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ BKE_image_mark_dirty(ima, ibuf);
- if (ibuf->userdata) {
- if (userdata->displacement_buffer) {
- MEM_freeN(userdata->displacement_buffer);
+ if (ibuf->rect_float) {
+ ibuf->userflags |= IB_RECT_INVALID;
}
- MEM_freeN(userdata->mask_buffer);
- MEM_freeN(userdata);
- ibuf->userdata = NULL;
- }
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID;
+ imb_freemipmapImBuf(ibuf);
+ }
+
+ if (ibuf->userdata) {
+ if (userdata->displacement_buffer) {
+ MEM_freeN(userdata->displacement_buffer);
+ }
- BKE_image_release_ibuf(ima, ibuf, NULL);
- DEG_id_tag_update(&ima->id, 0);
+ MEM_freeN(userdata->mask_buffer);
+ MEM_freeN(userdata);
+ ibuf->userdata = NULL;
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ DEG_id_tag_update(&ima->id, 0);
+ }
}
}
diff --git a/source/blender/render/intern/texture_margin.cc b/source/blender/render/intern/texture_margin.cc
index d01c0dbea71..2d68148a86a 100644
--- a/source/blender/render/intern/texture_margin.cc
+++ b/source/blender/render/intern/texture_margin.cc
@@ -46,6 +46,7 @@ class TextureMarginMap {
Vector<int> loop_to_poly_map_;
int w_, h_;
+ float uv_offset_[2];
Vector<uint32_t> pixel_data_;
ZSpan zspan_;
uint32_t value_to_store_;
@@ -61,6 +62,7 @@ class TextureMarginMap {
public:
TextureMarginMap(size_t w,
size_t h,
+ const float uv_offset[2],
MPoly const *mpoly,
MLoop const *mloop,
MLoopUV const *mloopuv,
@@ -76,6 +78,8 @@ class TextureMarginMap {
totloop_(totloop),
totedge_(totedge)
{
+ copy_v2_v2(uv_offset_, uv_offset);
+
pixel_data_.resize(w_ * h_, 0xFFFFFFFF);
zbuf_alloc_span(&zspan_, w_, h_);
@@ -277,8 +281,8 @@ class TextureMarginMap {
float2 uv_to_xy(MLoopUV const &mloopuv) const
{
float2 ret;
- ret.x = ((mloopuv.uv[0] * w_) - (0.5f + 0.001f));
- ret.y = ((mloopuv.uv[1] * h_) - (0.5f + 0.001f));
+ ret.x = (((mloopuv.uv[0] - uv_offset_[0]) * w_) - (0.5f + 0.001f));
+ ret.y = (((mloopuv.uv[1] - uv_offset_[1]) * h_) - (0.5f + 0.001f));
return ret;
}
@@ -482,7 +486,8 @@ static void generate_margin(ImBuf *ibuf,
const int margin,
const Mesh *me,
DerivedMesh *dm,
- char const *uv_layer)
+ char const *uv_layer,
+ const float uv_offset[2])
{
MPoly *mpoly;
@@ -531,7 +536,8 @@ static void generate_margin(ImBuf *ibuf,
tottri = dm->getNumLoopTri(dm);
}
- TextureMarginMap map(ibuf->x, ibuf->y, mpoly, mloop, mloopuv, totpoly, totloop, totedge);
+ TextureMarginMap map(
+ ibuf->x, ibuf->y, uv_offset, mpoly, mloop, mloopuv, totpoly, totloop, totedge);
bool draw_new_mask = false;
/* Now the map contains 3 sorts of values: 0xFFFFFFFF for empty pixels, `0x80000000 + polyindex`
@@ -555,8 +561,8 @@ static void generate_margin(ImBuf *ibuf,
* intersection tests where a pixel gets in between 2 faces or the middle of a quad,
* camera aligned quads also have this problem but they are less common.
* Add a small offset to the UVs, fixes bug T18685. */
- vec[a][0] = uv[0] * (float)ibuf->x - (0.5f + 0.001f);
- vec[a][1] = uv[1] * (float)ibuf->y - (0.5f + 0.002f);
+ vec[a][0] = (uv[0] - uv_offset[0]) * (float)ibuf->x - (0.5f + 0.001f);
+ vec[a][1] = (uv[1] - uv_offset[1]) * (float)ibuf->y - (0.5f + 0.002f);
}
/* NOTE: we need the top bit for the dijkstra distance map. */
@@ -592,16 +598,20 @@ static void generate_margin(ImBuf *ibuf,
} // namespace blender::render::texturemargin
-void RE_generate_texturemargin_adjacentfaces(
- ImBuf *ibuf, char *mask, const int margin, const Mesh *me, char const *uv_layer)
+void RE_generate_texturemargin_adjacentfaces(ImBuf *ibuf,
+ char *mask,
+ const int margin,
+ const Mesh *me,
+ char const *uv_layer,
+ const float uv_offset[2])
{
- blender::render::texturemargin::generate_margin(ibuf, mask, margin, me, nullptr, uv_layer);
+ blender::render::texturemargin::generate_margin(
+ ibuf, mask, margin, me, nullptr, uv_layer, uv_offset);
}
-void RE_generate_texturemargin_adjacentfaces_dm(ImBuf *ibuf,
- char *mask,
- const int margin,
- DerivedMesh *dm)
+void RE_generate_texturemargin_adjacentfaces_dm(
+ ImBuf *ibuf, char *mask, const int margin, DerivedMesh *dm, const float uv_offset[2])
{
- blender::render::texturemargin::generate_margin(ibuf, mask, margin, nullptr, dm, nullptr);
+ blender::render::texturemargin::generate_margin(
+ ibuf, mask, margin, nullptr, dm, nullptr, uv_offset);
}