Page MenuHome

Data Transfer modifier works inconsistently when dealing with Vertex Color Alpha
Closed, ResolvedPublicBUG

Description

System Information
Operating system: Windows-10-10.0.18362-SP0 64 Bits
Graphics card: GeForce GTX 1060 6GB/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 456.71

Blender Version
Broken: version: 2.90.1, branch: master, commit date: 2020-09-23 06:43, hash: rB3e85bb34d0d7
Worked: -

Short description of error
When using DataTransfer modifier to transfer vertex colors from object to another, vertex color alpha interferes with color transfer. Vertex color alpha seems to work as a mask which is not expected.

Exact steps for others to reproduce the error

(See attached blend file for ready-made setup)

  1. Create a cube. Give it a vertex color layer.
  2. Create another cube or plane. Give it fully red, blue or green coloring and erase some parts of its vertex color alpha.
  3. Add Data transfer modifier to the first cube. Copy vertex colors from the other object. Only 'Above' and 'Below threshold' Mix mode settings seems to fully transfer RGB without alpha affecting the transfer.
  4. Create material for the cube that has copied values. Create emissive shader and attach vertex color input node into it.
  5. Check with different mix modes and see how result varies.
  6. Optionally: Apply data transfer and inspect vertex colors. Alpha causes issue with RGB channels.

Event Timeline

Teemu (TMug) updated the task description. (Show Details)
Germano Cavalcante (mano-wii) changed the task status from Needs Triage to Confirmed.Oct 22 2020, 3:20 AM
Germano Cavalcante (mano-wii) changed the subtype of this task from "Report" to "Bug".

I can confirm.
This occurs in older versions like 2.79 as well.
Apparently the alpha value replaces the original color with white.
I don't know why that happens, it seems to be a bug.

Robert Guetzkow (rjg) renamed this task from Data Tranfer works inconsistently when dealing with Vertex Color Alpha to Data Transfer modifier works inconsistently when dealing with Vertex Color Alpha.Oct 23 2020, 12:33 PM

Apparently the alpha value replaces the original color with white.

White is the original vertex color on the destination object - which is not being replaced by red because the source layer has alpha = 0 there.

I don't know why that happens, it seems to be a bug.

This is because modes other than Above Threshold and Below Threshold do real Mixing (btw. I guess it would be good to gray out the Mix factor for the threshold ones).
Mixing is done premultiplied, see layerCopyValue_mloopcol / blend_color_interpolate_byte and the comment in blend_color_interpolate_byte:

/* do color interpolation, but in premultiplied space so that RGB colors
 * from zero alpha regions have no influence */

Doing color interpolation premultiplied is probably usually the right thing to do (it might be different in the context of DataTransfer modifier?), not sure this is a bug, @Bastien Montagne (mont29) or @Brecht Van Lommel (brecht) might know?

To me this looks like what happens when you don't interpolate premultiplied. So I would check if the code is calling this function and that the function is working correctly.

Also, layerCopyValue_mloopcol copying alpha from m1 to m2 rather than using the interpolated alpha is wrong, though I'm not sure that would cause this issue.

To me this looks like what happens when you don't interpolate premultiplied. So I would check if the code is calling this function and that the function is working correctly.

Also, layerCopyValue_mloopcol copying alpha from m1 to m2 rather than using the interpolated alpha is wrong, though I'm not sure that would cause this issue.

Code is called, and I think it does what it advertises: it takes straight input, premultiplies colors with the alpha internally before blending, so you get no color change in the target if the source has another color (but no alpha there).
This is the right thing to do, no? At least this is how layer blending in Gimp etc works afaict.
I think the reason this actually looks "off" in this file is that interpolation of alpha in the viewport on this lowpoly is just not "enough".
It already looks a lot better if you subdivide a bit:

However, I think there is also something wrong with blend_color_interpolate_byte: if the combined alpha (after applying the mix factor) is zero, it would just copy the whole color, but alpha should be zero here?

1
2
3diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
4index eb82bb81a89..7ad4f0d9585 100644
5--- a/source/blender/blenlib/intern/math_color_blend_inline.c
6+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
7@@ -606,6 +606,7 @@ MINLINE void blend_color_interpolate_byte(uchar dst[4],
8 }
9 else {
10 copy_v4_v4_uchar(dst, src1);
11+ dst[3] = 0;
12 }
13 }
14

If that is corrected (otherwise you get popping if a mix factor of one is used), you are right, interpolated alpha should be used:

1
2
3diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
4index 466a0115a9d..8b903b98173 100644
5--- a/source/blender/blenkernel/intern/customdata.c
6+++ b/source/blender/blenkernel/intern/customdata.c
7@@ -751,6 +751,7 @@ static void layerCopyValue_mloopcol(const void *source,
8 m2->r = m1->r;
9 m2->g = m1->g;
10 m2->b = m1->b;
11+ m2->a = m1->a;
12 }
13 else { /* Modes that support 'real' mix factor. */
14 unsigned char src[4] = {m1->r, m1->g, m1->b, m1->a};
15@@ -776,8 +777,8 @@ static void layerCopyValue_mloopcol(const void *source,
16 m2->r = (char)dst[0];
17 m2->g = (char)dst[1];
18 m2->b = (char)dst[2];
19+ m2->a = (char)dst[3];
20 }
21- m2->a = m1->a;
22 }
23
24 static bool layerEqual_mloopcol(const void *data1, const void *data2)
25diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
26index eb82bb81a89..7ad4f0d9585 100644
27--- a/source/blender/blenlib/intern/math_color_blend_inline.c
28+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
29@@ -606,6 +606,7 @@ MINLINE void blend_color_interpolate_byte(uchar dst[4],
30 }
31 else {
32 copy_v4_v4_uchar(dst, src1);
33+ dst[3] = 0;
34 }
35 }
36

Philipp Oeser (lichtwerk) closed this task as Resolved.Wed, Nov 4, 12:43 PM
Philipp Oeser (lichtwerk) claimed this task.

Since rB6a5d2f4ea226: Fix blend_color_interpolate_byte returning wrong alpha in certain case and rB3fc97727df6d: CustomData color copying: use interpolated alpha have been committed, I think the alpha handling is now actually correct.

For the viewport interpolation being "off" on lowres [highres works better - see my example file above], I think this deserves to be a separate report.

Will close this one (feel free to comment again though if issues persist - we can always reopen in that case)