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 try to implement a HLSL shader the does the normal Alphablend with premultiplied colors (just as XNA4 does) but depending on some existing colors. One can think of adding a glow to a 2D terrain where the glow should only be applied to the not fully transparent parts of the terrain.

My current code is:

sampler TextureSampler1 : register(s1); // Addition (Terrain-only particles)
sampler TextureSampler2 : register(s2); // Existing (Terrain)

float4 main(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    // Look up color from partly transparent existing texture (premultipied colors)
    float4 existing = tex2D(TextureSampler2, texCoord);

    // For transparent pixels -> Color stays the same
    if ((existing.r + existing.g + existing.b + existing.a) == 0) return existing;

    // Look up color from partly transparent addition-texture (e.g. glow) (using premultipied colors) that should be added to existing color
    float4 addition = tex2D(TextureSampler1, texCoord);

    // Rescale light that is added by existing alpha
    addition.rgb *= existing.a;

    // Use this color to blend
    existing.rgb *= (1 - addition.a) + addition.rgb; 

    return existing;
}

However, there still seems to be a problem with the alpha channel. Any ideas?

share|improve this question
    
You might want to look into the lerp() function to make blending easier. –  ChrisC Jan 25 '13 at 23:05

2 Answers 2

up vote 1 down vote accepted

Your line:

existing.rgb *= (1 - addition.a) + addition.rgb; 

does

existing.rgb = existing.rgb * ((1 - addition.a) + addition.rgb);

what you probably wanted is

existing.rgb = existing.rgb * (1 - addition.a) + addition.rgb;
share|improve this answer

Interestingly, the following code works. But why?

float4 main(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    // Look up color from partly transparent existing texture (premultipied colors)
    float4 existing = tex2D(TextureSampler2, texCoord);

    // For transparent pixels -> Color stays the same
    if ((existing.r + existing.g + existing.b + existing.a) == 0) return existing;

    // Look up color from partly transparent addition-texture (e.g. glow) (premultipied colors) that should be added to existing color
    float4 addition = tex2D(TextureSampler1, texCoord);

    float4 output;

    // Keep light blocking properties
    output.a = existing.a; 
    // Rescale light that is added by existing alpha
    addition.rgb = addition.rgb * existing.a;
    // Use this color to blend
    output.rgb = existing.rgb * (1 - addition.a) + addition.rgb; 

    return output;
}
share|improve this answer
    
Is this an answer to your question or an additional question? If it's an answer, it's a poor one, since good answers should also tell you the why. –  Byte56 Jan 25 '13 at 22:00
    
@Byte56: Sure, I would love to know why. To my knowledge the below code seem equivalent to the upper one. Thos only difference is that the output color is accumulated in existing and not in an additional variable output. I am not sure why this makes a difference here. –  pad_ares Jan 25 '13 at 23:13
1  
Sorry, I didn't understand your reply. I was suggesting that you merge this answer with your question, since it doesn't appear to stand as an answer on its own. –  Byte56 Jan 25 '13 at 23:26
2  
You used the *= operator incorrectly, see my answer. It has a lower precedence than +. Basically everything on the right side of *= gets resolved before executing the multiplication. –  Archy Jan 26 '13 at 1:53

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.