• Advertisement
Sign in to follow this  

How to draw a background picture for 2D

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

i want to use a 640x480 bmp file as background picture for my tiny 2D-game. at first, i attemped to use ID3DXSPRITE to draw it, but it's too slow. perhaps it is because that the bmp file is too large for texture. then i tried to use surface copying. but it didnot work. code as follows:
void initbk()
{...
g_pd3dDevice->CreateOffscreenPlainSurface( Info.Width, Info.Height, Info.Format, D3DPOOL_SYSTEMMEM, &g_pd3dBkSurface, NULL ) £»
D3DXLoadSurfaceFromFile( g_pd3dBkSurface, NULL, NULL, "bk.png", NULL, D3DX_FILTER_NONE, 0, NULL )£»
}
void Render()
{
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
LPDIRECT3DSURFACE9 pbksurface = NULL;
g_pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pbksurface );
g_pd3dDevice->UpdateSurface( g_pd3dBkSurface, NULL, pbksurface, NULL );
pbksurface->Release();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

Share this post


Link to post
Share on other sites
Advertisement
D3DXSprite is a far better way to do what you want.

In what way was it too slow?

What video card/CPU are you testing on?

Share this post


Link to post
Share on other sites
Somebody correct me if I'm wrong but I think a lot of times a texture like this is just upsampled to 1024x512 or something like that. Maybe that could make it slower than expected.

One thing that really pissed me off when first learning D3D is that there's no easy way to just draw a pixel by pixel 'background', you need a large textured quad and the draw time is pretty slow relatively speaking. Expect your framerate to drop a lot, but always remember to track seconds per frame, not (the reciprocal) FPS or you will think it is worse than it really is.

Share this post


Link to post
Share on other sites
Yes, most of the times, (depend on your video driver), your texture would become 1024x512, but no matter what method u use, u will always get that. In my 2d game, my background is 800x600, so I pack other small textures into the same file as 1024x1024, that would save alot of memory.

in terms of performance, my program draws to two monitors on Intel Extreme card, the frame rate on both monitors are 60+.

Share this post


Link to post
Share on other sites
Quote:
Original post by MasterWorks
Somebody correct me if I'm wrong but I think a lot of times a texture like this is just upsampled to 1024x512 or something like that. Maybe that could make it slower than expected.


Providing the card supports D3DPTEXTURECAPS_NONPOW2CONDITIONAL (and you'd be hard-pressed to find one that doesn't these days) you can certainly load and use non-pow2 textures as sprites. In general the speed hit should be that extreme.

Quote:

One thing that really pissed me off when first learning D3D is that there's no easy way to just draw a pixel by pixel 'background', you need a large textured quad and the draw time is pretty slow relatively speaking.

Pixel drawing is slow by its nature. You can however get decent effects by creating a DYNAMIC texture and drawing it as a quad/sprite to the backbuffer after you twiddle its bits.

Share this post


Link to post
Share on other sites
but when i resize the bmp file to 1024x1024, the speed is very slow either. my graphic card is ATI mobile rage, 8M ram. it's most likely that the video memory is not enough for it.

and why i cannot use UpdateSurface in my code to bitblt a surface to backbuffer? is somewhere or other error?

Share this post


Link to post
Share on other sites
There are a lot of limitations on UpdateSurface. You should read the Forum FAQ on debugging D3D apps, it will tell you why it is failing.

There are a number of threads related to sprites on the first page of topics in this forum. You should read them as well since they talk about issues like this.

Share this post


Link to post
Share on other sites
Hi. I have very similar problem - I want to draw with GDI methods on the backbuffer in D3D8. I figured out that only way is to lock backbuffer and copy bits to locked BB memory. You're saying about 2D game - why D3D then? I think that using DirectDraw7 would be somewhat simplier, and I'm sure it'll be MUCH faster. Maybe initialization isn't so trivial as in D3D9, but remember - the APIs with programmer-simple interface are the slowest (simple for programmer OR fast-working - NEVER both).

Share this post


Link to post
Share on other sites
Quote:
Original post by hcZeeWolf
I think that using DirectDraw7 would be somewhat simplier, and I'm sure it'll be MUCH faster.

In general D3D will be MUCH faster because that's what the hardware is tuned for. In this particular case where it's a fairly old chip with little memory, DD might be a better option.

Share this post


Link to post
Share on other sites
I find what the mistake is in my code.
first, Info.Format must equal to backbuffer format in CreateOffscreenPlainSurface.
second, source rect cannot larger than backbuffer in UpdateSurface function. I lose sight of the window's border width and caption height.
fps is ok. I think it is similar to the BitBlt function in DirectDraw7.



void initbk()
{...
g_pd3dDevice->CreateOffscreenPlainSurface( Info.Width, Info.Height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &g_pd3dBkSurface, NULL ) £»
D3DXLoadSurfaceFromFile( g_pd3dBkSurface, NULL, NULL, "bk.png", NULL, D3DX_FILTER_NONE, 0, NULL )£»
}
void Render()
{
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
LPDIRECT3DSURFACE9 pbksurface = NULL;
g_pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pbksurface );
RECT srcrect = { 0, 0, 600, 400 };
g_pd3dDevice->UpdateSurface( g_pd3dBkSurface, &srcrect, pbksurface, NULL );
pbksurface->Release();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}


Share this post


Link to post
Share on other sites
Quote:
Original post by hcZeeWolf
... but remember - the APIs with programmer-simple interface are the slowest (simple for programmer OR fast-working - NEVER both).


I'm curious as to what leads to such a conclusion...

Share this post


Link to post
Share on other sites
Quote:
Original post by MasterWorks
Somebody correct me if I'm wrong but I think a lot of times a texture like this is just upsampled to 1024x512 or something like that. Maybe that could make it slower than expected.

One thing that really pissed me off when first learning D3D is that there's no easy way to just draw a pixel by pixel 'background', you need a large textured quad and the draw time is pretty slow relatively speaking. Expect your framerate to drop a lot, but always remember to track seconds per frame, not (the reciprocal) FPS or you will think it is worse than it really is.


Sprites are rounded up to a power of 2.

Writing the assembly code to blt an image pixel by pixel onto the back buffer is not really that hard. However, if your screen resolution changes, you will need to use a different image.

D3DSprite is the way to go. If its a background, disable z-buffer, alpha-blending, lighting and anything else you don't need, and if the image is to cover the whole screen, don't clear the back buffer each frame, just the z-buffer.

Share this post


Link to post
Share on other sites
Quote:
Original post by DBX
Quote:
Original post by hcZeeWolf
... but remember - the APIs with programmer-simple interface are the slowest (simple for programmer OR fast-working - NEVER both).


I'm curious as to what leads to such a conclusion...


It's an old, simple rule - the fastest code is the one you never call. Compare:


pobj->Init1();
pobj->Init2();
pobj->Init3();

/*
pobj2::Init()
{
pobj->Init1();
pobj->Init2();
pobj->Init3();
}
*/

pobj2->Init();



How do you think, which one is faster? I've had P120 with 4MB card and 24MB RAM for a long time. I run 3D rotating cube written in D3D8 (4 - 8 FPS) - it's code took about 100 lines. Simple to write, slow like sh... I run also height map terrain with ability to "fly" around the scene in pure DOS 6.22 (100 - 120 FPS) - about 4000 lines. Tooks weeks to write, fast like hell. And now you have your answer. Multitasking/threading systems, hardware-independent API's are the point where you loose performance. That's the price for simplicity of code. Greetz.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement