diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt_filter_color.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_filter_color.c | 89 |
1 files changed, 80 insertions, 9 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index e4180a36a98..5d4a2c54832 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -109,6 +109,7 @@ static void color_filter_task_cb(void *__restrict userdata, } copy_v3_v3(orig_color, orig_data.col); + final_color[3] = orig_data.col[3]; /* Copy alpha */ switch (mode) { case COLOR_FILTER_FILL: { @@ -128,8 +129,14 @@ static void color_filter_task_cb(void *__restrict userdata, break; case COLOR_FILTER_SATURATION: rgb_to_hsv_v(orig_color, hsv_color); - hsv_color[1] = clamp_f(hsv_color[1] + fade, 0.0f, 1.0f); - hsv_to_rgb_v(hsv_color, final_color); + + if (hsv_color[1] != 0.0f) { + hsv_color[1] = clamp_f(hsv_color[1] + fade, 0.0f, 1.0f); + hsv_to_rgb_v(hsv_color, final_color); + } + else { + copy_v3_v3(final_color, orig_color); + } break; case COLOR_FILTER_VALUE: rgb_to_hsv_v(orig_color, hsv_color); @@ -186,7 +193,32 @@ static void color_filter_task_cb(void *__restrict userdata, float col[4]; SCULPT_vertex_color_get(ss, vd.index, col); - blend_color_interpolate_float(final_color, col, smooth_color, fade); + if (fade < 0.0f) { + interp_v4_v4v4(smooth_color, smooth_color, col, 0.5f); + } + + bool copy_alpha = col[3] == smooth_color[3]; + + if (fade < 0.0f) { + float delta_color[4]; + + /* Unsharp mask. */ + copy_v4_v4(delta_color, ss->filter_cache->pre_smoothed_color[vd.index]); + sub_v4_v4(delta_color, smooth_color); + + copy_v4_v4(final_color, col); + madd_v4_v4fl(final_color, delta_color, fade); + } + else { + blend_color_interpolate_float(final_color, col, smooth_color, fade); + } + + CLAMP4(final_color, 0.0f, 1.0f); + + /* Prevent accumulated numeric error from corrupting alpha. */ + if (copy_alpha) { + final_color[3] = smooth_color[3]; + } break; } } @@ -201,6 +233,46 @@ static void color_filter_task_cb(void *__restrict userdata, BKE_pbvh_node_mark_update_color(data->nodes[n]); } +static void sculpt_color_presmooth_init(SculptSession *ss) +{ + int totvert = SCULPT_vertex_count_get(ss); + + if (!ss->filter_cache->pre_smoothed_color) { + ss->filter_cache->pre_smoothed_color = MEM_malloc_arrayN( + totvert, sizeof(float) * 4, "ss->filter_cache->pre_smoothed_color"); + } + + for (int i = 0; i < totvert; i++) { + SCULPT_vertex_color_get(ss, i, ss->filter_cache->pre_smoothed_color[i]); + } + + for (int iteration = 0; iteration < 2; iteration++) { + for (int i = 0; i < totvert; i++) { + float avg[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + int total = 0; + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { + float col[4] = {0}; + + copy_v4_v4(col, ss->filter_cache->pre_smoothed_color[ni.index]); + + add_v4_v4(avg, col); + total++; + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + + if (total > 0) { + mul_v4_fl(avg, 1.0f / (float)total); + interp_v4_v4v4(ss->filter_cache->pre_smoothed_color[i], + ss->filter_cache->pre_smoothed_color[i], + avg, + 0.5f); + } + } + } +} + static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent *event) { Object *ob = CTX_data_active_object(C); @@ -227,6 +299,10 @@ static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent RNA_float_get_array(op->ptr, "fill_color", fill_color); IMB_colormanagement_srgb_to_scene_linear_v3(fill_color); + if (filter_strength < 0.0 && !ss->filter_cache->pre_smoothed_color) { + sculpt_color_presmooth_init(ss); + } + SculptThreadedTaskData data = { .sd = sd, .ob = ob, @@ -273,12 +349,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent return OPERATOR_CANCELLED; } - if (!SCULPT_has_colors(ss)) { - return OPERATOR_CANCELLED; - } - SCULPT_undo_push_begin(ob, "color filter"); - BKE_sculpt_color_layer_create_if_needed(ob); /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of @@ -310,7 +381,7 @@ void SCULPT_OT_color_filter(struct wmOperatorType *ot) /* api callbacks */ ot->invoke = sculpt_color_filter_invoke; ot->modal = sculpt_color_filter_modal; - ot->poll = SCULPT_vertex_colors_poll; + ot->poll = SCULPT_mode_poll; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; |