Jump to content
  • Advertisement
Sign in to follow this  
odyodyodys

Alpha Blending of D3DTexture9

This topic is 3693 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

Hi all, I have a texture (IDirect3DTexture9) and want to alpha blend an image on it.. I thought this would be an easy part, but I am in trouble now... What I am trying to do is simple: Copy an alpha blended image on top of that texture
// Get the texture from the Allcator presenter (Because Im using Vmr9 + allocator presenter)
CComPtr<IDirect3DTexture9> texture;
presentationInfo->lpSurf->GetContainer( IID_IDirect3DTexture9, (LPVOID*) &(texture.p) );

// Create a surface from that texture
CComPtr<IDirect3DSurface9> baseSurface;
texture->GetSurfaceLevel(0, &baseSurface);


// Create a surface from the image file
CComPtr<IDirect3DSurface9> imageSurface;

direct3DDevice->CreateOffscreenPlainSurface(640, 480, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &imageSurface, NULL);

D3DXLoadSurfaceFromFile(imageSurface.p, NULL, NULL, L"c:\\1.bmp", NULL, D3DX_DEFAULT, 0, NULL);


// Stretch images
direct3DDevice->StretchRect(imageSurface.p, NULL, baseSurface.p, NULL, D3DTEXF_NONE );


This works ok, but I don't have alpha blending.. (No errors returned) The image covers the whole texture.. (The bmp has an alpha channel of course..) I read that this can also be done with ID3DXSprite, but I don't know where to start. Are there any easy or difficult ways to copy an image onto a texture with alpha? P.S. Everything uses D3DPOOL_DEFAULT. Also, on the D3DDevice initialization: direct3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); direct3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); direct3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); direct3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); direct3DDevice->SetRenderState(D3DRS_ALPHAREF, 0x00); direct3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);

Share this post


Link to post
Share on other sites
Advertisement
You can't copy onto a texture and do alpha blending since the pixels are just replaced.

If you want to alpha blend two or more images, you'll have to do a render-to-texture, using the target texture as a render target.
However, it'll be far easier to just alpha blend to the backbuffer using ID3DXSprite. You'd just render all your textures on top of each other as seperate Draw() calls.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
If you want to alpha blend two or more images, you'll have to do a render-to-texture, using the target texture as a render target.
However, it'll be far easier to just alpha blend to the backbuffer using ID3DXSprite. You'd just render all your textures on top of each other as seperate Draw() calls.


Thanks for your reply,
but it was not that helpful cause I am beginner in d3d!

Is it possible to explain some more?

Share this post


Link to post
Share on other sites
Quote:
Original post by odyodyodys
Quote:
Original post by Evil Steve
If you want to alpha blend two or more images, you'll have to do a render-to-texture, using the target texture as a render target.
However, it'll be far easier to just alpha blend to the backbuffer using ID3DXSprite. You'd just render all your textures on top of each other as seperate Draw() calls.


Thanks for your reply,
but it was not that helpful cause I am beginner in d3d!

Is it possible to explain some more?
Use D3DXCreateSprite to get an ID3DXSprite interface at load time, and then load any textures you want using D3DXCreateTextureFromFile or D3DXCreateTextureFromFileEx. Then, to alpha blend the textures together, just render them on top of each other:

LPD3DXSPRITE pSprite; // Your sprite, initialised from D3DXCreateSprite
LPDIRECT3DTEXTURE9 pTex1, pTex2, pTex3; // Your textures, initialised from D3DXCreateTextureFromFile[Ex]

// Begin sprite rendering
if(SUCCEEDED(pSprite->Begin(D3DXSPRITE_ALPHABLEND)))
{
D3DXVECTOR3 vPos(0, 0, 0); // Position to draw the blended textures at

pSprite->Draw(pTex1, NULL, NULL, &vPos, D3DCOLOR_RGBA(255, 255, 255, 255));
pSprite->Draw(pTex2, NULL, NULL, &vPos, D3DCOLOR_RGBA(255, 255, 255, 255));
pSprite->Draw(pTex3, NULL, NULL, &vPos, D3DCOLOR_RGBA(255, 255, 255, 255));
pSprite->End();
}


That'll draw all three textures, alpha blended together in the top left of the backbuffer.

Share this post


Link to post
Share on other sites
Thank you!

That was really helpful..

Unfortunately, I cannot use this method cause I have implemented an Allocator-Presenter filter to use with VMR9 in a custom video player.
This brings me a texture with the current frame on it.
I want to draw an image (eg. logo) on top of this frame..

What I've done till now is the following:

// I have the texture (frame) in the "texture" variable which is a ID3DTexture9.

// 1. Get the surface description from the texture.
D3DSURFACE_DESC surfaceInfo;
texture->GetLevelDesc(0, &surfaceInfo);

//2. Create a new surface
CComPtr<IDirect3DSurface9> firstSurface;
hr = _direct3DDevice->CreateOffscreenPlainSurface(surfaceInfo.Width, surfaceInfo.Height, surfaceInfo.Format, D3DPOOL_SYSTEMMEM, &(firstSurface.p), NULL );

//3. get the surface from the texture
hr = texture->GetSurfaceLevel(0, &(firstSurface.p));

//3.a Create a surface on the System memory (the previous one is on the Device)
CComPtr<IDirect3DSurface9> systemSurface;
hr = _direct3DDevice->CreateOffscreenPlainSurface(surfaceInfo.Width, surfaceInfo.Height, surfaceInfo.Format, D3DPOOL_SYSTEMMEM, &(systemSurface.p), NULL );

// a. Copy from DeviceMem to SystemMem
hr = this->_direct3DDevice->GetRenderTargetData(firstSurface.p, systemSurface.p );

//4. Lock the surface
D3DLOCKED_RECT lockedRect;
hr = systemSurface->LockRect(&lockedRect, NULL, D3DLOCK_DONOTWAIT | D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK);

//5. Create another surface with alpha format in the system memory (so it is possible to blit between alpha surfaces)
CComPtr<IDirect3DSurface9> alphaSystemSurface;
hr = _direct3DDevice->CreateOffscreenPlainSurface(surfaceInfo.Width, surfaceInfo.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &(alphaSystemSurface.p), NULL );

//6. Lock the alphaSurface before blitting
D3DLOCKED_RECT alphaLockedRect;
hr = alphaSystemSurface->LockRect(&alphaLockedRect, NULL, D3DLOCK_DONOTWAIT | D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK);

//7. blit using BitBltFromRGBToRGB function from MediaPlayerClassic source code.
// Dont care about this at the moment. The original surface can be the same as the last one.

//8. Create another surface that does not has alpha color format (this will be updated)
CComPtr<IDirect3DSurface9> noAlphaSystemSurface;
hr = _direct3DDevice->CreateOffscreenPlainSurface(surfaceInfo.Width, surfaceInfo.Height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &(noAlphaSystemSurface.p), NULL );

// 9. Update the surface (copy the noAlpha system surface to device surface) both are of the same format and size.
hr = this->_direct3DDevice->UpdateSurface(noAlphaSystemSurface.p , NULL, firstSurface.p, NULL ); // FAILS with D3DERR_INVALIDCALL (0x8876086c)


// 10. Present the texture. (works ok)


Any suggestions on what am I doing wrong?




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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!