Derivative map baker
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 9 Oct 2013 15:51:14 +0000 (15:51 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 9 Oct 2013 15:51:14 +0000 (15:51 +0000)
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
source/blender/editors/object/object_bake.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_scene.c
source/blender/render/extern/include/RE_multires_bake.h
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/source/bake.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/multires_bake.c

index e11f179e2cb20dd69934b6cd53b5a15cda8c5c35..288f95ca4b05a7b80474579fce3ec6a98c1801f9 100644 (file)
@@ -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__)
index 376f2ed294b60eb8e641fc7c5fe8bcc9482eb113..4a8097f260e9e068e1743440b4b41c19f9eb9e8e 100644 (file)
 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;
index 35bd46507760afec220ed0fe4603c80eed4585c5..232fe62df31c86e3bd77895300576504bca9c3a8 100644 (file)
@@ -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
index 9414591eaf923e978e7c663a85d14cb9adde1fa8..573175e57e5f36998f2009c33f71e246574e3f8b 100644 (file)
@@ -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);
index 04cfe55e3a3e549a58dacf90237531ba5abe9ded..c1c5fc4a04d73b9ab8e464c96d35b02cc5a8dc73 100644 (file)
@@ -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;
index 73a89ad884fbd42635e8392bc317120ee1c48c61..35d971ab976054f477fd342d9c80576f34f8c179 100644 (file)
@@ -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);
 
index 19ddfb7a13d5c080984799ffbd0185b3eb2f8a5a..baec1a74721a034775ce297d57c7d01b72da8d59 100644 (file)
@@ -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
index 6e70e670ff86a027188fbf400350517287f6b575..f4bbdb6add87ddbc76d026b90ba2f23f6965065f 100644 (file)
@@ -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; 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.
+                        */
+                       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);
+}
index a0104a30d0e36b45d8d066ef228de9db613cfdd8..b5377a078481ab0658db5c31a45177d21eef18d7 100644 (file)
@@ -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;
        }
index a2fa37fd7ea7283573f2e1709c6e9ea5bb999216..3259608c18fc7234c055912dad8784f33b45b9b3 100644 (file)
@@ -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);