Sign in to follow this  
AbsolutDew

Alpha blending woes

Recommended Posts

I have a particle texture with an alpha channel and I'm using Direct3D. After experimentation I found that SrcBlend = SrcAlpha and DestBlend = InvSrcAlpha seems to do what I want (render my particle with a specified color, don't blend with the background, and dont draw the transparent parts of the texture). Short question: I'm trying to make particles fade out. I can change their color but changing the alpha has no effect. I assume this is a blending problem because if I turn it off the particles fade like I expected (but the transparent parts are drawn, obviously). Longer question: What is SrcBlend and DestBlend? I vaguely understand that setting one of these to, say, D3DBLEND_SRCALPHA multiplies all the colors of the texture by the value of the alpha channel, but little else. Apologies if my questions are poor, I'm struggling with a lot of new (to me) things right now.

Share this post


Link to post
Share on other sites
Quote:
Original post by AbsolutDew
After experimentation I found that SrcBlend = SrcAlpha and DestBlend = InvSrcAlpha seems to do what I want (render my particle with a specified color, don't blend with the background, and dont draw the transparent parts of the texture).

Longer question: What is SrcBlend and DestBlend?


Basically, these are the parameters to decide how much of the 'src' and 'dest' pixel to put in the replacement pixel that you're generating. 'SrcBlend = SrcAlpha' means 'take an amount from the src image (your particle in this case) proportional to the source's alpha'. 'DestBlend = InvSrcAlpha' means 'take an amount from the dest image (whatever was previously rendered) inversely proportional to the source's alpha'. So if your particle's alpha value for a given pixel was 0.75, the new pixel would be (particleRGB * 0.75) + (screenRGB * 0.25).

Now, I'm no 3D expert, certainly not with modern hardware, so this next advice may no longer apply. However, as well as there being per-pixel alpha (which is in your alpha channel), there is per-vertex alpha, which you specify when sending the polygons to be rendered. By changing this on all applicable vertices from the default of 1.0 to something lower, you can effectively fade out the whole polygon. How to do this probably depends on how you're rendering those particles.

Share this post


Link to post
Share on other sites
Haven't specifically used it, but it sounds like what your lookin for.


SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, true)
SetRenderState(D3DRS_SRCBLENDALPHA,D3DBLEND_SRCALPHA)
SetRenderState(D3DRS_DESTBLENDALPHA,D3DBLEND_INVSRCALPHA)

static int BlendIn;
static D3DCOLOR BlendOut;

BlendIn = 255; // <-- control transparency here, 0 to 255 value
BlendOut=D3DCOLOR_ARGB(BlendIn,BlendIn,BlendIn,BlendIn);
d3ddev->SetRenderState(D3DRS_BLENDFACTOR, BlendOut);
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BLENDFACTOR)
SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVBLENDFACTOR)






This should blend your alpha seperately and allow src / dest blending seperately in a fading fashion by controlling the blendfactor :)

Let me know how this works... I'm makin it up as I go.

[Edited by - Ebola0001 on September 8, 2006 6:55:36 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Kylotan
Basically, these are the parameters to decide how much of the 'src' and 'dest' pixel to put in the replacement pixel that you're generating. 'SrcBlend = SrcAlpha' means 'take an amount from the src image (your particle in this case) proportional to the source's alpha'. 'DestBlend = InvSrcAlpha' means 'take an amount from the dest image (whatever was previously rendered) inversely proportional to the source's alpha'. So if your particle's alpha value for a given pixel was 0.75, the new pixel would be (particleRGB * 0.75) + (screenRGB * 0.25).


Seems kinda obvious now! Guess I just didn't understand how it fit together.

Quote:
Original post by Ebola0001
This should blend your alpha seperately and allow src / dest blending seperately in a fading fashion by controlling the blendfactor :)


Thanks! I'll try to work with that when I get home. Seems like a lot of extra work though =/ Why doesn't it just use the alpha value from my vertex (like how Kylotan described). Should it be?

Share this post


Link to post
Share on other sites
Which version of DirectX are you using? Each has different ways of handling things, due to the rapid changes in graphics technology. It is perhaps because you've missed a setting somewhere (D3DRS_ALPHABLENDENABLE?)

Share this post


Link to post
Share on other sites
Quote:
Original post by Kylotan
Which version of DirectX are you using? Each has different ways of handling things, due to the rapid changes in graphics technology. It is perhaps because you've missed a setting somewhere (D3DRS_ALPHABLENDENABLE?)


I'm using DX9. I'm using a shader to texture/change color of particles (modified and tinkered with from an example I found in the SDK). I'm obviously no shader expert but I've looked up everything I'm using and to the best of my understanding this isn't doing anything more than setting the texture and vertex color as if I'd done it in code (though it seems a bit like voodoo to me!), it's just convenient for me to "script" my rendering.


float4 Color;

VSTEXTURE_OUTPUT VSTexture
(
float4 Position : POSITION,
float3 Normal : NORMAL,
float2 TexCoord : TEXCOORD0
)
{
VSTEXTURE_OUTPUT Out = (VSTEXTURE_OUTPUT)0;

float3 P = mul(Position, World); // position (view space)
P = mul(float4(P, 1), View); // position (view space)

Out.Position = mul(float4(P, 1), Projection); // projected position
Out.Diffuse = Color;
Out.TexCoord = TexCoord; // texture coordinates

return Out;
}

pass PTexture
{
// single texture/one directional light shader
VertexShader = compile vs_1_1 VSTexture();
PixelShader = NULL;

// texture
Texture[0] = (Tex0);

// enable alpha blending
AlphaBlendEnable = TRUE;
ZWriteEnable = FALSE;
Lighting = FALSE;
SrcBlend = SrcAlpha;
DestBlend = InvSrcAlpha;
}



And then each frame I use:


D3DXCOLOR newColor;
newColor.a = 0.5f;
newColor.r = 1.0f;
newColor.g = 0.0f;
newColor.b = 0.0f;
pEffect->SetFloatArray("Color", newColor, 4);


But no matter what I set a to, it's always rendered fully visible as if a = 1, though I can change the color with r, g, b to whatever I like.


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this