Vector displacement for the sculpting draw brush #104481

Merged
Jeroen Bakker merged 18 commits from robin.hohni/blender:sculpt-vector-displacement into main 2023-02-14 15:29:40 +01:00
15 changed files with 257 additions and 259 deletions
Showing only changes of commit 5ca7ce0752 - Show all commits

View File

@ -1141,11 +1141,10 @@ def brush_texture_settings(layout, brush, sculpt):
# texture_sample_bias
layout.prop(brush, "texture_sample_bias", slider=True, text="Sample Bias")
# use_rgb_as_vector_displacement (Only working for draw brush for now)
if brush.sculpt_tool == 'DRAW':
col = layout.column()
col.active = tex_slot.map_mode == 'AREA_PLANE'
col.prop(brush, "use_rgb_as_vector_displacement", text="RGB as Vector Displacement")
col.prop(brush, "use_color_as_displacement", text="Vector Displacement")
Jeroen-Bakker marked this conversation as resolved
Review

Python has some rules about the number of lines between statements. Here it is max 1.

Python has some rules about the number of lines between statements. Here it is max 1.

View File

@ -203,7 +203,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
if (col) {
float rgba[4];
paint_get_tex_pixel_srgb_with_clamp(mtex, x, y, rgba, thread_id, pool, convert_to_linear, colorspace);
paint_get_tex_pixel_color_with_clamp(mtex, x, y, rgba, pool, thread_id, convert_to_linear, colorspace);
buffer[index * 4] = rgba[0] * 255;
buffer[index * 4 + 1] = rgba[1] * 255;
@ -213,7 +213,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
else {
float avg;
float rgba_dummy[4];
paint_get_tex_pixel(mtex, x, y, thread_id, pool, &avg, rgba_dummy);
paint_get_tex_pixel(mtex, x, y, pool, thread_id, &avg, rgba_dummy);
avg += br->texture_sample_bias;

View File

@ -353,13 +353,13 @@ float paint_calc_object_space_radius(struct ViewContext *vc,
const float center[3],
float pixel_radius);
bool paint_get_tex_pixel(
const struct MTex *mtex, float u, float v, int thread, struct ImagePool *pool, float *r_intensity, float r_rgba[4]);
void paint_get_tex_pixel_srgb_with_clamp(const struct MTex *mtex,
const struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread, float *r_intensity, float r_rgba[4]);
void paint_get_tex_pixel_color_with_clamp(const struct MTex *mtex,
float u,
float v,
float rgba[4],
int thread,
struct ImagePool *pool,
int thread,
bool convert,
struct ColorSpace *colorspace);

View File

@ -149,8 +149,8 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo
bool paint_get_tex_pixel(const MTex *mtex,
float u,
float v,
int thread,
struct ImagePool *pool,
int thread,
/* Return arguments. */
float *r_intensity,
float r_rgba[4])
@ -170,12 +170,12 @@ bool paint_get_tex_pixel(const MTex *mtex,
return hasRGB;
}
void paint_get_tex_pixel_srgb_with_clamp(const MTex *mtex,
void paint_get_tex_pixel_color_with_clamp(const MTex *mtex,
float u,
float v,
float rgba[4],
int thread,
struct ImagePool *pool,
int thread,
bool convert_to_linear,
struct ColorSpace *colorspace)
{

View File

@ -2557,35 +2557,52 @@ static float brush_strength(const Sculpt *sd,
}
}
float SCULPT_brush_factor_with_color(SculptSession *ss,
const Brush *brush,
const float brush_point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
int thread_id,
AutomaskingNodeData *automask_data,
float r_rgb[3])
static float sculpt_apply_hardness(const SculptSession *ss, const float input_len)
{
const StrokeCache *cache = ss->cache;
float final_len = input_len;
const float hardness = cache->paint_brush.hardness;
float p = input_len / cache->radius;
if (p < hardness) {
final_len = 0.0f;
}
else if (hardness == 1.0f) {
final_len = cache->radius;
}
else {
p = (p - hardness) / (1.0f - hardness);
final_len = p * cache->radius;
}
return final_len;
}
static void sculpt_apply_texture(const SculptSession *ss,
const Brush *brush,
const float brush_point[3],
const int thread_id,
float *r_value,
float r_rgba[4])
{
StrokeCache *cache = ss->cache;
const Scene *scene = cache->vc->scene;
const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
float avg = 1.0f;
float rgba[4];
float point[3];
sub_v3_v3v3(point, brush_point, cache->plane_offset);
if (!mtex->tex) {
rgba[0] = 1.0f;
rgba[1] = 1.0f;
rgba[2] = 1.0f;
*r_value = 1.0f;
r_rgba[0] = 1.0f;
r_rgba[1] = 1.0f;
r_rgba[2] = 1.0f;
r_rgba[3] = 1.0f;
return;
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
float point[3];
sub_v3_v3v3(point, brush_point, cache->plane_offset);
if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
/* Get strength by feeding the vertex location directly into a texture. */
avg = BKE_brush_sample_tex_3d(scene, brush, mtex, point, rgba, 0, ss->tex_pool);
*r_value = BKE_brush_sample_tex_3d(scene, brush, mtex, point, r_rgba, 0, ss->tex_pool);
}
else {
float symm_point[3];
@ -2616,33 +2633,39 @@ float SCULPT_brush_factor_with_color(SculptSession *ss,
x += mtex->ofs[0];
y += mtex->ofs[1];
paint_get_tex_pixel(mtex, x, y, thread_id, ss->tex_pool, &avg, rgba);
paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id, r_value, r_rgba);
add_v3_fl(rgba, brush->texture_sample_bias); // v3 -> Ignore alpha
avg -= brush->texture_sample_bias;
add_v3_fl(r_rgba, brush->texture_sample_bias); // v3 -> Ignore alpha
*r_value -= brush->texture_sample_bias;
}
else {
float point_2d[2];
ED_view3d_project_float_v2_m4(cache->vc->region, symm_point, point_2d, cache->projection_mat);
const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
avg = BKE_brush_sample_tex_3d(scene, brush, mtex, point_3d, rgba, 0, ss->tex_pool);
*r_value = BKE_brush_sample_tex_3d(scene, brush, mtex, point_3d, r_rgba, 0, ss->tex_pool);
}
}
}
float SCULPT_brush_strength_factor(SculptSession *ss,
const Brush *brush,
const float brush_point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
int thread_id,
AutomaskingNodeData *automask_data)
{
StrokeCache *cache = ss->cache;
float avg = 1.0f;
float rgba[4];
sculpt_apply_texture(ss, brush, brush_point, thread_id, &avg, rgba);
/* Hardness. */
float final_len = len;
const float hardness = cache->paint_brush.hardness;
float p = len / cache->radius;
if (p < hardness) {
final_len = 0.0f;
}
else if (hardness == 1.0f) {
final_len = cache->radius;
}
else {
p = (p - hardness) / (1.0f - hardness);
final_len = p * cache->radius;
}
const float final_len = sculpt_apply_hardness(ss, len);
/* Falloff curve. */
const float falloff = BKE_brush_curve_strength(brush, final_len, cache->radius)
@ -2654,26 +2677,57 @@ float SCULPT_brush_factor_with_color(SculptSession *ss,
/* Auto-masking. */
const float automasking_factor = SCULPT_automasking_factor_get(cache->automasking, ss, vertex, automask_data);
/* Apply masks */
const float masks_combined = falloff * paint_mask * automasking_factor;
mul_v3_fl(rgba, masks_combined);
avg *= masks_combined;
/* Copy rgba for vector displacement */
copy_v3_v3(r_rgb, rgba);
avg *= masks_combined;
return avg;
}
void SCULPT_calc_vertex_displacement(SculptSession *ss, float rgb[3], float out_offset[3])
void SCULPT_brush_strength_color(struct SculptSession *ss,
const struct Brush *brush,
const float brush_point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
int thread_id,
struct AutomaskingNodeData *automask_data,
float r_rgba[4])
{
rgb[2] *= ss->cache->bstrength;
mul_mat3_m4_v3(ss->cache->brush_local_mat_inv, rgb);
StrokeCache *cache = ss->cache;
float avg = 1.0f;
sculpt_apply_texture(ss, brush, brush_point, thread_id, &avg, r_rgba);
/* Hardness. */
const float final_len = sculpt_apply_hardness(ss, len);
/* Falloff curve. */
const float falloff = BKE_brush_curve_strength(brush, final_len, cache->radius)
* frontface(brush, cache->view_normal, vno, fno);
/* Paint mask. */
const float paint_mask = 1.0f - mask;
/* Auto-masking. */
const float automasking_factor = SCULPT_automasking_factor_get(cache->automasking, ss, vertex, automask_data);
const float masks_combined = falloff * paint_mask * automasking_factor;
mul_v4_fl(r_rgba, masks_combined);
}
void SCULPT_calc_vertex_displacement(SculptSession *ss, float rgba[4], float out_offset[3])
{
rgba[2] *= ss->cache->bstrength;
mul_mat3_m4_v3(ss->cache->brush_local_mat_inv, rgba);
robin.hohni marked this conversation as resolved
Review

For readability would suggest to first square the size, and then do the inf check using math::safe_divide. Seems we currently don't have a safe divide in math for 2 vector types.

rgba[i] *= math::safe_divide(1.0f, POW2(brush->mtex.size[i])); perhaps?

For readability would suggest to first square the size, and then do the inf check using `math::safe_divide`. Seems we currently don't have a safe divide in math for 2 vector types. `rgba[i] *= math::safe_divide(1.0f, POW2(brush->mtex.size[i]));` perhaps?
Review

Thanks for the hint! Made a commit :)

Thanks for the hint! Made a commit :)
if (ss->cache->radial_symmetry_pass) {
mul_m4_v3(ss->cache->symm_rot_mat, rgb);
mul_m4_v3(ss->cache->symm_rot_mat, rgba);
}
flip_v3_v3(out_offset, rgb, ss->cache->mirror_symmetry_pass);
flip_v3_v3(out_offset, rgba, ss->cache->mirror_symmetry_pass);
}
bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
@ -3262,18 +3316,16 @@ static void do_gravity_task_cb_ex(void *__restrict userdata,
continue;
}
float rgb[3];
const float fade = SCULPT_brush_factor_with_color(ss,
brush,
vd.co,
sqrtf(test.dist),
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
nullptr,
rgb);
const float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
nullptr);
mul_v3_v3fl(proxy[vd.i], offset, fade);

View File

@ -266,24 +266,33 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
/* Offset vertex. */
float rgb[3];
float fade = SCULPT_brush_factor_with_color(ss,
brush,
vd.co,
sqrtf(test.dist),
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
if(ss->cache->brush->flag2 & BRUSH_RGB_AS_VECTOR_DISPLACEMENT
if(ss->cache->brush->flag2 & BRUSH_USE_COLOR_AS_DISPLACEMENT
&& (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)) {
SCULPT_calc_vertex_displacement(ss, rgb, proxy[vd.i]);
float r_rgba[4];
SCULPT_brush_strength_color(ss,
brush,
vd.co,
sqrtf(test.dist),
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
r_rgba);
SCULPT_calc_vertex_displacement(ss, r_rgba, proxy[vd.i]);
}
else {
float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data);
mul_v3_v3fl(proxy[vd.i], offset, fade);
}
@ -312,7 +321,6 @@ void SCULPT_do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
* initialize before threads so they can do curve mapping. */
BKE_curvemapping_init(brush->curve);
/* Threaded loop over nodes. */
SculptThreadedTaskData data = {
.sd = sd,
@ -380,8 +388,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -390,8 +397,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@ -487,8 +493,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -497,8 +502,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@ -614,8 +618,7 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -624,8 +627,7 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@ -778,8 +780,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
if (SCULPT_plane_trim(ss->cache, brush, val)) {
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -788,8 +789,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@ -944,8 +944,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -954,8 +953,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@ -1080,8 +1078,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
/* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
ss->cache->radius * test.dist,
@ -1090,8 +1087,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@ -1242,8 +1238,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
else {
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
fade = bstrength * SCULPT_brush_factor_with_color(ss,
fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -1252,8 +1247,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
}
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
@ -1386,8 +1380,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
sqrtf(test.dist),
@ -1396,8 +1389,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@ -1470,8 +1462,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float vec[3], rot[3][3];
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
sqrtf(test.dist),
@ -1480,8 +1471,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
sub_v3_v3v3(vec, orig_data.co, ss->cache->location);
axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade);
@ -1551,8 +1541,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = SCULPT_brush_factor_with_color(ss,
const float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -1561,8 +1550,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
const int vi = vd.index;
float *disp_factor;
@ -1673,8 +1661,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -1683,8 +1670,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float val[3];
if (vd.fno) {
@ -1750,8 +1736,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -1760,8 +1745,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@ -1838,8 +1822,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata,
/* Offset vertex. */
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = SCULPT_brush_factor_with_color(ss,
const float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -1848,8 +1831,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float val1[3];
float val2[3];
@ -1963,8 +1945,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -1973,8 +1954,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float disp_center[3];
float x_disp[3];
float z_disp[3];
@ -2088,18 +2068,16 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
float fade = bstrength * SCULPT_brush_factor_with_color(ss,
brush,
orig_data.co,
sqrtf(test.dist),
orig_data.no,
NULL,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
sqrtf(test.dist),
orig_data.no,
NULL,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data);
if (grab_silhouette) {
float silhouette_test_dir[3];
@ -2301,8 +2279,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
/* Offset vertex. */
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = SCULPT_brush_factor_with_color(ss,
const float fade = SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
sqrtf(test.dist),
@ -2311,8 +2288,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@ -2393,8 +2369,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = SCULPT_brush_factor_with_color(ss,
const float fade = SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
sqrtf(test.dist),
@ -2403,8 +2378,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float current_disp[3];
float current_disp_norm[3];
float final_disp[3] = {0.0f, 0.0f, 0.0f};
@ -2559,8 +2533,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = SCULPT_brush_factor_with_color(ss,
const float fade = SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
sqrtf(test.dist),
@ -2569,8 +2542,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co);
if (vd.is_mesh) {
@ -2644,8 +2616,7 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -2654,8 +2625,7 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float limit_co[3];
float disp[3];
@ -2719,8 +2689,7 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -2729,8 +2698,7 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float current_disp[3];
float current_disp_norm[3];
@ -2889,9 +2857,8 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength *
SCULPT_brush_factor_with_color(ss,
SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -2900,8 +2867,7 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
*vd.mask,
vd.vertex,
thread_id,
&automask_data,
rgb) *
&automask_data) *
ss->cache->pressure;
float avg[3], val[3];
@ -2982,8 +2948,7 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
}
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = SCULPT_brush_factor_with_color(ss,
const float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -2992,8 +2957,7 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
if (bstrength > 0.0f) {
(*vd.mask) += fade * bstrength * (1.0f - *vd.mask);

View File

@ -507,9 +507,8 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
dist = dist_to_plane_v3(current_vertex_location, deform_plane);
}
float rgb[3];
const float fade = sim_factor * bstrength *
SCULPT_brush_factor_with_color(ss,
SCULPT_brush_strength_factor(ss,
brush,
current_vertex_location,
dist,
@ -518,8 +517,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float brush_disp[3];

View File

@ -144,9 +144,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
if (face_hidden) {
continue;
}
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -155,8 +153,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
if (fade > 0.05f) {
ss->face_sets[vert_map->indices[j]] = ss->cache->paint_face_set;
@ -168,9 +165,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -179,8 +174,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
if (fade > 0.05f) {
SCULPT_vertex_face_set_set(ss, vd.vertex, ss->cache->paint_face_set);
@ -231,8 +225,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
continue;
}
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -241,8 +234,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co);
if (vd.is_mesh) {

View File

@ -1242,25 +1242,38 @@ const float *SCULPT_brush_frontface_normal_from_falloff_shape(SculptSession *ss,
char falloff_shape);
/**
* Return a color and grayscale of a brush texture at a particular vertex multiplied by active masks.
* The grayscale value is usually multiplied by the offset vector and the color is used for non-linear vertex displacement.
* Return a multiplier for brush strength on a particular vertex.
*/
float SCULPT_brush_factor_with_color(struct SculptSession *ss,
const struct Brush *brush,
const float point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
int thread_id,
struct AutomaskingNodeData *automask_data,
float rgb[3]);
float SCULPT_brush_strength_factor(struct SculptSession *ss,
const struct Brush *brush,
const float point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
int thread_id,
struct AutomaskingNodeData *automask_data);
/**
* Return a color of a brush texture on a particular vertex multiplied by active masks.
*/
void SCULPT_brush_strength_color(struct SculptSession *ss,
const struct Brush *brush,
const float brush_point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
int thread_id,
struct AutomaskingNodeData *automask_data,
float r_rgba[4]);
/**
* Calculates the vertex offset for a single vertex depending on the brush setting rgb as vector displacement.
*/
void SCULPT_calc_vertex_displacement(SculptSession *ss, float rgb[3], float out_offset[3]);
void SCULPT_calc_vertex_displacement(SculptSession *ss, float rgba[3], float out_offset[3]);
/**
* Tilts a normal by the x and y tilt values using the view axis.

View File

@ -72,8 +72,7 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
/* Use the brush falloff to weight the sampled normals. */
float rgb[3];
const float fade = SCULPT_brush_factor_with_color(ss,
const float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -82,8 +81,7 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
/* Sample the normal and area of the +X and -X axis individually. */
if (local_co[0] > 0.0f) {
@ -189,9 +187,8 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
/* Deform the local space along the Y axis to avoid artifacts on curved strokes. */
/* This produces a not round brush tip. */
float rgb[3];
local_co[1] *= 2.0f;
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
len_v3(local_co),
@ -200,8 +197,7 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);

View File

@ -59,8 +59,7 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -69,8 +68,7 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float smooth_color[4];
SCULPT_neighbor_color_average(ss, smooth_color, vd.vertex);
@ -155,8 +153,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
float fade = bstrength * SCULPT_brush_factor_with_color(ss,
float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
distance_to_stroke_location,
@ -165,8 +162,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
/* Density. */
float noise = 1.0f;
@ -413,8 +409,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -423,8 +418,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float current_disp[3];
float current_disp_norm[3];

View File

@ -174,8 +174,7 @@ template<typename ImageBuffer> class PaintingKernel {
const float3 face_normal(0.0f, 0.0f, 0.0f);
const float mask = 0.0f;
float rgb[3];
const float falloff_strength = SCULPT_brush_factor_with_color(
const float falloff_strength = SCULPT_brush_strength_factor(
ss,
brush,
pixel_pos,
@ -185,8 +184,7 @@ template<typename ImageBuffer> class PaintingKernel {
mask,
BKE_pbvh_make_vref(PBVH_REF_NONE),
thread_id,
automask_data,
rgb);
automask_data);
float4 paint_color = brush_color * falloff_strength * brush_strength;
float4 buffer_color;
blend_color_mix_float(buffer_color, color, paint_color);

View File

@ -206,8 +206,7 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -216,8 +215,7 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float disp[3];
madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade);
@ -298,8 +296,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(
const float fade = bstrength * SCULPT_brush_strength_factor(
ss,
brush,
vd.co,
@ -309,8 +306,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
if (smooth_mask) {
float val = SCULPT_neighbor_mask_average(ss, vd.vertex) - *vd.mask;
val *= fade * bstrength;
@ -478,8 +474,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -488,8 +483,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
float disp[3];
SCULPT_surface_smooth_laplacian_step(
@ -528,8 +522,7 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex(
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float rgb[3];
const float fade = bstrength * SCULPT_brush_factor_with_color(ss,
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
@ -538,8 +531,7 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex(
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
rgb);
&automask_data);
SCULPT_surface_smooth_displace_step(
ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.vertex, beta, fade);
}

View File

@ -412,7 +412,7 @@ typedef enum eBrushFlags2 {
BRUSH_CLOTH_USE_COLLISION = (1 << 6),
BRUSH_AREA_RADIUS_PRESSURE = (1 << 7),
BRUSH_GRAB_SILHOUETTE = (1 << 8),
BRUSH_RGB_AS_VECTOR_DISPLACEMENT = (1 << 9),
BRUSH_USE_COLOR_AS_DISPLACEMENT = (1 << 9),
} eBrushFlags2;
typedef enum {

View File

@ -2893,10 +2893,10 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Texture Sample Bias", "Value added to texture samples");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_rgb_as_vector_displacement", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_RGB_AS_VECTOR_DISPLACEMENT);
RNA_def_property_ui_text(prop, "RGB as vector displacement",
"Handles each pixel as individual vector for displacement. Works only with area plane mapping");
prop = RNA_def_property(srna, "use_color_as_displacement", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_USE_COLOR_AS_DISPLACEMENT);
RNA_def_property_ui_text(prop, "Vector Displacement",
"Handles each pixel color as individual vector for displacement. Works only with area plane mapping");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "normal_weight", PROP_FLOAT, PROP_FACTOR);