From d917bdb095573161522194449fc22f6809e5b5b2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 9 Oct 2013 15:51:14 +0000 Subject: Derivative map baker Added support for derivative map baking, which is accessable as a dedicated baker type. Works pretty much the same as displacement map baker, but gives you derivative map. In fact, inernally this baker is just a filter which applies on the result of displacement map. Both regular and multires baking are supported. Patch by Morten Mikkelsen and self. --- release/scripts/startup/bl_ui/properties_render.py | 11 +- source/blender/editors/object/object_bake.c | 36 ++-- source/blender/makesdna/DNA_scene_types.h | 2 + source/blender/makesrna/intern/rna_scene.c | 12 ++ .../render/extern/include/RE_multires_bake.h | 21 ++- source/blender/render/extern/include/RE_pipeline.h | 1 + .../blender/render/extern/include/RE_shader_ext.h | 3 + source/blender/render/intern/source/bake.c | 194 ++++++++++++++++++++- .../blender/render/intern/source/convertblender.c | 5 +- .../blender/render/intern/source/multires_bake.c | 15 +- 10 files changed, 266 insertions(+), 34 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index e11f179e2cb..288f95ca4b0 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -501,7 +501,7 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel): layout.prop(rd, "bake_type") multires_bake = False - if rd.bake_type in ['NORMALS', 'DISPLACEMENT', 'AO']: + if rd.bake_type in ['NORMALS', 'DISPLACEMENT', 'DERIVATIVE', 'AO']: layout.prop(rd, "use_bake_multires") multires_bake = rd.use_bake_multires @@ -542,11 +542,20 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel): if rd.bake_type == 'DISPLACEMENT': col = split.column() col.prop(rd, "use_bake_lores_mesh") + if rd.bake_type == 'AO': col = split.column() col.prop(rd, "bake_bias") col.prop(rd, "bake_samples") + if rd.bake_type == 'DERIVATIVE': + row = layout.row() + row.prop(rd, "use_bake_user_scale", text="") + + sub = row.column() + sub.active = rd.use_bake_user_scale + sub.prop(rd, "bake_user_scale", text="User Scale") + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index 376f2ed294b..4a8097f260e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -91,20 +91,24 @@ typedef struct MultiresBakerJobData { struct MultiresBakerJobData *next, *prev; DerivedMesh *lores_dm, *hires_dm; - int simple, lvl, tot_lvl; + bool simple; + int lvl, tot_lvl; ListBase images; } MultiresBakerJobData; /* data passing to multires-baker job */ typedef struct { ListBase data; - int bake_clear, bake_filter; - short mode, use_lores_mesh; - int number_of_rays; - float bias; - int raytrace_structure; - int octree_resolution; - int threads; + bool bake_clear; /* Clear the images before baking */ + int bake_filter; /* Bake-filter, aka margin */ + short mode; /* mode of baking (displacement, normals, AO) */ + bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */ + int number_of_rays; /* Number of rays to be cast when doing AO baking */ + float bias; /* Bias between object and start ray point when doing AO baking */ + int raytrace_structure; /* Optimization structure to be used for AO baking */ + int octree_resolution; /* Reslution of octotree when using octotree optimization structure */ + int threads; /* Number of threads to be used for baking */ + float user_scale; /* User scale used to scale displacement when baking derivative map. */ } MultiresBakeJob; static bool multiresbake_check(bContext *C, wmOperator *op) @@ -236,7 +240,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l return dm; } -static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, int *simple) +static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, bool *simple) { Mesh *me = (Mesh *)ob->data; MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); @@ -253,7 +257,7 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH); *lvl = mmd->totlvl; - *simple = mmd->simple; + *simple = mmd->simple != 0; tmp_mmd.lvl = mmd->totlvl; tmp_mmd.sculptlvl = mmd->totlvl; @@ -349,7 +353,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) if (scene->r.bake_mode == RE_BAKE_NORMALS) { clear_flag = CLEAR_TANGENT_NORMAL; } - else if (scene->r.bake_mode == RE_BAKE_DISPLACEMENT) { + else if (ELEM(scene->r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { clear_flag = CLEAR_DISPLACEMENT; } @@ -376,6 +380,8 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) bkr.raytrace_structure = scene->r.raytrace_structure; bkr.octree_resolution = scene->r.ocres; bkr.threads = BKE_scene_num_threads(scene); + bkr.user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f; + //bkr.reports= op->reports; /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple); @@ -414,6 +420,8 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj) bkj->raytrace_structure = scene->r.raytrace_structure; bkj->octree_resolution = scene->r.ocres; bkj->threads = BKE_scene_num_threads(scene); + bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f; + //bkj->reports = op->reports; CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { @@ -453,7 +461,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa if (bkj->mode == RE_BAKE_NORMALS) { clear_flag = CLEAR_TANGENT_NORMAL; } - else if (bkj->mode == RE_BAKE_DISPLACEMENT) { + else if (ELEM(bkj->mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { clear_flag = CLEAR_DISPLACEMENT; } @@ -468,6 +476,8 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa bkr.bake_filter = bkj->bake_filter; bkr.mode = bkj->mode; bkr.use_lores_mesh = bkj->use_lores_mesh; + bkr.user_scale = bkj->user_scale; + //bkr.reports = bkj->reports; /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ bkr.lores_dm = data->lores_dm; @@ -773,7 +783,7 @@ static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const static int is_multires_bake(Scene *scene) { - if (ELEM3(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO)) + if (ELEM4(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_AO)) return scene->r.bake_flag & R_BAKE_MULTIRES; return 0; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 35bd4650776..232fe62df31 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -511,6 +511,7 @@ typedef struct RenderData { short bake_normal_space, bake_quad_split; float bake_maxdist, bake_biasdist; short bake_samples, bake_pad; + float bake_user_scale, bake_pad1; /* path to render output */ char pic[1024]; /* 1024 = FILE_MAX */ @@ -1353,6 +1354,7 @@ typedef struct Scene { #define R_BAKE_MULTIRES 16 #define R_BAKE_LORES_MESH 32 #define R_BAKE_VCOL 64 +#define R_BAKE_USERSCALE 128 /* bake_normal_space */ #define R_BAKE_SPACE_CAMERA 0 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 9414591eaf9..573175e57e5 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -4088,6 +4088,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {RE_BAKE_NORMALS, "NORMALS", 0, "Normals", "Bake normals"}, {RE_BAKE_TEXTURE, "TEXTURE", 0, "Textures", "Bake textures"}, {RE_BAKE_DISPLACEMENT, "DISPLACEMENT", 0, "Displacement", "Bake displacement"}, + {RE_BAKE_DERIVATIVE, "DERIVATIVE", 0, "Derivative", "Bake derivative map"}, {RE_BAKE_EMIT, "EMIT", 0, "Emission", "Bake Emit values (glow)"}, {RE_BAKE_ALPHA, "ALPHA", 0, "Alpha", "Bake Alpha values (transparency)"}, {RE_BAKE_MIRROR_INTENSITY, "MIRROR_INTENSITY", 0, "Mirror Intensity", "Bake Mirror values"}, @@ -4674,6 +4675,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna) "Bake to vertex colors instead of to a UV-mapped image"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "use_bake_user_scale", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_USERSCALE); + RNA_def_property_ui_text(prop, "User scale", "Use a user scale for the derivative map"); + + prop = RNA_def_property(srna, "bake_user_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "bake_user_scale"); + RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_ui_text(prop, "Scale", + "Instead of automatically normalizing to 0..1, " + "apply a user scale to the derivative map."); + /* stamp */ prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/render/extern/include/RE_multires_bake.h b/source/blender/render/extern/include/RE_multires_bake.h index 04cfe55e3a3..c1c5fc4a04d 100644 --- a/source/blender/render/extern/include/RE_multires_bake.h +++ b/source/blender/render/extern/include/RE_multires_bake.h @@ -37,21 +37,26 @@ struct MultiresBakeRender; typedef struct MultiresBakeRender { DerivedMesh *lores_dm, *hires_dm; - int simple, lvl, tot_lvl, bake_filter; - short mode, use_lores_mesh; + bool simple; + int bake_filter; /* Bake-filter, aka margin */ + int lvl, tot_lvl; + short mode; + bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */ - int number_of_rays; - float bias; + int number_of_rays; /* Number of rays to be cast when doing AO baking */ + float bias; /* Bias between object and start ray point when doing AO baking */ int tot_obj, tot_image; ListBase image; int baked_objects, baked_faces; - int raytrace_structure; - int octree_resolution; - int threads; - + int raytrace_structure; /* Optimization structure to be used for AO baking */ + int octree_resolution; /* Reslution of octotree when using octotree optimization structure */ + int threads; /* Number of threads to be used for baking */ + + float user_scale; /* User scale used to scale displacement when baking derivative map. */ + short *stop; short *do_update; float *progress; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 73a89ad884f..35d971ab976 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -281,6 +281,7 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd); #define RE_BAKE_MIRROR_INTENSITY 10 #define RE_BAKE_ALPHA 11 #define RE_BAKE_EMIT 12 +#define RE_BAKE_DERIVATIVE 13 void RE_Database_Baking(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, const int type, struct Object *actob); diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 19ddfb7a13d..baec1a74721 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -213,6 +213,9 @@ int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob struct Image *RE_bake_shade_get_image(void); void RE_bake_ibuf_filter(struct ImBuf *ibuf, char *mask, const int filter); void RE_bake_ibuf_normalize_displacement(struct ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max); +float RE_bake_make_derivative(struct ImBuf *ibuf, float *heights_buffer, const char *mask, + const float height_min, const float height_max, + const float fmult); #define BAKE_RESULT_OK 0 #define BAKE_RESULT_NO_OBJECTS 1 diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c index 6e70e670ff8..f4bbdb6add8 100644 --- a/source/blender/render/intern/source/bake.c +++ b/source/blender/render/intern/source/bake.c @@ -553,7 +553,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) } } - if (bs->type == RE_BAKE_DISPLACEMENT) { + if (ELEM(bs->type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { if (hit) bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y); else @@ -688,7 +688,7 @@ static int get_next_bake_face(BakeShade *bs) if (R.r.bake_flag & R_BAKE_CLEAR) { if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid); - else if (R.r.bake_mode == RE_BAKE_DISPLACEMENT) + else if (ELEM(R.r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) 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); @@ -984,8 +984,10 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up use_mask = true; /* do we need buffer to store displacements */ - if (type == RE_BAKE_DISPLACEMENT) { - if ((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) { + if (ELEM(type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { + if (((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) || + (type == RE_BAKE_DERIVATIVE)) + { use_displacement_buffer = true; use_mask = true; } @@ -1089,8 +1091,15 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up userdata = (BakeImBufuserData *)ibuf->userdata; if (userdata) { if (use_displacement_buffer) { - RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, - displacement_min, displacement_max); + if (type == RE_BAKE_DERIVATIVE) { + float user_scale = (R.r.bake_flag & R_BAKE_USERSCALE) ? R.r.bake_user_scale : -1.0f; + RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + displacement_min, displacement_max, user_scale); + } + else { + RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + displacement_min, displacement_max); + } } RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter); @@ -1124,3 +1133,176 @@ struct Image *RE_bake_shade_get_image(void) return R.bakebuf; } +/* **************** Derivative Maps Baker **************** */ + +static void add_single_heights_margin(const ImBuf *ibuf, const char *mask, float *heights_buffer) +{ + int x ,y; + + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + int index = ibuf->x * y + x; + + /* If unassigned pixel, look for neighbors. */ + if (mask[index] != FILTER_MASK_USED) { + float height_acc = 0; + int denom = 0; + int i, j; + + for (j = -1; j <= 1; j++) + for (i = -1; i <= 1; i++) { + int w = (i == 0 ? 1 : 0) + (j == 0 ? 1 : 0) + 1; + + if (i != 0 || j != 0) { + int index2 = 0; + int x0 = x + i; + int y0 = y + j; + + CLAMP(x0, 0, ibuf->x - 1); + CLAMP(y0, 0, ibuf->y - 1); + + index2 = ibuf->x * y0 + x0; + + if (mask[index2] == FILTER_MASK_USED) { + height_acc += w * heights_buffer[index2]; + denom += w; + } + } + } + + /* Insert final value. */ + if (denom > 0) { + heights_buffer[index] = height_acc / denom; + } + } + } + } +} + +/* returns user-scale */ +float RE_bake_make_derivative(ImBuf *ibuf, float *heights_buffer, const char *mask, + const float height_min, const float height_max, + const float fmult) +{ + const float delta_height = height_max - height_min; + const float denom = delta_height > 0.0f ? (8 * delta_height) : 1.0f; + bool auto_range_fit = fmult <= 0.0f; + float max_num_deriv = -1.0f; + int x, y, index; + + /* Need a single margin to calculate good derivatives. */ + add_single_heights_margin(ibuf, mask, heights_buffer); + + if (auto_range_fit) { + /* If automatic range fitting is enabled. */ + for (y = 0; y < ibuf->y; y++) { + const int Yu = y == (ibuf->y - 1) ? (ibuf->y - 1) : (y+1); + const int Yc = y; + const int Yd = y == 0 ? 0 : (y - 1); + + for (x= 0; x < ibuf->x; x++) { + const int Xl = x == 0 ? 0 : (x - 1); + const int Xc = x; + const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1); + + const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl]; + const float Hu = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl]; + const float Hd = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl]; + + const float Hl = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl]; + const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc]; + const float Hr = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr]; + + /* This corresponds to using the sobel kernel on the heights buffer + * to obtain the derivative multiplied by 8. + */ + const float deriv_x = Hu + 2 * Hcy + Hd; + const float deriv_y = Hr + 2 * Hcx + Hl; + + /* early out */ + index = ibuf->x * y + x; + if (mask[index] != FILTER_MASK_USED) { + continue; + } + + /* Widen bound. */ + if (fabsf(deriv_x) > max_num_deriv) { + max_num_deriv = fabsf(deriv_x); + } + + if (fabsf(deriv_y) > max_num_deriv) { + max_num_deriv = fabsf(deriv_y); + } + } + } + } + + /* Output derivatives. */ + auto_range_fit &= (max_num_deriv > 0); + for (y = 0; y < ibuf->y; y++) { + const int Yu= y==(ibuf->y-1) ? (ibuf->y-1) : (y+1); + const int Yc= y; + const int Yd= y==0 ? 0 : (y-1); + + for(x= 0; xx; x++) { + const int Xl = x == 0 ? 0 : (x - 1); + const int Xc = x; + const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1); + + const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl]; + const float Hu = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl]; + const float Hd = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl]; + + const float Hl = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl]; + const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc]; + const float Hr = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr]; + + /* This corresponds to using the sobel kernel on the heights buffer + * to obtain the derivative multiplied by 8. + */ + float deriv_x = Hu + 2 * Hcy + Hd; + float deriv_y = Hr + 2 * Hcx + Hl; + + /* Early out. */ + index = ibuf->x * y + x; + if (mask[index] != FILTER_MASK_USED){ + continue; + } + + if (auto_range_fit) { + deriv_x /= max_num_deriv; + deriv_y /= max_num_deriv; + } else { + deriv_x *= (fmult / denom); + deriv_y *= (fmult / denom); + } + + deriv_x = deriv_x * 0.5f + 0.5f; + deriv_y = deriv_y * 0.5f + 0.5f; + + /* Clamp. */ + CLAMP(deriv_x, 0.0f, 1.0f); + CLAMP(deriv_y, 0.0f, 1.0f); + + /* Write out derivatives. */ + if (ibuf->rect_float) { + float *rrgbf = ibuf->rect_float + index * 4; + + rrgbf[0] = deriv_x; + rrgbf[1] = deriv_y; + rrgbf[2] = 0.0f; + rrgbf[3] = 1.0f; + } else { + char *rrgb = (char*)ibuf->rect + index * 4; + + rrgb[0] = FTOCHAR(deriv_x); + rrgb[1] = FTOCHAR(deriv_y); + rrgb[2] = 0; + rrgb[3] = 255; + } + } + } + + /* Eeturn user-scale (for rendering). */ + return auto_range_fit ? (max_num_deriv / denom) : (fmult > 0.0f ? (1.0f / fmult) : 0.0f); +} diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index a0104a30d0e..b5377a07848 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -5983,6 +5983,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned * RE_BAKE_AO: for baking, no lamps, but all objects * RE_BAKE_TEXTURE:for baking, no lamps, only selected objects * RE_BAKE_DISPLACEMENT:for baking, no lamps, only selected objects + * RE_BAKE_DERIVATIVE:for baking, no lamps, only selected objects * RE_BAKE_SHADOW: for baking, only shadows, but all objects */ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, const int type, Object *actob) @@ -5991,7 +5992,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, float mat[4][4]; float amb[3]; const short onlyselected= !ELEM4(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO); - const short nolamps= ELEM3(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT); + const short nolamps= ELEM4(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE); re->main= bmain; re->scene= scene; @@ -6010,7 +6011,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, if (type==RE_BAKE_NORMALS && re->r.bake_normal_space==R_BAKE_SPACE_TANGENT) re->flag |= R_NEED_TANGENT; - if (!actob && ELEM4(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT)) { + if (!actob && ELEM5(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { re->r.mode &= ~R_SHADOW; re->r.mode &= ~R_RAYTRACE; } diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index a2fa37fd7ea..3259608c18f 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -124,7 +124,7 @@ typedef struct { const int *orig_index_mp_to_orig; } MAOBakeData; -static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int face_num, const int vert_index) +static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int face_num, const int vert_index) { unsigned int indices[] = {data->mface[face_num].v1, data->mface[face_num].v2, data->mface[face_num].v3, data->mface[face_num].v4}; @@ -1231,6 +1231,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) do_multires_bake(bkr, ima, TRUE, apply_tangmat_callback, init_normal_data, free_normal_data, result); break; case RE_BAKE_DISPLACEMENT: + case RE_BAKE_DERIVATIVE: do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data, free_heights_data, result); break; case RE_BAKE_AO: @@ -1248,7 +1249,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) { LinkData *link; - int use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT; + bool use_displacement_buffer = ELEM(bkr->mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE); for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; @@ -1259,8 +1260,14 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) continue; if (use_displacement_buffer) { - RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, - result->height_min, result->height_max); + if (bkr->mode == RE_BAKE_DERIVATIVE) { + RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + result->height_min, result->height_max, bkr->user_scale); + } + else { + RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + result->height_min, result->height_max); + } } RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter); -- cgit v1.2.3