KompjoeFriek
KompjoeFriek

Reputation: 3885

DirectX9 additive blending with alpha

I'm trying to implement additive blending, and then alpha blend the result in DirectX9.

Background on which i an rendering:

Background

The image i'm using to additive blend:

enter image description here

My current render-loop:

// Render loop:
myColor = 0xFFFFFF;
myAlpha = 0xFF;
myColorDraw = DRGBA( GetR(myColor), GetG(myColor), GetB(myColor), alpha );

myD3DSprite->Begin( D3DXSPRITE_ALPHABLEND );

// Default alpha blending
//D3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
//D3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

// Additive blending
D3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR );
D3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );

MyD3DSprite->Draw( myTexture, &myRectSource, NULL, NULL, myColorDraw );
myD3DSprite->End();

If i understand correctly, this will take a pixel from the source (the image I'm using to blend) and multiply that with a pixel from the destination (the texture I'm rendering on, in this case the background).

I think the math is something like this: TARGET = SRC * (DEST * 1). But please correct me if I'm wrong.

This is the result (Which is pretty much what i wanted):

enter image description here

All that is left to do is use the alpha from myColorDraw so i can "fade" the source image, but i have absolutely no clue how to combine these 2 things. (I think multiplying all colors with myColorDraw would also give me the result i want, just as long the alpha is included).

I have fiddled around with using a separate alpha blend:

D3DDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
D3DDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_BLENDFACTOR );
D3DDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVDESTCOLOR);

And i tried adding a TextureStage:

D3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_BLENDDIFFUSEALPHA );
D3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG0,  D3DTA_CURRENT );
D3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1,  D3DTA_DIFFUSE );

But they don't seem to have any effect on the result. I'm probably doing this completely wrong because my knowledge of DirectX and rendering in general is very limited. Can someone please point me in the right direction?

-- edit --

I may have forgot to mention that anything can be in the background. I just used a single (background)image for this question so the wanted result would be clear.

Upvotes: 2

Views: 2633

Answers (1)

Mykola
Mykola

Reputation: 3373

You in this case must not use alpha for this all, simply use texture color coeficients RGB.

Here is simple pixel shader for this texture blending:

struct PS_INPUT 
{
   float2 TexCoord : TEXCOORD0;
};

sampler Texture0;
sampler Texture1;

float color; // blend color factor

float4 ps_main(PS_INPUT Input) : COLOR0
{   
   return clamp(tex2D(Texture0, Input.TexCoord) + 
                tex2D(Texture1, Input.TexCoord) * abs(color), 0, 1);
}

With the Direct3D API

To select backgound color as argument of colorop use

device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);

With previously specified difuse color of primitive material.

Or using some constant color

device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_CONSTANT);
device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);

specified by

device->SetTextureStageState(0, D3DTSS_CONSTANT, /* D3DCOLOR HERE */);

the second texture

device->SetTexture(1, tex);
device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);

And the result:

enter image description here

Upvotes: 2

Related Questions