[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [56391] trunk/blender/source/blender/ editors/sculpt_paint/paint_image_proj.c: Fix #35140: texture paint would give 'noisy' strokes and poor results for strokes

Brecht Van Lommel brechtvanlommel at pandora.be
Mon Apr 29 19:35:51 CEST 2013


Revision: 56391
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=56391
Author:   blendix
Date:     2013-04-29 17:35:50 +0000 (Mon, 29 Apr 2013)
Log Message:
-----------
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;

Modified Paths:
--------------
    trunk/blender/source/blender/editors/sculpt_paint/paint_image_proj.c

Modified: trunk/blender/source/blender/editors/sculpt_paint/paint_image_proj.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/paint_image_proj.c	2013-04-29 17:16:17 UTC (rev 56390)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_image_proj.c	2013-04-29 17:35:50 UTC (rev 56391)
@@ -290,8 +290,8 @@
 	/* 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 @@
 	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 @@
 	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 @@
 
 					if (falloff > 0.0f) {
 						float texrgb[3];
-						float mask = falloff * brush_alpha;
+						float mask = falloff;
 
 						if (ps->is_texbrush) {
 							MTex *mtex = &brush->mtex;
@@ -3887,23 +3888,33 @@
 							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) {
 
 							/* copy of code above */




More information about the Bf-blender-cvs mailing list