Speeding up 2D rendering in DirectDraw.
I wrote a terrain rendering program, there are 22 tiles in every row,40 tiles in every column.However the fps is not very high, about 18 fps.I set the screen mode in 800 multiply 600, 16 bit color.I think there must be some optimizing method to improve fps.Thanks!
//The code like the following
int iWidth = 22;//27
int iHeight = 40;
int iStartX = ((g_iViewPortX+32)>>6)*2;
int iStartY = ((g_iViewPortY+16)>>5)*2;
RECT rcRect;
for( int w=(iStartX-1>=0?iStartX-1:iStartX);w=0?iStartY-1:iStartY);h<iStartY+iHeight;h++)
{
if(w%2!=h%2) continue;
int offset = CalculateOffSet( w, h );
ClipBlt( g_lpDDSBuffer, (w-1)*32-g_iViewPortX,
(h-1)*16-g_iViewPortY,
g_lpDDSTile,
GetPicArea( offset, &rcRect ),
TRUE );
}
Are the ClipBlt, CalculateOffset and GetPicArea your functions too? If so, could you please post the code to them too. BTW what computer have you got? Perhaps 18 fps isn''t that little after all, if you have an old one.
/John
/John
I am working in a 2D game, using tiles and layers. With the same resolution and bit depth, drawing 680 tiles, and 3 sprites I am getting 70 fps. There are some things to consider, like your computer specs. Make sure you are creating your surfaces in videomemory since this add a great speed boost.
By far, the most time consuming operation is blitting. I've been adding some code to perform collision detection and it has not changed my fps.
Here are my computer specs:
PIII 550
320 MB RAM
GeForce 4 MX 440
Windows 2000
DirectX 8.1
"- To begin with, said the Cat, a dog's not mad. You grant that?
- I suppose so, said Alice.
- Well, then, - the Cat went on - you see, a dog growls when it's angry, and wags its tail when it's pleased. Now I growl when I'm pleased, and wag my tail when I'm angry. Therefore I'm mad."
[edited by - Andre Luiz Silva on April 28, 2003 12:17:08 PM]
By far, the most time consuming operation is blitting. I've been adding some code to perform collision detection and it has not changed my fps.
Here are my computer specs:
PIII 550
320 MB RAM
GeForce 4 MX 440
Windows 2000
DirectX 8.1
"- To begin with, said the Cat, a dog's not mad. You grant that?
- I suppose so, said Alice.
- Well, then, - the Cat went on - you see, a dog growls when it's angry, and wags its tail when it's pleased. Now I growl when I'm pleased, and wag my tail when I'm angry. Therefore I'm mad."
[edited by - Andre Luiz Silva on April 28, 2003 12:17:08 PM]
One of the most common reasons for slow speeds in Directdraw are the ammount of Lock() and UnLock() calls you have in your application. Don''t put Lock and Unlock calls in a loop unless it''s absolutely nessassary.
The second thing is alpha blending can eat much CPU and there is very little you can do to optimize these things so if your doing alpha blending try to minimize it for now and see if that''s causing your slow speeds.
The second thing is alpha blending can eat much CPU and there is very little you can do to optimize these things so if your doing alpha blending try to minimize it for now and see if that''s causing your slow speeds.
In this terrain rendering program, I select the diamond as the base tile with the width of 64 pixels and the height of 32 pixels.The whole terrain is just connected by the diamond. The screen mode is 800 multiply 600, 16 bit color.The code like the following.
My computer status: Celeron 400, 64M, SIS6326 8M video;
The fps is just about 18.But StarCraft could run very quickly though its display mode is somewhat lower than my application.
void DrawTile( )
{
int iWidth = 22;
int iHeight = 40;
int iStartX = ((g_iViewPortX+32)>>6)*2;
int iStartY = ((g_iViewPortY+16)>>5)*2;
RECT rcRect;
for( int w=(iStartX1>=0iStartX1:iStartX);w for( int h=(iStartY-1>=0iStartY1:iStartY);h {
if(w%2!=h%2) continue;
int offset = CalculateOffSet( w, h );
ClipBlt( g_lpDDSBuffer,(w-1)*32-g_iViewPortX,
(h-1)*16-g_iViewPortY,
g_lpDDSTile,
GetPicArea( offset, &rcRect ),
TRUE );
}
}
The function CalculateOffSet( ) is just to compute the index of tile.
The function GetPicArea( ) is just to obtain the rectangle region of image of tile.
The function ClipBlt( ) is just to Display the DirectDrawSurface,supporting the cliping operation.
The code like the following.
//Function:CalculateOffSet( )
int CalculateOffSet( int iTileX, int iTileY )
{
int offset;
if(iTileX%2==0)
{
offset = (iTileY>>1)*(2*g_iMapWidth>>6+1)+(iTileX>>1);
}
else
{
offset =(iTileY>>1+1)*(g_iMapWidth>>6+1)+(iTileY-(iTileY>>1+1))*(g_iMapWidth>>6)+(iTileX>>1);
}
return offset;
}
//Function:GetPicArea( )
RECT* GetPicArea( int iIndex, RECT* prcRect )
{
prcRect->left = (m_pTileData[iIndex].type%3)*64;
prcRect->top = (m_pTileData[iIndex].type/3)*32;
prcRect->right = prcRect->left + TILEWIDTH;
prcRect->bottom = prcRect->top + TILEHEIGHT;
return prcRect;
}
//Function:ClipBlt( )
void ClipBlt( IDirectDrawSurface *pdds1, int iX, int iY,
IDirectDrawSurface *pdds2, RECT *prcArea, BOOL bTrans = TRUE )
{
POINT src;
src.x = iX; src.y = iY;
RECT rcRect;
rcRect.left = prcArea->left; rcRect.top = prcArea->top;
rcRect.right= prcArea->right; rcRect.bottom = prcArea->bottom;
if(iX<0)
{
rcRect.left = prcArea->left - iX;
src.x = 0;
}
if(iY<0)
{
rcRect.top = prcArea->top - iY;
src.y = 0;
}
if(iX+prcArea->right-prcArea->left>800)
{
rcRect.right = prcArea->left + (800-iX);
}
if(iY+prcArea->bottom-prcArea->top>600)
{
rcRect.bottom = prcArea->top + (600-iY);
}
pdds1->BltFast( src.x, src.y, pdds2, &rcRect, bTrans?DDBLTFAST_SRCCOLORKEY:FALSE );
}
My computer status: Celeron 400, 64M, SIS6326 8M video;
The fps is just about 18.But StarCraft could run very quickly though its display mode is somewhat lower than my application.
void DrawTile( )
{
int iWidth = 22;
int iHeight = 40;
int iStartX = ((g_iViewPortX+32)>>6)*2;
int iStartY = ((g_iViewPortY+16)>>5)*2;
RECT rcRect;
for( int w=(iStartX1>=0iStartX1:iStartX);w for( int h=(iStartY-1>=0iStartY1:iStartY);h {
if(w%2!=h%2) continue;
int offset = CalculateOffSet( w, h );
ClipBlt( g_lpDDSBuffer,(w-1)*32-g_iViewPortX,
(h-1)*16-g_iViewPortY,
g_lpDDSTile,
GetPicArea( offset, &rcRect ),
TRUE );
}
}
The function CalculateOffSet( ) is just to compute the index of tile.
The function GetPicArea( ) is just to obtain the rectangle region of image of tile.
The function ClipBlt( ) is just to Display the DirectDrawSurface,supporting the cliping operation.
The code like the following.
//Function:CalculateOffSet( )
int CalculateOffSet( int iTileX, int iTileY )
{
int offset;
if(iTileX%2==0)
{
offset = (iTileY>>1)*(2*g_iMapWidth>>6+1)+(iTileX>>1);
}
else
{
offset =(iTileY>>1+1)*(g_iMapWidth>>6+1)+(iTileY-(iTileY>>1+1))*(g_iMapWidth>>6)+(iTileX>>1);
}
return offset;
}
//Function:GetPicArea( )
RECT* GetPicArea( int iIndex, RECT* prcRect )
{
prcRect->left = (m_pTileData[iIndex].type%3)*64;
prcRect->top = (m_pTileData[iIndex].type/3)*32;
prcRect->right = prcRect->left + TILEWIDTH;
prcRect->bottom = prcRect->top + TILEHEIGHT;
return prcRect;
}
//Function:ClipBlt( )
void ClipBlt( IDirectDrawSurface *pdds1, int iX, int iY,
IDirectDrawSurface *pdds2, RECT *prcArea, BOOL bTrans = TRUE )
{
POINT src;
src.x = iX; src.y = iY;
RECT rcRect;
rcRect.left = prcArea->left; rcRect.top = prcArea->top;
rcRect.right= prcArea->right; rcRect.bottom = prcArea->bottom;
if(iX<0)
{
rcRect.left = prcArea->left - iX;
src.x = 0;
}
if(iY<0)
{
rcRect.top = prcArea->top - iY;
src.y = 0;
}
if(iX+prcArea->right-prcArea->left>800)
{
rcRect.right = prcArea->left + (800-iX);
}
if(iY+prcArea->bottom-prcArea->top>600)
{
rcRect.bottom = prcArea->top + (600-iY);
}
pdds1->BltFast( src.x, src.y, pdds2, &rcRect, bTrans?DDBLTFAST_SRCCOLORKEY:FALSE );
}
In my opinion you are getting low frame rates because of your computer specs. I believe Starcraft uses the dirty rectangle technique.
"- To begin with, said the Cat, a dog''s not mad. You grant that?
- I suppose so, said Alice.
- Well, then, - the Cat went on - you see, a dog growls when it''s angry, and wags its tail when it''s pleased. Now I growl when I''m pleased, and wag my tail when I''m angry. Therefore I''m mad."
"- To begin with, said the Cat, a dog''s not mad. You grant that?
- I suppose so, said Alice.
- Well, then, - the Cat went on - you see, a dog growls when it''s angry, and wags its tail when it''s pleased. Now I growl when I''m pleased, and wag my tail when I''m angry. Therefore I''m mad."
One way to speed your program, is creating a surface of the same size of your terrain area, render your tiles to this surface and then copy this to your backbuffer, in the next frame if you aren,t moving, just copy your surface again to the backbuffer, when you are moving, just redraw the tiles first to your surface, this works for me and speed up a lot in my program.
Hope this help.
If God with me, Who against me?
Hope this help.
If God with me, Who against me?
17 fps sound about right for a system like that. Even with the slow CPU you could probably gain alot from upgrading you vid card. Even a dirt cheap geforce2 or equivalant ATI card. Something that had Direct Draw down to a science wich you card surly does not. They would be doing most of the work for all of the bliting. Since its a celron I asume it was factory built and may not have an AGP slot in wich case you may be able to still find PCI slot versons. Celron systems are not generaly built for the gamer.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement