forked from bartvdbraak/blender
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.
This commit is contained in:
parent
1255b1e82d
commit
d917bdb095
@ -501,7 +501,7 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
|
|||||||
layout.prop(rd, "bake_type")
|
layout.prop(rd, "bake_type")
|
||||||
|
|
||||||
multires_bake = False
|
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")
|
layout.prop(rd, "use_bake_multires")
|
||||||
multires_bake = 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':
|
if rd.bake_type == 'DISPLACEMENT':
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.prop(rd, "use_bake_lores_mesh")
|
col.prop(rd, "use_bake_lores_mesh")
|
||||||
|
|
||||||
if rd.bake_type == 'AO':
|
if rd.bake_type == 'AO':
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.prop(rd, "bake_bias")
|
col.prop(rd, "bake_bias")
|
||||||
col.prop(rd, "bake_samples")
|
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.
|
if __name__ == "__main__": # only for live edit.
|
||||||
bpy.utils.register_module(__name__)
|
bpy.utils.register_module(__name__)
|
||||||
|
@ -91,20 +91,24 @@
|
|||||||
typedef struct MultiresBakerJobData {
|
typedef struct MultiresBakerJobData {
|
||||||
struct MultiresBakerJobData *next, *prev;
|
struct MultiresBakerJobData *next, *prev;
|
||||||
DerivedMesh *lores_dm, *hires_dm;
|
DerivedMesh *lores_dm, *hires_dm;
|
||||||
int simple, lvl, tot_lvl;
|
bool simple;
|
||||||
|
int lvl, tot_lvl;
|
||||||
ListBase images;
|
ListBase images;
|
||||||
} MultiresBakerJobData;
|
} MultiresBakerJobData;
|
||||||
|
|
||||||
/* data passing to multires-baker job */
|
/* data passing to multires-baker job */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ListBase data;
|
ListBase data;
|
||||||
int bake_clear, bake_filter;
|
bool bake_clear; /* Clear the images before baking */
|
||||||
short mode, use_lores_mesh;
|
int bake_filter; /* Bake-filter, aka margin */
|
||||||
int number_of_rays;
|
short mode; /* mode of baking (displacement, normals, AO) */
|
||||||
float bias;
|
bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */
|
||||||
int raytrace_structure;
|
int number_of_rays; /* Number of rays to be cast when doing AO baking */
|
||||||
int octree_resolution;
|
float bias; /* Bias between object and start ray point when doing AO baking */
|
||||||
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. */
|
||||||
} MultiresBakeJob;
|
} MultiresBakeJob;
|
||||||
|
|
||||||
static bool multiresbake_check(bContext *C, wmOperator *op)
|
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;
|
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;
|
Mesh *me = (Mesh *)ob->data;
|
||||||
MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
|
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);
|
CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH);
|
||||||
|
|
||||||
*lvl = mmd->totlvl;
|
*lvl = mmd->totlvl;
|
||||||
*simple = mmd->simple;
|
*simple = mmd->simple != 0;
|
||||||
|
|
||||||
tmp_mmd.lvl = mmd->totlvl;
|
tmp_mmd.lvl = mmd->totlvl;
|
||||||
tmp_mmd.sculptlvl = 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) {
|
if (scene->r.bake_mode == RE_BAKE_NORMALS) {
|
||||||
clear_flag = CLEAR_TANGENT_NORMAL;
|
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;
|
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.raytrace_structure = scene->r.raytrace_structure;
|
||||||
bkr.octree_resolution = scene->r.ocres;
|
bkr.octree_resolution = scene->r.ocres;
|
||||||
bkr.threads = BKE_scene_num_threads(scene);
|
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) */
|
/* 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);
|
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->raytrace_structure = scene->r.raytrace_structure;
|
||||||
bkj->octree_resolution = scene->r.ocres;
|
bkj->octree_resolution = scene->r.ocres;
|
||||||
bkj->threads = BKE_scene_num_threads(scene);
|
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)
|
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) {
|
if (bkj->mode == RE_BAKE_NORMALS) {
|
||||||
clear_flag = CLEAR_TANGENT_NORMAL;
|
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;
|
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.bake_filter = bkj->bake_filter;
|
||||||
bkr.mode = bkj->mode;
|
bkr.mode = bkj->mode;
|
||||||
bkr.use_lores_mesh = bkj->use_lores_mesh;
|
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) */
|
/* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
|
||||||
bkr.lores_dm = data->lores_dm;
|
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)
|
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 scene->r.bake_flag & R_BAKE_MULTIRES;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -511,6 +511,7 @@ typedef struct RenderData {
|
|||||||
short bake_normal_space, bake_quad_split;
|
short bake_normal_space, bake_quad_split;
|
||||||
float bake_maxdist, bake_biasdist;
|
float bake_maxdist, bake_biasdist;
|
||||||
short bake_samples, bake_pad;
|
short bake_samples, bake_pad;
|
||||||
|
float bake_user_scale, bake_pad1;
|
||||||
|
|
||||||
/* path to render output */
|
/* path to render output */
|
||||||
char pic[1024]; /* 1024 = FILE_MAX */
|
char pic[1024]; /* 1024 = FILE_MAX */
|
||||||
@ -1353,6 +1354,7 @@ typedef struct Scene {
|
|||||||
#define R_BAKE_MULTIRES 16
|
#define R_BAKE_MULTIRES 16
|
||||||
#define R_BAKE_LORES_MESH 32
|
#define R_BAKE_LORES_MESH 32
|
||||||
#define R_BAKE_VCOL 64
|
#define R_BAKE_VCOL 64
|
||||||
|
#define R_BAKE_USERSCALE 128
|
||||||
|
|
||||||
/* bake_normal_space */
|
/* bake_normal_space */
|
||||||
#define R_BAKE_SPACE_CAMERA 0
|
#define R_BAKE_SPACE_CAMERA 0
|
||||||
|
@ -4088,6 +4088,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
|
|||||||
{RE_BAKE_NORMALS, "NORMALS", 0, "Normals", "Bake normals"},
|
{RE_BAKE_NORMALS, "NORMALS", 0, "Normals", "Bake normals"},
|
||||||
{RE_BAKE_TEXTURE, "TEXTURE", 0, "Textures", "Bake textures"},
|
{RE_BAKE_TEXTURE, "TEXTURE", 0, "Textures", "Bake textures"},
|
||||||
{RE_BAKE_DISPLACEMENT, "DISPLACEMENT", 0, "Displacement", "Bake displacement"},
|
{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_EMIT, "EMIT", 0, "Emission", "Bake Emit values (glow)"},
|
||||||
{RE_BAKE_ALPHA, "ALPHA", 0, "Alpha", "Bake Alpha values (transparency)"},
|
{RE_BAKE_ALPHA, "ALPHA", 0, "Alpha", "Bake Alpha values (transparency)"},
|
||||||
{RE_BAKE_MIRROR_INTENSITY, "MIRROR_INTENSITY", 0, "Mirror Intensity", "Bake Mirror values"},
|
{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");
|
"Bake to vertex colors instead of to a UV-mapped image");
|
||||||
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
|
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 */
|
/* stamp */
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
@ -37,20 +37,25 @@ struct MultiresBakeRender;
|
|||||||
|
|
||||||
typedef struct MultiresBakeRender {
|
typedef struct MultiresBakeRender {
|
||||||
DerivedMesh *lores_dm, *hires_dm;
|
DerivedMesh *lores_dm, *hires_dm;
|
||||||
int simple, lvl, tot_lvl, bake_filter;
|
bool simple;
|
||||||
short mode, use_lores_mesh;
|
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;
|
int number_of_rays; /* Number of rays to be cast when doing AO baking */
|
||||||
float bias;
|
float bias; /* Bias between object and start ray point when doing AO baking */
|
||||||
|
|
||||||
int tot_obj, tot_image;
|
int tot_obj, tot_image;
|
||||||
ListBase image;
|
ListBase image;
|
||||||
|
|
||||||
int baked_objects, baked_faces;
|
int baked_objects, baked_faces;
|
||||||
|
|
||||||
int raytrace_structure;
|
int raytrace_structure; /* Optimization structure to be used for AO baking */
|
||||||
int octree_resolution;
|
int octree_resolution; /* Reslution of octotree when using octotree optimization structure */
|
||||||
int threads;
|
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 *stop;
|
||||||
short *do_update;
|
short *do_update;
|
||||||
|
@ -281,6 +281,7 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd);
|
|||||||
#define RE_BAKE_MIRROR_INTENSITY 10
|
#define RE_BAKE_MIRROR_INTENSITY 10
|
||||||
#define RE_BAKE_ALPHA 11
|
#define RE_BAKE_ALPHA 11
|
||||||
#define RE_BAKE_EMIT 12
|
#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);
|
void RE_Database_Baking(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, const int type, struct Object *actob);
|
||||||
|
|
||||||
|
@ -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);
|
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_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);
|
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_OK 0
|
||||||
#define BAKE_RESULT_NO_OBJECTS 1
|
#define BAKE_RESULT_NO_OBJECTS 1
|
||||||
|
@ -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)
|
if (hit)
|
||||||
bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y);
|
bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y);
|
||||||
else
|
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_flag & R_BAKE_CLEAR) {
|
||||||
if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT)
|
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);
|
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);
|
IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
|
||||||
else
|
else
|
||||||
IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
|
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;
|
use_mask = true;
|
||||||
|
|
||||||
/* do we need buffer to store displacements */
|
/* do we need buffer to store displacements */
|
||||||
if (type == RE_BAKE_DISPLACEMENT) {
|
if (ELEM(type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) {
|
||||||
if ((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) {
|
if (((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) ||
|
||||||
|
(type == RE_BAKE_DERIVATIVE))
|
||||||
|
{
|
||||||
use_displacement_buffer = true;
|
use_displacement_buffer = true;
|
||||||
use_mask = true;
|
use_mask = true;
|
||||||
}
|
}
|
||||||
@ -1089,9 +1091,16 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
|
|||||||
userdata = (BakeImBufuserData *)ibuf->userdata;
|
userdata = (BakeImBufuserData *)ibuf->userdata;
|
||||||
if (userdata) {
|
if (userdata) {
|
||||||
if (use_displacement_buffer) {
|
if (use_displacement_buffer) {
|
||||||
|
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,
|
RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
|
||||||
displacement_min, displacement_max);
|
displacement_min, displacement_max);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter);
|
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;
|
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);
|
||||||
|
}
|
||||||
|
@ -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_AO: for baking, no lamps, but all objects
|
||||||
* RE_BAKE_TEXTURE:for baking, no lamps, only selected objects
|
* RE_BAKE_TEXTURE:for baking, no lamps, only selected objects
|
||||||
* RE_BAKE_DISPLACEMENT: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
|
* 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)
|
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 mat[4][4];
|
||||||
float amb[3];
|
float amb[3];
|
||||||
const short onlyselected= !ELEM4(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO);
|
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->main= bmain;
|
||||||
re->scene= scene;
|
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)
|
if (type==RE_BAKE_NORMALS && re->r.bake_normal_space==R_BAKE_SPACE_TANGENT)
|
||||||
re->flag |= R_NEED_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_SHADOW;
|
||||||
re->r.mode &= ~R_RAYTRACE;
|
re->r.mode &= ~R_RAYTRACE;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
do_multires_bake(bkr, ima, TRUE, apply_tangmat_callback, init_normal_data, free_normal_data, result);
|
||||||
break;
|
break;
|
||||||
case RE_BAKE_DISPLACEMENT:
|
case RE_BAKE_DISPLACEMENT:
|
||||||
|
case RE_BAKE_DERIVATIVE:
|
||||||
do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data, free_heights_data, result);
|
do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data, free_heights_data, result);
|
||||||
break;
|
break;
|
||||||
case RE_BAKE_AO:
|
case RE_BAKE_AO:
|
||||||
@ -1248,7 +1249,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
|
|||||||
static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
|
static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
|
||||||
{
|
{
|
||||||
LinkData *link;
|
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) {
|
for (link = bkr->image.first; link; link = link->next) {
|
||||||
Image *ima = (Image *)link->data;
|
Image *ima = (Image *)link->data;
|
||||||
@ -1259,9 +1260,15 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (use_displacement_buffer) {
|
if (use_displacement_buffer) {
|
||||||
|
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,
|
RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
|
||||||
result->height_min, result->height_max);
|
result->height_min, result->height_max);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter);
|
RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user