Reputation: 3885
I'm trying to implement additive blending, and then alpha blend the result in DirectX9.
Background on which i an rendering:
The image i'm using to additive blend:
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):
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
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:
Upvotes: 2