diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-04-29 21:35:50 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-04-29 21:35:50 +0400 |
commit | f135246c01e7e59c6718c781bbecbdb6eec5bc8b (patch) | |
tree | 3d36298242042e6be89922a75314dbc5e6d9afa1 /source | |
parent | 93e3107806466cc5de64d30298f843505e2b8f79 (diff) |
Fix #35140: texture paint would give 'noisy' strokes and poor results for strokes
crossing themselves.
Again an old issue, the code that was limiting the max contribution to a pixel by
doing a max() operation, which is very sensitive to the spacing of the stroke dabs.
Instead we now use a formula does adds up on repeated dabs but approaches the
maximum brush value slowly and never exceeds it, which gives nice smooth results.
mask_accum = mask_accum + (sqrt(brush_max) - mask_accum) * sqrt(brush_max) * mask;
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image_proj.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index aa43287a551..5dab192e069 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -290,8 +290,8 @@ typedef struct ProjPixel { /* Only used when the airbrush is disabled. * Store the max mask value to avoid painting over an area with a lower opacity * with an advantage that we can avoid touching the pixel at all, if the - * new mask value is lower then mask_max */ - unsigned short mask_max; + * new mask value is lower then mask_accum */ + unsigned short mask_accum; /* for various reasons we may want to mask out painting onto this pixel */ unsigned short mask; @@ -1343,7 +1343,7 @@ static ProjPixel *project_paint_uvpixel_init( projPixel->y_px = y_px; projPixel->mask = (unsigned short)(mask * 65535); - projPixel->mask_max = 0; + projPixel->mask_accum = 0; /* which bounding box cell are we in?, needed for undo */ projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) + @@ -3764,6 +3764,7 @@ static void *do_projectpaint_thread(void *ph_v) float co[2]; unsigned short mask_short; const float brush_alpha = BKE_brush_alpha_get(ps->scene, brush); + const float sqrt_brush_alpha = sqrtf(brush_alpha); const float brush_radius = (float)BKE_brush_size_get(ps->scene, brush); const float brush_radius_sq = brush_radius * brush_radius; /* avoid a square root with every dist comparison */ @@ -3860,7 +3861,7 @@ static void *do_projectpaint_thread(void *ph_v) if (falloff > 0.0f) { float texrgb[3]; - float mask = falloff * brush_alpha; + float mask = falloff; if (ps->is_texbrush) { MTex *mtex = &brush->mtex; @@ -3887,22 +3888,32 @@ static void *do_projectpaint_thread(void *ph_v) mask *= BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool); } - if (!ps->do_masking) { - /* for an aurbrush there is no real mask, so just multiply the alpha by it */ - mask *= ((float)projPixel->mask) * (1.0f / 65535.0f); - } - else { - mask_short = (unsigned short)(projPixel->mask * mask); - - if (mask_short > projPixel->mask_max) { - mask = ((float)mask_short) * (1.0f / 65535.0f); - projPixel->mask_max = mask_short; + if (ps->do_masking) { + /* masking to keep brush contribution to a pixel limited. note we do not do + * a simple max(mask, mask_accum), as this is very sensitive to spacing and + * gives poor results for strokes crossing themselves. + * + * Instead we use a formula that adds up but approaches brush_alpha slowly + * and never exceeds it, which gives nice smooth results. */ + float mask_accum = projPixel->mask_accum; + + mask = mask_accum + (sqrt_brush_alpha * 65535.0f - mask_accum) * sqrt_brush_alpha * mask; + mask_short = (unsigned short)mask; + + if (mask_short > projPixel->mask_accum) { + projPixel->mask_accum = mask_short; + mask = mask_short * (1.0f / 65535.0f); } else { /* Go onto the next pixel */ continue; } } + else + mask *= brush_alpha; + + /* extra mask for normal, layer stencil, .. */ + mask *= ((float)projPixel->mask) * (1.0f / 65535.0f); if (mask > 0.0f) { |