Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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.

share|improve this question

4 Answers 4

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

this.Color.A = weight;

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

share|improve this answer
    
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.. –  Wouter Sep 26 '11 at 18:04
    
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. –  Vigil Sep 26 '11 at 18:07

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.

share|improve this answer
    
It is defined as 0,0,0,0: msdn.microsoft.com/en-us/library/… The issue is probably our custom engine.. –  Wouter Sep 26 '11 at 18:15
    
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. –  Nathan Reed Sep 26 '11 at 18:39
    
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). –  Wouter Sep 27 '11 at 12:14
    
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. –  Nathan Reed Sep 27 '11 at 16:36

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);

share|improve this answer
up vote 2 down vote accepted

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.