[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [56359] trunk/blender/source/blender: Fix #34233: bad alpha blending for 3D texture painting.

Brecht Van Lommel brechtvanlommel at pandora.be
Sun Apr 28 13:55:41 CEST 2013


Revision: 56359
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=56359
Author:   blendix
Date:     2013-04-28 11:55:41 +0000 (Sun, 28 Apr 2013)
Log Message:
-----------
Fix #34233: bad alpha blending for 3D texture painting. Same changes as the
previous fix for 2D image painting were done, and also:

* For brushes that do masking (keeping the max contribution to a pixel limited),
  the alpha from textures is now part of the mask. In many cases the logic
  worked out the same and where it didn't it used to cause artifacts.

* Color interpolation for smear and soften tools now happens in premultipied
  space, to avoid bleeding of RGB colors from zero alpha areas.

* Fix a few cases where byte <=> float conversion was not doing the proper
  straight <=> premul conversion.

* Replace some float division by constants with multiplications, is faster.

Note: float texture painting seems to have some issues updating the OpenGL
texture, but issue was already there before this commit.

Modified Paths:
--------------
    trunk/blender/source/blender/blenlib/intern/math_color.c
    trunk/blender/source/blender/blenlib/intern/math_color_inline.c
    trunk/blender/source/blender/editors/sculpt_paint/paint_image_proj.c
    trunk/blender/source/blender/imbuf/IMB_imbuf.h
    trunk/blender/source/blender/imbuf/intern/rectop.c

Modified: trunk/blender/source/blender/blenlib/intern/math_color.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_color.c	2013-04-28 11:05:49 UTC (rev 56358)
+++ trunk/blender/source/blender/blenlib/intern/math_color.c	2013-04-28 11:55:41 UTC (rev 56359)
@@ -197,9 +197,9 @@
 	if (hexcol[0] == '#') hexcol++;
 
 	if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi) == 3) {
-		*r = ri / 255.0f;
-		*g = gi / 255.0f;
-		*b = bi / 255.0f;
+		*r = ri * (1.0f / 255.0f);
+		*g = gi * (1.0f / 255.0f);
+		*b = bi * (1.0f / 255.0f);
 		CLAMP(*r, 0.0f, 1.0f);
 		CLAMP(*g, 0.0f, 1.0f);
 		CLAMP(*b, 0.0f, 1.0f);
@@ -394,17 +394,17 @@
 
 void rgb_uchar_to_float(float col_r[3], const unsigned char col_ub[3])
 {
-	col_r[0] = ((float)col_ub[0]) / 255.0f;
-	col_r[1] = ((float)col_ub[1]) / 255.0f;
-	col_r[2] = ((float)col_ub[2]) / 255.0f;
+	col_r[0] = ((float)col_ub[0]) * (1.0f / 255.0f);
+	col_r[1] = ((float)col_ub[1]) * (1.0f / 255.0f);
+	col_r[2] = ((float)col_ub[2]) * (1.0f / 255.0f);
 }
 
 void rgba_uchar_to_float(float col_r[4], const unsigned char col_ub[4])
 {
-	col_r[0] = ((float)col_ub[0]) / 255.0f;
-	col_r[1] = ((float)col_ub[1]) / 255.0f;
-	col_r[2] = ((float)col_ub[2]) / 255.0f;
-	col_r[3] = ((float)col_ub[3]) / 255.0f;
+	col_r[0] = ((float)col_ub[0]) * (1.0f / 255.0f);
+	col_r[1] = ((float)col_ub[1]) * (1.0f / 255.0f);
+	col_r[2] = ((float)col_ub[2]) * (1.0f / 255.0f);
+	col_r[3] = ((float)col_ub[3]) * (1.0f / 255.0f);
 }
 
 void rgb_float_to_uchar(unsigned char col_r[3], const float col_f[3])

Modified: trunk/blender/source/blender/blenlib/intern/math_color_inline.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_color_inline.c	2013-04-28 11:05:49 UTC (rev 56358)
+++ trunk/blender/source/blender/blenlib/intern/math_color_inline.c	2013-04-28 11:55:41 UTC (rev 56359)
@@ -309,8 +309,8 @@
 
 MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
 {
-	float alpha = color[3] / 255.0f;
-	float fac = alpha / 255.0f;
+	float alpha = color[3] * (1.0f / 255.0f);
+	float fac = alpha * (1.0f / 255.0f);
 
 	result[0] = color[0] * fac;
 	result[1] = color[1] * fac;

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-28 11:05:49 UTC (rev 56358)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_image_proj.c	2013-04-28 11:55:41 UTC (rev 56359)
@@ -40,9 +40,10 @@
 #  include "BLI_winstuff.h"
 #endif
 
-#include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "BLI_math_color_blend.h"
 #include "BLI_memarena.h"
 #include "BLI_threads.h"
 #include "BLI_utildefines.h"
@@ -110,26 +111,6 @@
 	return FTOCHAR(val);
 }
 
-#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f)  {                                  \
-	(c)[0] = f_to_char((f)[0]);                                               \
-	(c)[1] = f_to_char((f)[1]);                                               \
-	(c)[2] = f_to_char((f)[2]);                                               \
-	(c)[3] = f_to_char((f)[3]);                                               \
-} (void)0
-
-#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c)  {                                  \
-	(f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]);                                  \
-	(f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]);                                  \
-	(f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]);                                  \
-	(f)[3] = IMAPAINT_CHAR_TO_FLOAT((c)[3]);                                  \
-} (void)0
-
-#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f)  {                                   \
-	(c)[0] = f_to_char((f)[0]);                                               \
-	(c)[1] = f_to_char((f)[1]);                                               \
-	(c)[2] = f_to_char((f)[2]);                                               \
-} (void)0
-
 /* ProjectionPaint defines */
 
 /* approx the number of buckets to have under the brush,
@@ -570,7 +551,7 @@
 			else {
 				float rgba_tmp_f[4];
 				bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y);
-				IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_f);
+				premul_float_to_straight_uchar(rgba, rgba_tmp_f);
 			}
 		}
 		else {
@@ -580,7 +561,7 @@
 			else {
 				unsigned char rgba_tmp[4];
 				bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y);
-				IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, rgba_tmp);
+				straight_uchar_to_premul_float(rgba_fp, rgba_tmp);
 			}
 		}
 	}
@@ -599,7 +580,7 @@
 		if (rgba) {
 			if (ibuf->rect_float) {
 				float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4);
-				IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_fp);
+				premul_float_to_straight_uchar(rgba, rgba_tmp_fp);
 			}
 			else {
 				*((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4));
@@ -611,8 +592,8 @@
 				copy_v4_v4(rgba_fp, (ibuf->rect_float + ((xi + yi * ibuf->x) * 4)));
 			}
 			else {
-				char *tmp_ch = ((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
-				IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, tmp_ch);
+				unsigned char *tmp_ch = ((unsigned char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
+				straight_uchar_to_premul_float(rgba_fp, tmp_ch);
 			}
 		}
 	}
@@ -1192,10 +1173,10 @@
 			project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, rgba_f);
 
 			if (ibuf_other->rect_float) { /* from float to float */
-				mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) / 3.0f) * rgba_f[3];
+				mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) * (1.0f / 3.0f)) * rgba_f[3];
 			}
 			else { /* from char to float */
-				mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) / (256 * 3.0f)) * (rgba_ub[3] / 256.0f);
+				mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) * (1.0f / (255.0f * 3.0f))) * (rgba_ub[3] * (1.0f / 255.0f));
 			}
 
 			BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
@@ -1339,14 +1320,16 @@
 
 	if (ibuf->rect_float) {
 		projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
-		projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0];
-		projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1];
-		projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2];
-		projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3];
+		projPixel->origColor.f[0] = projPixel->pixel.f_pt[0];
+		projPixel->origColor.f[1] = projPixel->pixel.f_pt[1];
+		projPixel->origColor.f[2] = projPixel->pixel.f_pt[2];
+		projPixel->origColor.f[3] = projPixel->pixel.f_pt[3];
+		zero_v4(projPixel->newColor.f);
 	}
 	else {
 		projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4));
-		projPixel->origColor.uint = projPixel->newColor.uint = *projPixel->pixel.uint_pt;
+		projPixel->origColor.uint = *projPixel->pixel.uint_pt;
+		projPixel->newColor.uint = 0;
 	}
 
 	/* screenspace unclamped, we could keep its z and w values but don't need them at the moment */
@@ -1602,9 +1585,9 @@
 static void scale_quad(float insetCos[4][3], float *origCos[4], const float inset)
 {
 	float cent[3];
-	cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0] + origCos[3][0]) / 4.0f;
-	cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) / 4.0f;
-	cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) / 4.0f;
+	cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0] + origCos[3][0]) * (1.0f / 4.0f);
+	cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) * (1.0f / 4.0f);
+	cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) * (1.0f / 4.0f);
 
 	sub_v3_v3v3(insetCos[0], origCos[0], cent);
 	sub_v3_v3v3(insetCos[1], origCos[1], cent);
@@ -1626,9 +1609,9 @@
 static void scale_tri(float insetCos[4][3], float *origCos[4], const float inset)
 {
 	float cent[3];
-	cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) / 3.0f;
-	cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) / 3.0f;
-	cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) / 3.0f;
+	cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) * (1.0f / 3.0f);
+	cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) * (1.0f / 3.0f);
+	cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) * (1.0f / 3.0f);
 
 	sub_v3_v3v3(insetCos[0], origCos[0], cent);
 	sub_v3_v3v3(insetCos[1], origCos[1], cent);
@@ -2193,8 +2176,8 @@
 	/* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
 	 * this is done so we can avoid offsetting all the pixels by 0.5 which causes
 	 * problems when wrapping negative coords */
-	xhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 3.0f)) / ibuf_xf;
-	yhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 4.0f)) / ibuf_yf;
+	xhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE * (1.0f / 3.0f))) / ibuf_xf;
+	yhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE * (1.0f / 4.0f))) / ibuf_yf;
 
 	/* Note about (PROJ_GEOM_TOLERANCE/x) above...
 	 * Needed to add this offset since UV coords are often quads aligned to pixels.
@@ -2477,8 +2460,8 @@
 										if (!is_ortho) {
 											pixelScreenCo[3] = 1.0f;
 											mul_m4_v4((float(*)[4])ps->projectMat, pixelScreenCo); /* cast because of const */
-											pixelScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * pixelScreenCo[0] / pixelScreenCo[3];
-											pixelScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * pixelScreenCo[1] / pixelScreenCo[3];
+											pixelScreenCo[0] = (float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * pixelScreenCo[0] / pixelScreenCo[3];
+											pixelScreenCo[1] = (float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * pixelScreenCo[1] / pixelScreenCo[3];
 											pixelScreenCo[2] = pixelScreenCo[2] / pixelScreenCo[3]; /* Use the depth for bucket point occlusion */
 										}
 
@@ -2976,8 +2959,8 @@
 			mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co);
 
 			/* screen space, not clamped */
-			projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0];
-			projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1];
+			projScreenCo[0] = (float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * projScreenCo[0];
+			projScreenCo[1] = (float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * projScreenCo[1];

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list