Jump to content
  • Advertisement
Sign in to follow this  
daVinci

Alpha blending with HLSL

This topic is 3403 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. I'm trying to implement alpha blending with HLSL only (without render states and other stuff). I want Multiply, Darken, Overlay and so on. But now I hung up with just normal blending. I have this shader: ... float3 blended = alpha * overlyingRGB + ((1-alpha) * underlyingAlpha * underlyingRGB); return float4(blended, underlyingAlpha + (1-underlyingAlpha)*alpha); ... Note, overlying and underlying are partially transparent This works incorrect (as if darker, maybe) ================================================ Shader code: ================================================ // Input images sampler2D underlyingSampler : register(s0); sampler2D overlyingSampler : register(s1); // Opacity of source image float opacity : register(c0); float4 main(float2 uv : TEXCOORD) : COLOR { float4 overlying = tex2D(overlyingSampler, uv); float4 underlying = tex2D(underlyingSampler, uv); float3 overlyingRGB = overlying.rgb; float3 underlyingRGB = underlying.rgb; float overlyingAlpha = overlying.a; float underlyingAlpha = underlying.a; float alpha = opacity * overlyingAlpha; float3 blended = alpha * overlyingRGB + ((1-alpha) * underlyingAlpha * underlyingRGB); return float4(blended, underlyingAlpha + (1-underlyingAlpha)*alpha); }

Share this post


Link to post
Share on other sites
Advertisement

//////////// STATES ///////////////

BlendState SrcAlphaBlend
{
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA;
DestBlend = INV_SRC_ALPHA;
BlendOp = ADD;
SrcBlendAlpha = ONE;
DestBlendAlpha = ONE;
BlendOpAlpha = ADD;
RenderTargetWriteMask[0] = 0x0F;
};

// SNIP

//--------------------------------------------------------------------------------------
// Transforms positions and copies texture coordinates
//
PS_IN_TINT VS_Tint( VS_IN_TINT input )
{
PS_IN_TINT output = (PS_IN_TINT)0;

// Transform the incoming model-space position to projection space
matrix worldViewProjection = mul( mul(world, view), projection);
output.position = mul( input.position, worldViewProjection);

// Copy the texture coordinate
output.texCoord = input.texCoord;

return output;
}

// SNIP

//--------------------------------------------------------------------------------------
// Colors the object with the diffuse color multiplied by the texture color
//
float4 PS_Tint( PS_IN_TINT input ) : SV_Target
{
return diffuseColor * diffuseTexture.Sample(samplerLinear, input.texCoord);
}

// SNIP

//--------------------------------------------------------------------------------------
//
//
technique10 RenderGlow
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS_Tint() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS_Tint() ) );

SetBlendState( SrcAlphaBlend, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
SetDepthStencilState( DefaultDepthStencil, 0);
}
}




Share this post


Link to post
Share on other sites
In normal blending, the "underlying" alpha value is not used. You are multiplying by it which will make the underlyingRGB color darker, unless that alpha value is 1.

Share this post


Link to post
Share on other sites
Quote:
Original post by kanato
In normal blending, the "underlying" alpha value is not used. You are multiplying by it which will make the underlyingRGB color darker, unless that alpha value is 1.

But I have to use the underlying alpha value.
For ex.,
Underlying 0, 1, 0, 0 (transparent)
Overlying 1, 0, 0, 0.5 (semitransparent red)
Result must be: 1, 0, 0, 0.5 (!)
My equation: 0.5 * (1, 0, 0) + ((1-0.5)*0*(0, 1, 0)) = (0.5, 0, 0)
If not use underlying alpha: 0.5 * (1, 0, 0) + ((1-0.5)*(0, 1, 0)) = (0.5, 0.5, 0)

Share this post


Link to post
Share on other sites
If that is what you want, then you should probably take a min selection of the two components - it doesn't matter what your alpha is on the bottom. So for each component, take the min of the two colors.

I don't think this is strictly speaking alpha blending though - have you checked into how any software renderers function in this regard? It might be worth having a look.

Share this post


Link to post
Share on other sites
I forgot to divide by resulted alpha, the correct in last line:

float resultAlpha = underlyingAlpha + (1-underlyingAlpha)*alpha;
return float4(blended / resultAlpha , resultAlpha);

Now _normal_ blending works correctly (I compared with Photoshop).
But I still don't get how to implement multiply, overlay.. modes.

Share this post


Link to post
Share on other sites
My solution see here http://degtyarevdaniel.blogspot.com/2009/05/advanced-alpha-blending-with-hlsl.html

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!