0
\$\begingroup\$

I'm using XNA 4.0 to create a 2D game and while implementing a layer tinting pixel shader I noticed that when the texture's alpha value is anything between 1 or 0 the end result is different than expected.

The tinting works from selecting a colour and setting the amount of tint. This is achieved via the shader which works out first the starting colour (for each r, g, b and a) :

float red = texCoord.r * vertexColour.r;

and then the final tinted colour :

output.r = red + (tintColour.r - red) * tintAmount;

The alpha value isn't tinted and is left as :

output.a = texCoord.a * vertexColour.a;

The picture in the link below shows different backdrops against an energy ball object where it's outer glow hasn't blended as I would like it to. The middle two are incorrect as the second non tinted one should not show a glow against a white BG and the third should be entirely invisible.

The blending function is NonPremultiplied.

enter image description here

Why the alpha value is interfering with the final colour?

| improve this question | | | | |
\$\endgroup\$
  • 2
    \$\begingroup\$ It sounds like a classic issue of not using (or using when you shouldn't) pre multiplied alpha values. \$\endgroup\$ – Phil Mar 25 '13 at 23:28
  • 1
    \$\begingroup\$ Agreed, it sounds like you want the surrounding glow to be additive while the energy ball is opaque. Classic case where premultiplied-alpha images would do the job. Also, tinting is usually done by multiplying the texture color by the tint color, rather than lerping to the tint color as you have it. \$\endgroup\$ – Nathan Reed Aug 7 '13 at 6:25
  • \$\begingroup\$ Thank you for the answers guys! The game has dramatically changed since and I've removed the lerp shader for regular alpha blend rendering. \$\endgroup\$ – MazK Jul 10 '17 at 10:19
1
\$\begingroup\$

This is the best blend function I've found to achieve the results I wanted. I ended up rejigging the render function for the game so that each object can decide which BlendState it wants to use.

This is the BlendState I used, it's the same as NonPremultiplied except AlphaSourceBlend is changed from Blend.SourceAlpha to Blend.One:

BlendState alphaBlend = new BlendState()
{
    AlphaBlendFunction = BlendFunction.Add,
    AlphaSourceBlend = Blend.One,
    AlphaDestinationBlend = Blend.InverseSourceAlpha,

    ColorBlendFunction = BlendFunction.Add,
    ColorSourceBlend = Blend.SourceAlpha,
    ColorDestinationBlend = Blend.InverseSourceAlpha
};
| improve this answer | | | | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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