Alpha Blending Effect...

Started by
6 comments, last by MasterWorks 18 years, 7 months ago
Hey all, I am starting off adding a simple particle engine to my project. It works great, and I am able to alpha blend without a problem. However, now I am moving beyond the basics and want to get into realism. The most common fire effect I have seen is the blend method where if two identical colors are drawn over one another the resulting pixel is drawn lighter, thus giving the white hot center with the darkening fringes... I have played with all my Renderstate properties, but it seems that no matter what I change, I can not get ANY type of change in the rendering of particles. I am using managed DirectX 9, C#. Also using the sprite class, specifically the Draw2D method. Here is the renderstate code. // set device states newDevice.RenderState.Lighting = true; newDevice.RenderState.Ambient = System.Drawing.Color.Gray; //Render States newDevice.RenderState.AlphaBlendEnable = true; newDevice.RenderState.AlphaFunction = Compare.Greater; newDevice.RenderState.AlphaTestEnable = true; newDevice.RenderState.DestinationBlend = Blend.InvSourceAlpha; newDevice.RenderState.SourceBlend = Blend.SourceAlpha; newDevice.RenderState.DiffuseMaterialSource = ColorSource.Material; //Color blending ops newDevice.TextureState[0].ColorOperation = TextureOperation.Modulate; newDevice.TextureState[0].ColorArgument1 = TextureArgument.TextureColor; newDevice.TextureState[0].ColorArgument2 = TextureArgument.Diffuse; //set the first alpha stage to texture alpha newDevice.TextureState[0].AlphaOperation = TextureOperation.SelectArg1; newDevice.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor; On a side note, the ambient color doesn't do anything either. Any help would be appreciated,
Advertisement
I haven't done this in a while, so as a heads up I could be completely wrong. Do you texture you're particles? Try adding a texture to them and then playing around with SetTextureStageState with values from the D3DTEXTUREOP enumeration.
Quote: newDevice.RenderState.AlphaTestEnable = true;
newDevice.RenderState.DestinationBlend = Blend.InvSourceAlpha;
newDevice.RenderState.SourceBlend = Blend.SourceAlpha;

First thing first, alpha test is used to clip off drawing and writing to the z-buffer. So if you sort it right, you shouldnt need it. Second setting those blend factors to InvSourcAlpha and SourceAlpha will just make the texture that has more black in the alpha channel more transparent. So if the alpha channel was 0.0, it would not render anybit of the pixel, and if it was set to 1.0 also in the texture, then it would be completely solid. But that isn't the effect you want, is it? You said you wanted it to add the pixel colors together. So lets do some simple color math.

the simple evaluation:
finalcolor = renderingtexturecolor * sourceblend + alreadydrawncolor * destinationblend

This is what you are currently doing:
finalcolor = firecolor * firealpha + predrawngrid * (1 - firealpha)

But thats not what you want, you want this:
finalcolor = firecolor * one + predrawngrid * 1

So to do that, set your sourceblend and destinationblend = to 1 or i think "Blend.One". I'm not sure if thats right because i program in C++, but the same problem would occur there. Also, now your fire texture won't need an alpha channel, so you can get rid of that. But when you use your fire, make sure that whatever you don't want shown, be in black, and whatever you do want shown, be in your fire color, but maybe a little bit darker. A good fire image should look something like this:

Except it should look like there are flames going up and kinda more realistic, but still with a black background.

I hope this helps. And sorry for the really long tutorial like thing.
I use Visual Basic, but for additive blend, the post above is correct, your factor should be ONE.

Here is what I do, so that you can still have an alpha component in your vertices and thus modulate the strength of the additive blend:

'normal blending
mD3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
mD3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA

'additive blending
mD3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
mD3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_ONE
Hey all,

Many thanks for your replies...

I tried each suggested method individually and when I changed the renderstates nothing happened to the way it was being drawn.

Do the renderstates work with DXSprite.Draw2D? Do I have to set a flag int sprite Begin?

Thanks In Advance,
Update:

If I set the "SpriteFlags.DoNotModifyRenderState" in the Sprite.Begin method, all I get is a black screen.

Update 2:

If I set the "SpriteFlags.None" flag in the Sprite.Begin method, this is my result:



Closer, but the color is now completely stripped out of my sprite... If the outer sprites that were not close the the overlapping middle area were there orignal orange color it would be perfect.

Do I have to draw the tile background sprites with a different render state, then the flame with another? I would assume this is the answer but I really don't know.

Once again, all help is appreciated!!
You have no problem, this is the expected result. You're doing additive blend against a VERY BRIGHT background, which causes clipping and loss of color. Your blue channel is already saturated, and the red and green are too in places, so you're not going to get much detail out of your additive blend.

This topic is closed to new replies.

Advertisement