5
\$\begingroup\$

I'm fading an object from fully visible to transparent, but the fade darkens the object.

this.Color = Color.Lerp(Color.White, Color.Transparent, weight);

The object does fade to transparent, but.. It becomes darker and more transparent. There used to be a Color.TransparentWhite and Color.TransparentBlack in the non-premultiplied alpha xna world. How can I make the fade to transparent make the object fade through white to transparent with premultiplied alpha?

We are drawing sprites as quads using GraphicsDevice.DrawUserIndexedPrivitives and BlendState set to BlendState.AlphaBlend. This is supposed to do premultiplied alpha blending in XNA4.

Also, how the color is used in the rendering:

effect.Alpha = this.Color.A / 255f;
effect.DiffuseColor = new Vector3(this.Color.R / 255f, this.Color.G / 255f, this.Color.B / 255f)

I suspect I should not use premultiplied alpha when using Alpha and DiffuseColor to make sprites/texts transparent. However when I use Color.Lerp to fade to new Color(1,1,1,0) it still darkens.

\$\endgroup\$

4 Answers 4

2
\$\begingroup\$

If the color is in premultiplied-alpha form, you'll need to lerp both the RGB and the alpha to zero. Lerping only the alpha to zero would result in an additive blend. I don't know how Color.Transparent is defined, but maybe it's not (0, 0, 0, 0).

If lerping everything to zero still causes the darkening effect, then the color isn't being used as premultiplied-alpha.

\$\endgroup\$
4
  • \$\begingroup\$ It is defined as 0,0,0,0: msdn.microsoft.com/en-us/library/… The issue is probably our custom engine.. \$\endgroup\$
    – Wouter
    Commented Sep 26, 2011 at 18:15
  • \$\begingroup\$ Hmm. I'm confused, then; you say lerping just the alpha results in an additive blend, which seems to suggest the color is being applied as premultiplied-alpha, but lerping both RGB and alpha to zero results in over-darkening the color. It's strange. Maybe gamma correction is coming into play here? Ideally, colors should be lerped in linear space and then converted to gamma space afterward. \$\endgroup\$ Commented Sep 26, 2011 at 18:39
  • \$\begingroup\$ What do you mean with gamma correction? The only color operation I do is listed above, the Color.Lerp between Color(1,1,1,1) and Color(0,0,0,0). \$\endgroup\$
    – Wouter
    Commented Sep 27, 2011 at 12:14
  • \$\begingroup\$ Yes, but if you're not applying gamma transformations correctly in your renderer, that could lead to odd-looking artifacts when operating on colors. See this blog post for more information (this presentation for a deeper dive). If you're not familiar with this topic it's worth a read. This is just a shot in the dark, though; the problem could be something completely different. \$\endgroup\$ Commented Sep 27, 2011 at 16:36
2
\$\begingroup\$

If you want to use the "old ways" of alpha fading, you can disable premultiplied alpha for the specific texture. I doubt there is a noticeable difference between the new and old approaches, but new one may be a little bit darker indeed.

Check your fading texture in the "Properties" tab and set "Premultiply Alpha" to false under "Content Processor" group. If you're using a sprite batch, set it to BlendState.NonPremultiplied before drawing. Then do your interpolation: this.Color = new Color(this.Color.R, this.Color.G, this.Color.B, alphaFade);

\$\endgroup\$
1
\$\begingroup\$

Don't lerp the colour components, just set the alpha:

this.Color.A = weight;

(where weight = 255 if opaque and 0 when transparent)

\$\endgroup\$
2
  • \$\begingroup\$ Doesnt work, this results in additive blending as stated by Nathan Reed. I will check our engine, it might not be set to user premultiplied alpha.. \$\endgroup\$
    – Wouter
    Commented Sep 26, 2011 at 18:04
  • \$\begingroup\$ It would work in XNA 3, but XNA 4 uses premultiplied alpha math in its color: (r, g, b) * a. Changing alpha of existing color this way is wrong. \$\endgroup\$
    – EnoughTea
    Commented Sep 26, 2011 at 18:07
1
\$\begingroup\$

When using effect.DiffuseColor and effect.Opacity you should not use premultiplied color space.

The problem is that I used Color.Lerp:

Color.Lerp(new Color(1,1,1,1), new Color(1,1,1,0), .5f);
color : {R:127 G:127 B:127 A:127}

What I did to solve this is by setting the color to:

effect.Opacity = this.Color.A / 255f;
if (effect.Opacity > 0)
{
    effect.DiffuseColor = new Vector3(this.Color.R / 255f, this.Color.G / 255f, this.Color.B / 255f) / Opacity;
}
else
{
    effect.DiffuseColor = Vector3.Zero;
}

Note the / Opacity to return from premultiplied color space to normal color space.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .