forked from bartvdbraak/blender
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;
This commit is contained in:
parent
93e3107806
commit
f135246c01
@ -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 (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;
|
||||
|
||||
if (mask_short > projPixel->mask_max) {
|
||||
mask = ((float)mask_short) * (1.0f / 65535.0f);
|
||||
projPixel->mask_max = mask_short;
|
||||
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) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user