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:
authorBrecht Van Lommel <brecht@blender.org>2022-04-22 21:44:49 +0300
committerBrecht Van Lommel <brecht@blender.org>2022-04-23 00:15:45 +0300
commit6787cc13d4efef19eb708e1912356f8c1d4d2e01 (patch)
tree7281d706ec6aad566306d12632cd6d7d6f8f462a /source/blender/render
parentbdc537e0a7b4b62af049dd4d508d5b08a4fa8b3b (diff)
Bake: add UDIM tile baking support
Works for both Cycles and multires bake. Triangles are baked to multiple UDIM images if they span across them, though such UV layouts are generally discouraged as there is no filtering across UDIM tiles. The bake margin currently only works within UDIM tiles. For the extend method this is logical, for the adjacent faces method it may be useful to support copying pixels from other UDIM tiles, though this seems somewhat complicated. Fixes T95190 Ref T72390
Diffstat (limited to 'source/blender/render')
-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
5 files changed, 179 insertions, 119 deletions
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);
}