Help! Best way to draw Rectangles on the screen?

Started by
9 comments, last by SimmerD 18 years, 9 months ago
I'm developing a game which has a player's health represented as a rectangle on the screen. I'm using DirectX9 April SDK, CDXUTDialog.DrawRect(). The player's health is scaling and changing colors as it goes from Full Health to zero. The way the CDXUTDialog::DrawRect() works is that it needs to be drawn every frame in order for the user to see it. So every frame, I'm calling my DrawHealthBox function which basically: -Recomputes the RECT dimensions based on the user's health (a few floating point calculations) -Redraws the RECT by calling the DrawRect() function. I'm drawing a few different RECT's , for other players, and I'm noticing that its HEAVILY bogging down the system, causing considerable framerate loss. Is the CDXUTDialog::DrawRect function not efficient? I'm wondering if theres a more efficient way of drawing a simple rectangle on the screen, no textures or anything, just a color.
Advertisement
Quote:Original post by EEder
I'm drawing a few different RECT's , for other players, and I'm noticing that its HEAVILY bogging down the system, causing considerable framerate loss.

Have you got any figures for this? Remember that Frames Per Second is not a linear scale, so you might not have a problem [smile]

If you really want to be sure, you might want to check the "PIX for Windows" tool - it's about as good as you can get for answering any D3D performance questions...

Quote:Original post by EEder
Is the CDXUTDialog::DrawRect function not efficient?

Difficult to tell for obvious reasons, but the DX team are well aware that people use their code in performance-critical applications, so they do tend to write good , clean and efficient implementations.

Quote:Original post by EEder
I'm wondering if theres a more efficient way of drawing a simple rectangle on the screen, no textures or anything, just a color.

If you write the code yourself, then yes, it's quite possible you can take advantage of a specialised implementation that does only what you want it to do. However, for something as trivial as a coloured TLQuad I'd be surprised if you could beat the DX-SDK's implementation!

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

I'm currently using vertex buffers in Direct3D8. For all of my shape functions, I have two functions:
> bool D3DMakeVertexBuffer(D3DCUSTOMVERTEX *vPoint,ULONG points) - Creates a vertex buffer (in a global variable) where the user specifies the address of the first vertex and how many verticies are going to be used
> bool D3DDrawVertexPrimitive(D3DDVP_TYPE type,ULONG points) - Draws a primitive shape in Direct3D by using the current vertex buffer (global), and calculates the number of primitives using the specified points and D3DDVP_TYPE (this is my enum, you won't find it on MSDN). "type" also specifies the type of primitive to be drawn.
NOTE: "D3DCUSTOMVERTEX" is a user-defined vertex struct.
If you're considering to use vertex buffers, then I would suggest researching them on MSDN.
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
As Jack said, a frame rate difference of 2 fps to 1 fps is huge but a frame rate difference of 1024 to 1023 fps is nothing.

I don't know how the DrawRect function was written, but if it's specifically using line lists, it may be a burdon on the system because line lists are meant for engineering applications with high precision and are much slower than triangle lists.

You can emulate the rectangle without a border if you create an untextured quad and supply a DIFFUSE color for the vertices. There may be a way to use ID3DXSprite to do that, I don't know.
Chris ByersMicrosoft DirectX MVP - 2005
Quote:Original post by Supernat02
I don't know how the DrawRect function was written, but if it's specifically using line lists, it may be a burdon on the system because line lists are meant for engineering applications with high precision and are much slower than triangle lists.

Interesting, I was under the impression that D3DPT_LINELIST (and/or D3DPT_LINESTRIP) was implemented as a form of degenerate triangle rendering...

Think I read that in one of the many Nvidia/ATI developer presentations/documents. Although, it is quite possible it's the opposite that we programmers should use degenerate triangles to draw lines..

Any ideas on that one Supernat02?
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Quote:Original post by jollyjeffers
Quote:Original post by Supernat02
I don't know how the DrawRect function was written, but if it's specifically using line lists, it may be a burdon on the system because line lists are meant for engineering applications with high precision and are much slower than triangle lists.

[snip]
Although, it is quite possible it's the opposite that we programmers should use degenerate triangles to draw lines..

If you supply degenerate triangles, they're not drawn at all.

Thanks for the comments guys, I thought I'd clarify a few points.

I wanted to give a more specific description of "frame rate loss."

I'm running my game windowed, 640x480. Commenting out all calls to my functions which constantly DrawRect, I get around 40 FPS. Adding in the function calls, it draws 6 RECT's, all around 100x100 or so, and the FPS drops down to 20 FPS. We have tested the same application on multiple computers, and the relative framerate loss is about the same. The more DrawRect's that are added, a proportional loss in framerate can be observed.

I figured I'd give the implementation of CDXUTDialog::DrawRect() real quick, in the hopes that it will stir something up in someone's mind. I understand that its not particularly meaningful without the full class definition and what not, but I figured I may as well.


HRESULT CDXUTDialog::DrawRect( RECT* pRect, D3DCOLOR color ){    RECT rcScreen = *pRect;    OffsetRect( &rcScreen, m_x, m_y );    // If caption is enabled, offset the Y position by its height.    if( m_bCaption )        OffsetRect( &rcScreen, 0, m_nCaptionHeight );    DXUT_SCREEN_VERTEX vertices[4] =    {        (float) rcScreen.left -0.5f,  (float) rcScreen.top -0.5f,    0.5f, 1.0f, color, 0, 0,        (float) rcScreen.right -0.5f, (float) rcScreen.top -0.5f,    0.5f, 1.0f, color, 0, 0,         (float) rcScreen.right -0.5f, (float) rcScreen.bottom -0.5f, 0.5f, 1.0f, color, 0, 0,         (float) rcScreen.left -0.5f,  (float) rcScreen.bottom -0.5f, 0.5f, 1.0f, color, 0, 0,    };    IDirect3DDevice9* pd3dDevice = m_pManager->GetD3DDevice();    // Since we're doing our own drawing here we need to flush the sprites    m_pManager->m_pSprite->Flush();    IDirect3DVertexDeclaration9 *pDecl = NULL;    pd3dDevice->GetVertexDeclaration( &pDecl );  // Preserve the sprite's current vertex decl    pd3dDevice->SetFVF( DXUT_SCREEN_VERTEX::FVF );    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );    pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );    pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vertices, sizeof(DXUT_SCREEN_VERTEX) );    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );    pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );    // Restore the vertex decl    pd3dDevice->SetVertexDeclaration( pDecl );    pDecl->Release();    return S_OK;}
Are you drawing a sprite or a shape? I don't know much about some of the functions called in there, but it seems like it's one of those functions that are heavily bogged down by "precautionary" code. There's probably a way to rewrite that so if you're going to draw multiple rectangles you would have to call some of those functions multiple times.
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
FPS does not scale linearly so it's hard to tell.

If you change the resolution to 800x600 windowed do you see the same FPS or does it change?
I'm not sure what GetD3DDevice is doing, but if you call that from some COM objects, for instance IDirect3DVertexBuffer9::GetDevice, then I've read that it will be slow. Another extremely slow call is DrawPrimitiveUP. I believe you're streaming from system memory to the video card...but I can't recall. I know I've read that it's extremely slow. As DirectX progresses, they may be optimized, so I may be out of date, but I'd suggest creating a real vertex buffer instead.
Chris ByersMicrosoft DirectX MVP - 2005

This topic is closed to new replies.

Advertisement