Bake-API: reduce memory footprint when baking more than one object (Fix T41092)
Combine all the highpoly pixel arrays into a single array with a lookup object_id for each of the highpoly objects. Note: This changes the Bake API, external engines should refer to the bake_api.c for the latest API. Many thanks for Sergey Sharybin for the complete review, changes suggestion and feedback. (you rock!) Reviewers: sergey Subscribers: pildanovak, marcclintdion, monio, metalliandy, brecht Maniphest Tasks: T41092 Differential Revision: https://developer.blender.org/D772
This commit is contained in:
parent
45e929dc12
commit
394c5318c6
Notes:
blender-bot
2023-02-14 10:21:15 +01:00
Referenced by issue #41092, Very high memory usage for Cycles baking compared to ordinary renders
|
@ -65,8 +65,8 @@ class CyclesRender(bpy.types.RenderEngine):
|
|||
def render(self, scene):
|
||||
engine.render(self)
|
||||
|
||||
def bake(self, scene, obj, pass_type, pixel_array, num_pixels, depth, result):
|
||||
engine.bake(self, obj, pass_type, pixel_array, num_pixels, depth, result)
|
||||
def bake(self, scene, obj, pass_type, object_id, pixel_array, num_pixels, depth, result):
|
||||
engine.bake(self, obj, pass_type, object_id, pixel_array, num_pixels, depth, result)
|
||||
|
||||
# viewport render
|
||||
def view_update(self, context):
|
||||
|
|
|
@ -59,11 +59,11 @@ def render(engine):
|
|||
_cycles.render(engine.session)
|
||||
|
||||
|
||||
def bake(engine, obj, pass_type, pixel_array, num_pixels, depth, result):
|
||||
def bake(engine, obj, pass_type, object_id, pixel_array, num_pixels, depth, result):
|
||||
import _cycles
|
||||
session = getattr(engine, "session", None)
|
||||
if session is not None:
|
||||
_cycles.bake(engine.session, obj.as_pointer(), pass_type, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
|
||||
_cycles.bake(engine.session, obj.as_pointer(), pass_type, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
|
||||
|
||||
|
||||
def reset(engine, data, scene):
|
||||
|
|
|
@ -189,9 +189,9 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
|
|||
PyObject *pysession, *pyobject;
|
||||
PyObject *pypixel_array, *pyresult;
|
||||
const char *pass_type;
|
||||
int num_pixels, depth;
|
||||
int num_pixels, depth, object_id;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "OOsOiiO", &pysession, &pyobject, &pass_type, &pypixel_array, &num_pixels, &depth, &pyresult))
|
||||
if(!PyArg_ParseTuple(args, "OOsiOiiO", &pysession, &pyobject, &pass_type, &object_id, &pypixel_array, &num_pixels, &depth, &pyresult))
|
||||
return NULL;
|
||||
|
||||
BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
|
||||
|
@ -208,7 +208,7 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
|
|||
|
||||
python_thread_state_save(&session->python_thread_state);
|
||||
|
||||
session->bake(b_object, pass_type, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result);
|
||||
session->bake(b_object, pass_type, object_id, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result);
|
||||
|
||||
python_thread_state_restore(&session->python_thread_state);
|
||||
|
||||
|
|
|
@ -511,18 +511,22 @@ void BlenderSession::render()
|
|||
sync = NULL;
|
||||
}
|
||||
|
||||
static void populate_bake_data(BakeData *data, BL::BakePixel pixel_array, const int num_pixels)
|
||||
static void populate_bake_data(BakeData *data, const int object_id, BL::BakePixel pixel_array, const int num_pixels)
|
||||
{
|
||||
BL::BakePixel bp = pixel_array;
|
||||
|
||||
int i;
|
||||
for(i=0; i < num_pixels; i++) {
|
||||
data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
|
||||
if(bp.object_id() == object_id) {
|
||||
data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
|
||||
} else {
|
||||
data->set_null(i);
|
||||
}
|
||||
bp = bp.next();
|
||||
}
|
||||
}
|
||||
|
||||
void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int /*depth*/, float result[])
|
||||
void BlenderSession::bake(BL::Object b_object, const string& pass_type, const int object_id, BL::BakePixel pixel_array, const size_t num_pixels, const int /*depth*/, float result[])
|
||||
{
|
||||
ShaderEvalType shader_type = get_shader_type(pass_type);
|
||||
size_t object_index = OBJECT_NONE;
|
||||
|
@ -578,7 +582,7 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::Bake
|
|||
|
||||
BakeData *bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
|
||||
|
||||
populate_bake_data(bake_data, pixel_array, num_pixels);
|
||||
populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
|
||||
|
||||
/* set number of samples */
|
||||
session->tile_manager.set_samples(session_params.samples);
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
/* offline render */
|
||||
void render();
|
||||
|
||||
void bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float pixels[]);
|
||||
void bake(BL::Object b_object, const string& pass_type, const int object_id, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float pixels[]);
|
||||
|
||||
void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
|
||||
void write_render_tile(RenderTile& rtile);
|
||||
|
|
|
@ -55,6 +55,11 @@ void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float d
|
|||
m_dvdy[i] = dvdy;
|
||||
}
|
||||
|
||||
void BakeData::set_null(int i)
|
||||
{
|
||||
m_primitive[i] = -1;
|
||||
}
|
||||
|
||||
int BakeData::object()
|
||||
{
|
||||
return m_object;
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
~BakeData();
|
||||
|
||||
void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
|
||||
void set_null(int i);
|
||||
int object();
|
||||
size_t size();
|
||||
uint4 data(int i);
|
||||
|
|
|
@ -574,6 +574,7 @@ static int bake(
|
|||
float *result = NULL;
|
||||
|
||||
BakePixel *pixel_array_low = NULL;
|
||||
BakePixel *pixel_array_high = NULL;
|
||||
|
||||
const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
|
||||
const bool is_noncolor = is_noncolor_pass(pass_type);
|
||||
|
@ -682,6 +683,7 @@ static int bake(
|
|||
}
|
||||
|
||||
pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
|
||||
pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
|
||||
result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
|
||||
|
||||
/* get the mesh as it arrives in the renderer */
|
||||
|
@ -755,8 +757,6 @@ static int bake(
|
|||
/* initialize highpoly_data */
|
||||
highpoly[i].ob = ob_iter;
|
||||
highpoly[i].restrict_flag = ob_iter->restrictflag;
|
||||
highpoly[i].pixel_array = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
|
||||
|
||||
|
||||
/* triangulating so BVH returns the primitive_id that will be used for rendering */
|
||||
highpoly[i].tri_mod = ED_object_modifier_add(
|
||||
|
@ -790,7 +790,7 @@ static int bake(
|
|||
|
||||
/* populate the pixel arrays with the corresponding face data for each high poly object */
|
||||
if (!RE_bake_pixels_populate_from_objects(
|
||||
me_low, pixel_array_low, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
|
||||
me_low, pixel_array_low, pixel_array_high, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
|
||||
cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage))
|
||||
{
|
||||
BKE_report(reports, RPT_ERROR, "Error handling selected objects");
|
||||
|
@ -799,8 +799,8 @@ static int bake(
|
|||
|
||||
/* the baking itself */
|
||||
for (i = 0; i < tot_highpoly; i++) {
|
||||
ok = RE_bake_engine(re, highpoly[i].ob, highpoly[i].pixel_array, num_pixels,
|
||||
depth, pass_type, result);
|
||||
ok = RE_bake_engine(re, highpoly[i].ob, i, pixel_array_high,
|
||||
num_pixels, depth, pass_type, result);
|
||||
if (!ok) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
|
||||
goto cage_cleanup;
|
||||
|
@ -826,7 +826,7 @@ cage_cleanup:
|
|||
ob_low->restrictflag &= ~OB_RESTRICT_RENDER;
|
||||
|
||||
if (RE_bake_has_engine(re)) {
|
||||
ok = RE_bake_engine(re, ob_low, pixel_array_low, num_pixels, depth, pass_type, result);
|
||||
ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, result);
|
||||
}
|
||||
else {
|
||||
BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
|
||||
|
@ -990,9 +990,6 @@ cleanup:
|
|||
for (i = 0; i < tot_highpoly; i++) {
|
||||
highpoly[i].ob->restrictflag = highpoly[i].restrict_flag;
|
||||
|
||||
if (highpoly[i].pixel_array)
|
||||
MEM_freeN(highpoly[i].pixel_array);
|
||||
|
||||
if (highpoly[i].tri_mod)
|
||||
ED_object_modifier_remove(reports, bmain, highpoly[i].ob, highpoly[i].tri_mod);
|
||||
|
||||
|
@ -1010,6 +1007,9 @@ cleanup:
|
|||
if (pixel_array_low)
|
||||
MEM_freeN(pixel_array_low);
|
||||
|
||||
if (pixel_array_high)
|
||||
MEM_freeN(pixel_array_high);
|
||||
|
||||
if (bake_images.data)
|
||||
MEM_freeN(bake_images.data);
|
||||
|
||||
|
|
|
@ -154,8 +154,10 @@ static void engine_render(RenderEngine *engine, struct Scene *scene)
|
|||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
static void engine_bake(RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type,
|
||||
const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result)
|
||||
static void engine_bake(RenderEngine *engine, struct Scene *scene,
|
||||
struct Object *object, const int pass_type,
|
||||
const int object_id, const struct BakePixel *pixel_array,
|
||||
const int num_pixels, const int depth, void *result)
|
||||
{
|
||||
extern FunctionRNA rna_RenderEngine_bake_func;
|
||||
PointerRNA ptr;
|
||||
|
@ -169,6 +171,7 @@ static void engine_bake(RenderEngine *engine, struct Scene *scene, struct Object
|
|||
RNA_parameter_set_lookup(&list, "scene", &scene);
|
||||
RNA_parameter_set_lookup(&list, "object", &object);
|
||||
RNA_parameter_set_lookup(&list, "pass_type", &pass_type);
|
||||
RNA_parameter_set_lookup(&list, "object_id", &object_id);
|
||||
RNA_parameter_set_lookup(&list, "pixel_array", &pixel_array);
|
||||
RNA_parameter_set_lookup(&list, "num_pixels", &num_pixels);
|
||||
RNA_parameter_set_lookup(&list, "depth", &depth);
|
||||
|
@ -423,6 +426,8 @@ static void rna_def_render_engine(BlenderRNA *brna)
|
|||
RNA_def_property_flag(prop, PROP_REQUIRED);
|
||||
prop = RNA_def_enum(func, "pass_type", render_pass_type_items, 0, "Pass", "Pass to bake");
|
||||
RNA_def_property_flag(prop, PROP_REQUIRED);
|
||||
prop = RNA_def_int(func, "object_id", 0, 0, INT_MAX, "Object Id", "Id of the current object being baked in relation to the others", 0, INT_MAX);
|
||||
RNA_def_property_flag(prop, PROP_REQUIRED);
|
||||
prop = RNA_def_pointer(func, "pixel_array", "BakePixel", "", "");
|
||||
RNA_def_property_flag(prop, PROP_REQUIRED);
|
||||
prop = RNA_def_int(func, "num_pixels", 0, 0, INT_MAX, "Number of Pixels", "Size of the baking batch", 0, INT_MAX);
|
||||
|
@ -816,6 +821,10 @@ static void rna_def_render_bake_pixel(BlenderRNA *brna)
|
|||
RNA_def_property_int_sdna(prop, NULL, "primitive_id");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "object_id", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "object_id");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_array(prop, 2);
|
||||
RNA_def_property_float_sdna(prop, NULL, "uv");
|
||||
|
|
|
@ -50,14 +50,13 @@ typedef struct BakeImages {
|
|||
} BakeImages;
|
||||
|
||||
typedef struct BakePixel {
|
||||
int primitive_id;
|
||||
int primitive_id, object_id;
|
||||
float uv[2];
|
||||
float du_dx, du_dy;
|
||||
float dv_dx, dv_dy;
|
||||
} BakePixel;
|
||||
|
||||
typedef struct BakeHighPolyData {
|
||||
struct BakePixel *pixel_array;
|
||||
struct Object *ob;
|
||||
struct ModifierData *tri_mod;
|
||||
struct Mesh *me;
|
||||
|
@ -72,7 +71,7 @@ typedef struct BakeHighPolyData {
|
|||
bool RE_bake_has_engine(struct Render *re);
|
||||
|
||||
bool RE_bake_engine(
|
||||
struct Render *re, struct Object *object, const BakePixel pixel_array[],
|
||||
struct Render *re, struct Object *object, const int object_id, const BakePixel pixel_array[],
|
||||
const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
|
||||
|
||||
/* bake.c */
|
||||
|
@ -82,7 +81,7 @@ bool RE_bake_internal(
|
|||
const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
|
||||
|
||||
bool RE_bake_pixels_populate_from_objects(
|
||||
struct Mesh *me_low, BakePixel pixel_array_from[],
|
||||
struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[],
|
||||
BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
|
||||
const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage);
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ typedef struct RenderEngineType {
|
|||
|
||||
void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Scene *scene);
|
||||
void (*render)(struct RenderEngine *engine, struct Scene *scene);
|
||||
void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result);
|
||||
void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result);
|
||||
|
||||
void (*view_update)(struct RenderEngine *engine, const struct bContext *context);
|
||||
void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
|
||||
|
|
|
@ -30,10 +30,11 @@
|
|||
*
|
||||
* The Bake API is fully implemented with Python rna functions. The operator expects/call a function:
|
||||
*
|
||||
* ``def bake(scene, object, pass_type, pixel_array, num_pixels, depth, result)``
|
||||
* ``def bake(scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result)``
|
||||
* - scene: current scene (Python object)
|
||||
* - object: object to render (Python object)
|
||||
* - pass_type: pass to render (string, e.g., "COMBINED", "AO", "NORMAL", ...)
|
||||
* - object_id: index of object to bake (to use with the pixel_array)
|
||||
* - pixel_array: list of primitive ids and barycentric coordinates to bake(Python object, see bake_pixel)
|
||||
* - num_pixels: size of pixel_array, number of pixels to bake (int)
|
||||
* - depth: depth of pixels to return (int, assuming always 4 now)
|
||||
|
@ -47,7 +48,7 @@
|
|||
*
|
||||
* \code{.c}
|
||||
* struct BakePixel {
|
||||
* int primitive_id;
|
||||
* int primitive_id, object_id;
|
||||
* float uv[2];
|
||||
* float du_dx, du_dy;
|
||||
* float dv_dx, dv_dy;
|
||||
|
@ -55,7 +56,7 @@
|
|||
* \endcode
|
||||
*
|
||||
* In python you have access to:
|
||||
* - ``primitive_id``, ``uv``, ``du_dx``, ``du_dy``, ``next``
|
||||
* - ``primitive_id``, ``object_id``, ``uv``, ``du_dx``, ``du_dy``, ``next``
|
||||
* - ``next()`` is a function that returns the next #BakePixel in the array.
|
||||
*
|
||||
* \note Pixels that should not be baked have ``primitive_id == -1``
|
||||
|
@ -126,12 +127,16 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v)
|
|||
pixel = &bd->pixel_array[i];
|
||||
pixel->primitive_id = bd->primitive_id;
|
||||
|
||||
/* At this point object_id is always 0, since this function runs for the
|
||||
* lowpoly mesh only. The object_id lookup indices are set afterwards. */
|
||||
|
||||
copy_v2_fl2(pixel->uv, u, v);
|
||||
|
||||
pixel->du_dx = bd->du_dx;
|
||||
pixel->du_dy = bd->du_dy;
|
||||
pixel->dv_dx = bd->dv_dx;
|
||||
pixel->dv_dy = bd->dv_dy;
|
||||
pixel->object_id = 0;
|
||||
}
|
||||
|
||||
void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask)
|
||||
|
@ -271,7 +276,7 @@ static void calc_barycentric_from_point(
|
|||
* This function populates pixel_array and returns TRUE if things are correct
|
||||
*/
|
||||
static bool cast_ray_highpoly(
|
||||
BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakeHighPolyData *highpoly,
|
||||
BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakePixel *pixel_array, BakeHighPolyData *highpoly,
|
||||
const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly,
|
||||
const float du_dx, const float du_dy, const float dv_dx, const float dv_dy)
|
||||
{
|
||||
|
@ -322,22 +327,22 @@ static bool cast_ray_highpoly(
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < tot_highpoly; i++) {
|
||||
if (hit_mesh == i) {
|
||||
calc_barycentric_from_point(triangles[i], hits[i].index, hits[i].co, &primitive_id, uv);
|
||||
highpoly[i].pixel_array[pixel_id].primitive_id = primitive_id;
|
||||
copy_v2_v2(highpoly[i].pixel_array[pixel_id].uv, uv);
|
||||
if (hit_mesh != -1) {
|
||||
calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv);
|
||||
pixel_array[pixel_id].primitive_id = primitive_id;
|
||||
pixel_array[pixel_id].object_id = hit_mesh;
|
||||
copy_v2_v2(pixel_array[pixel_id].uv, uv);
|
||||
|
||||
/* the differentials are relative to the UV/image space, so the highpoly differentials
|
||||
* are the same as the low poly differentials */
|
||||
highpoly[i].pixel_array[pixel_id].du_dx = du_dx;
|
||||
highpoly[i].pixel_array[pixel_id].du_dy = du_dy;
|
||||
highpoly[i].pixel_array[pixel_id].dv_dx = dv_dx;
|
||||
highpoly[i].pixel_array[pixel_id].dv_dy = dv_dy;
|
||||
}
|
||||
else {
|
||||
highpoly[i].pixel_array[pixel_id].primitive_id = -1;
|
||||
}
|
||||
/* the differentials are relative to the UV/image space, so the highpoly differentials
|
||||
* are the same as the low poly differentials */
|
||||
pixel_array[pixel_id].du_dx = du_dx;
|
||||
pixel_array[pixel_id].du_dy = du_dy;
|
||||
pixel_array[pixel_id].dv_dx = dv_dx;
|
||||
pixel_array[pixel_id].dv_dy = dv_dy;
|
||||
}
|
||||
else {
|
||||
pixel_array[pixel_id].primitive_id = -1;
|
||||
pixel_array[pixel_id].object_id = -1;
|
||||
}
|
||||
|
||||
MEM_freeN(hits);
|
||||
|
@ -437,7 +442,7 @@ static void mesh_calc_tri_tessface(
|
|||
}
|
||||
|
||||
bool RE_bake_pixels_populate_from_objects(
|
||||
struct Mesh *me_low, BakePixel pixel_array_from[],
|
||||
struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[],
|
||||
BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
|
||||
const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage)
|
||||
{
|
||||
|
@ -508,10 +513,7 @@ bool RE_bake_pixels_populate_from_objects(
|
|||
primitive_id = pixel_array_from[i].primitive_id;
|
||||
|
||||
if (primitive_id == -1) {
|
||||
int j;
|
||||
for (j = 0; j < tot_highpoly; j++) {
|
||||
highpoly[j].pixel_array[i].primitive_id = -1;
|
||||
}
|
||||
pixel_array_to[i].primitive_id = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -530,7 +532,7 @@ bool RE_bake_pixels_populate_from_objects(
|
|||
}
|
||||
|
||||
/* cast ray */
|
||||
if (!cast_ray_highpoly(treeData, tris_high, highpoly, co, dir, i, tot_highpoly,
|
||||
if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly,
|
||||
pixel_array_from[i].du_dx, pixel_array_from[i].du_dy,
|
||||
pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) {
|
||||
/* if it fails mask out the original pixel array */
|
||||
|
|
|
@ -463,7 +463,8 @@ bool RE_bake_has_engine(Render *re)
|
|||
}
|
||||
|
||||
bool RE_bake_engine(
|
||||
Render *re, Object *object, const BakePixel pixel_array[],
|
||||
Render *re, Object *object,
|
||||
const int object_id, const BakePixel pixel_array[],
|
||||
const size_t num_pixels, const int depth,
|
||||
const ScenePassType pass_type, float result[])
|
||||
{
|
||||
|
@ -501,7 +502,7 @@ bool RE_bake_engine(
|
|||
type->update(engine, re->main, re->scene);
|
||||
|
||||
if (type->bake)
|
||||
type->bake(engine, re->scene, object, pass_type, pixel_array, num_pixels, depth, result);
|
||||
type->bake(engine, re->scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result);
|
||||
|
||||
engine->tile_x = 0;
|
||||
engine->tile_y = 0;
|
||||
|
|
Loading…
Reference in New Issue