Skip to main content
GameDev.net gamedev.net
🔒 Locked

D3DXLoadSurfaceFromSurface

Started by ms291052 Oct 11, 2003 at 10:32 PM 29 replies 2.9k views
Original Post
ms291052
ms291052
I am currently rewriting my slow old 2D engine to be a little more efficient. In the old version it copied a bitmap pixel by pixel to the desired surface frame by frame, which was, of course, extraordinarily slow. Now I copy it once, to a stored surface which I then D3DXLoadSurfaceFromSurface to the desired surface. The only problem with this is that with my old version if the current pixel (the one it''s about to copy) matched the ColorKey, it was never copied and with D3DXLoadSurfaceFromSurface it copies black instead, forcing a black rectangle around all my 2D bitmaps I''m trying to display. Is there a way, to simply make D3DXLoadSurfaceFromSurface not touch instead of setting all the ColorKey-colored pixels to black?
ms291052
ms291052
hmmm.. It appears as though D3DXLoadSurfaceFromSurface is doing its job after all. It''s setting the appropriate pixels to ARGB(0,0,0,0) but my program''s still rendering them and I''m not quite sure why...
Nik02
Nik02
You should set the alpha blending related renderstates for the transparency to work.
Use the search function, this has been discussed many, many times here...

-Nik
Niko Suni
ms291052
ms291052

g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

I have ALPHABLENDENABLE as well as SRC and DEST BLENDs. Did I leave out any other important ones?
Nik02
Nik02
Those seem OK. What about texture stage states? In particular, alpha source state?

-Nik

EDIT:
Use D3DBLEND_INVSRCALPHA for dest factor, see if that has any effect (i doubt it).

[edited by - Nik02 on October 12, 2003 5:08:17 AM]
Niko Suni
ms291052
ms291052

g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );

EDIT:
D3DBLEND_INVSRCALPHA had no effect either

[edited by - ms291052 on October 12, 2003 5:19:00 AM]
Nik02
Nik02
Are you ABSOLUTELY sure that the texture really contains an alpha channel? Just ruling out the possibilities

-Nik
Niko Suni
ms291052
ms291052
The BMP doesn''t but the pixels do when they get to the surface... Assuming all unshown functions work (they do) here''s my code:

void CBitmap::DrawBitmap(DWORD* pDestData, int DestPitch, LPDIRECT3DSURFACE9 pDestSurface)
{
if(!RenderedOnce)
{
D3DLOCKED_RECT LockedRect;
pDestSurface->LockRect(&LockedRect, NULL, 0);
pDestSurface->UnlockRect();
pDestData = (DWORD*)LockedRect.pBits;
DestPitch = LockedRect.Pitch;

RenderedOnce = true;
LoadBitmapToSurface(strPathName, &pBitmapSurface, g_pd3dDevice);
D3DSURFACE_DESC d3dsd;
pBitmapSurface->GetDesc(&d3dsd);
width = d3dsd.Width;
height = d3dsd.Height;
HRESULT r = 0;
int OffsetX = 0, OffsetY = 0;
POINT BmpDestPoint = {0,0};
RECT BmpRect = {0,0,0,0};
OffsetX = rect.left;
OffsetY = rect.top;
SetRect(&BmpRect, OffsetX, OffsetY, rect.right, rect.bottom);
BmpDestPoint.x = x;
BmpDestPoint.y = y;
D3DLOCKED_RECT LockedBitmap;
r = pBitmapSurface->LockRect(&LockedBitmap, 0, D3DLOCK_READONLY);
if(FAILED(r))
return;
DWORD* pBMPData = (DWORD*)LockedBitmap.pBits;
LockedBitmap.Pitch /= 4;
DestPitch /= 4;
int BMPOffset = OffsetY * LockedBitmap.Pitch + OffsetX;
int DestOffset = y * DestPitch + x;
for(int cy = 0; cy < (rect.bottom - rect.top); cy++)
{
for(int cx = 0; cx < (rect.right - rect.left); cx++)
{
if(bTransparent)
{
if(pBMPData[BMPOffset] != ColorKey)
pDestData[DestOffset] = pBMPData[BMPOffset];
else
pBMPData[BMPOffset] = D3DCOLOR_ARGB(0, 255, 0, 255);
}
else
{
pDestData[DestOffset] = pBMPData[BMPOffset];
}
BMPOffset++;
DestOffset++;
}
DestOffset += DestPitch - (rect.right - rect.left);
BMPOffset += LockedBitmap.Pitch - (rect.right - rect.left);
}
pBitmapSurface->UnlockRect();
cout << "Copying..." << endl;
}
RECT rect3 = {x, y, x + width, y + height};
D3DXLoadSurfaceFromSurface(pDestSurface, NULL,&rect3,pBitmapSurface,NULL,NULL,D3DX_DEFAULT,D3DCOLOR_ARGB(0, 255, 0, 255));
}

and the ColorKey is (255, 0, 255).
And for what it''s worth:

class CBitmap
{
public:
char* strPathName;
int x, y, height, width, xVel, yVel;
BOOL bTransparent;
BOOL RenderedOnce;
BOOL draw;
D3DCOLOR ColorKey;
RECT rect;
LPDIRECT3DSURFACE9 pBitmapSurface;
CBitmap();
~CBitmap();
void DrawBitmap(DWORD* pDestData, int DestPitch, LPDIRECT3DSURFACE9);
void Update();
void GetBounds(RECT* prect);
BOOL Intersects(CBitmap* cbmp);
};
Nik02
Nik02
Can you spot a bug?


if(bTransparent)
{
if(pBMPData[BMPOffset] != ColorKey)
pDestData[DestOffset] = pBMPData[BMPOffset];
else
pBMPData[BMPOffset] = D3DCOLOR_ARGB(0, 255, 0, 255);
}
else
{
pDestData[DestOffset] = pBMPData[BMPOffset];
}


-Nik

[edited by - Nik02 on October 12, 2003 5:40:51 AM]
Niko Suni
ms291052
ms291052
err...
test pixel against the color key... if it''s not the same, then copy it, otherwise set it to (0, 255, 0, 255)

unless I''m missing something, that code''s clean (although I''m known for missing the obvious)
Nik02
Nik02
You seem to set the source pixel to transparent, instead of destination pixel:


pBMPData[BMPOffset] = D3DCOLOR_ARGB(0, 255, 0, 255);

//should probably be:

pDestData[DestOffset] = D3DCOLOR_ARGB(0, 255, 0, 255);


You missed the obvious

-Nik
Niko Suni
ms291052
ms291052
pDestData[DestOffset] = D3DCOLOR_ARGB(0, 255, 0, 255);
definately changed something but it's not perfect yet

we went from the left to the right here. The right side is the original.


EDIT:
if I change the ColorKey paramater of D3DXLoadSurfaceFromSurface(...) to D3DCOLOR_ARGB(0, 255, 0, 255) instead of D3DCOLOR_ARGB(255, 255, 0, 255), we go back to the left side.

[edited by - ms291052 on October 12, 2003 6:03:42 AM]
Nik02
Nik02
Do you clear to black? If so, then the code works!


-Nik

EDIT:
change this:

D3DCOLOR_ARGB(0, 255, 0, 255);


to this:

D3DCOLOR_ARGB(255, 0, 255, 0);


[edited by - Nik02 on October 12, 2003 6:04:16 AM]
Niko Suni
ms291052
ms291052
I''m clearing to black but I have other things behind the bitmap (that grey stuff behind the bitmap is part of something larger).
ms291052
ms291052
eh, if my pDestData[DestOffset] and my ColorKey (passed to D3DXCreateSurfaceFromSurface) are the same, I get the *non-* transparent black background, otherwise it shows the original (pink) background.

Edit:
D3DCOLOR_ARGB(255, 0, 255, 0) -> Black Background.

[edited by - ms291052 on October 12, 2003 6:09:30 AM]
Nik02
Nik02
In case of colorkey pixel, try setting the destination pixel to, pure and simple, 0. That means completely transparent black.

-Nik

EDIT:
And therefore would act as transparent when rendered, assuming the blending states are on.

[edited by - Nik02 on October 12, 2003 6:11:25 AM]
Niko Suni
ms291052
ms291052
Still Black
Nik02
Nik02
Draw the quad last, after any other geometry. It could be that z-buffering is playing tricks here...

-Nik

[edited by - Nik02 on October 12, 2003 6:14:55 AM]
Niko Suni
ms291052
ms291052
It is drawn dead last. Should I try disabling Z-buffering? Should I try it with W-buffering or what?

g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

g_pBackSurf = 0;
g_pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &g_pBackSurf);
Bitmap.DrawBitmap(0, 0, g_pBackSurf);
g_pBackSurf->Release();
g_pBackSurf=0;

g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, 4 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, 2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, 2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, 2 );
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

EDIT:
No good with Z-Buffing off either.

[edited by - ms291052 on October 12, 2003 6:17:13 AM]
Nik02
Nik02
Why do you select arg2''s in the texture stage states, when the texture (by default) is supposed to be in argument 1?

-Nik
Niko Suni

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.