Sign in to follow this  

Which is more efficient?

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

For my game I need to have large maps made up of textured tiles (or Quads). by large I mean 100*100 tile maps. Each tiles properties would be read from a map file indicating the texture to be used its position etc. I have two ways I can get the tiles onto the screen, but I'm not sure which way would be more effective. The first way which I have already implemented and got working is that I have one vertex array which holds the vertex information for creating 1 tile in model space. That is then stored in a vertex buffer. Before drawing the tile I set the "StreamSource" to that VB and then for each tile in my tile array I call the Render() function which basically sets the texture, sets the World matrix so the tile will be in the right place and finally DrawPrimitve is called which draws the tile. That is repeated for each tile being drawn every frame. The second way would be to again have the vertex array described above but this time use a Dynamic vertex Buffer. So when a new tile is needed its vertex data is appended onto the DVB. If the user calls Render or if the DVB gets full it puts all of the tiles stored in the DVB onto the screen at once using 1 call to DrawPrimitive. Obviously this technique makes texturing each tile differently harder but it's not something I can't overcome. So my question is which of the above would be more effective for what I'm trying to do? [Edited by - Dom_152 on April 5, 2006 4:16:25 AM]

Share this post


Link to post
Share on other sites
The second. Definitely. DrawPrimitive() is SLOW. You should never be calling it more than 500 times per frame or so. 1000 as an absolute upper limit.
The second method is how I'd implement it. Make sure you sort your tiles by texture so you can get the best performance out of it, and avoid redundant texture changes though.

Share this post


Link to post
Share on other sites
OK thanks, two questions:

How would I go about sorting the polygons depending on the texure and two as the tiles will be using one large bitmap using UV co-ordinates to get the right texture how would I acheive animated tiles? Tiles with 1 or more frames of animation?

Share this post


Link to post
Share on other sites
Quote:
Original post by Dom_152
How would I go about sorting the polygons depending on the texure


One way would be something like:

int numTiles = 0;
for(each texture, tex)
{
for(each tile, t)
{
if(t's texture == tex)
{
AddToTheVertexBuffer()
numTiles++
}
}
}

RenderTilesFromTheVB(numTiles)


Something like that, anyway. You could cache the values between frames, and save doing that double loop every frame.

Quote:
Original post by Dom_152
As the tiles will be using one large bitmap using UV co-ordinates to get the right texture how would I acheive animated tiles? Tiles with 1 or more frames of animation?

If you only use one IDirect3DTexture9 interface, then you don't need to sort at all. The sorting is only useful if you need to change textures between draw calls.

For an animated texture, I'd put several "frames" on one texture, and change the UV coordinates of the tile to change the frame being displayed.

Share this post


Link to post
Share on other sites
Thank you very much for clearing that up for me =D. now I'm going to go and re-write my code now. Thanks again!

Share this post


Link to post
Share on other sites
Sorry but I have another question. If I only have 1 Vertex Array containing the info on the Tiles how can I adjust the UV values for one tile without affecting the others?

Share this post


Link to post
Share on other sites
Quote:
Original post by Dom_152
Sorry but I have another question. If I only have 1 Vertex Array containing the info on the Tiles how can I adjust the UV values for one tile without affecting the others?
I don't quite follow. Each tile will probably be made up of 6 vertices (2 triangles). Each tile should have it's own copy of the vertices anyway, otherwise you won't be able to edit the UV coordinates.

Share this post


Link to post
Share on other sites
OK basically when i want to append a tile to the buffer I have to add this array of information:

VTile TilesTemp[] = { {-1.0f, -1.0f, 0.0f, 0.0f, 0.0f},
{-1.0f, 1.0f, 0.0f, 0.0f, 1.0f},
{0.0f, -1.0f, 0.0f, 0.25f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.25f, 1.0f}};


Note: The last two numbers are the UV co-ordinates. They are set to 0.25 because I was testing something.

To the buffer, does this mean I should alter the array for each tiles specification before I add it to the buffer?

Share this post


Link to post
Share on other sites
Quote:
Original post by Dom_152
To the buffer, does this mean I should alter the array for each tiles specification before I add it to the buffer?
Yes. You should be changing the UV coordinates of the tile so you can have different tiles with different textures.

You do just have one IDirect3DTexture9 interface, don't you? I wasn't entirely sure from your earlier post.

Share this post


Link to post
Share on other sites
Quote:
Original post by Dom_152So my question is which of the above would be more effective for what I'm trying to do?


I'm assuming that the map is static (i.e., its data doesn't change with time). In this case, neither of these solutions is the best. I see no reason not to put the entire map statically into a vertex buffer. 100x100 is small enough to take an insignificant chunk of video RAM (under 2MB).

You can then select what to render using a "dynamic" index buffer. That's a lot less data updated mid-level than changing the vertex buffer.

You can animate tiles by creating duplicate tiles, each with its own texture coords, but sharing the same location, and switch between them based on time.

Share this post


Link to post
Share on other sites
I would like to give some advice based on assumptions:

Assume your tiles can be computed with formula or loaded directly from some source and they are all in world space, then,

1) If you just need to use 1 large texture that contains all the art works for all the tiles you are drawing, using 1 dynamic VB and 1 static IB and 1 DrawIndexedPrimitives call is the most efficient.

2) If you need to use many different textures for different tiles or different UV for dfferent frames of animation, using 1 dynamic VB and 1 static IB and sort the tiles using the same texture map and 1 DrawIndexedPrimitives call to draw all the tiles with the same texture. Then repeat for all other sets.

Draw calls are not slow. State changes are not slow as well. The major performance hit comes from stalling the GPU. GPU works best and fastest when it repeat the same drawing with the same states again and again such that the pipelining and parallelism is fully used.

So, sorting and batching is a must with lots of polygons that need to change any rendering states.

Share this post


Link to post
Share on other sites
Quote:
Original post by pcwlai
Draw calls are not slow. State changes are not slow as well.

Not compared to a sick elderly snail, perhaps.

Share this post


Link to post
Share on other sites
Ha yes, well I'm back with yet another question. If I still want to use D3DXIntersectTri() (Which I do) to detect which tile the mouse is over how should I save each tiles vertice co-ordinates to then convert to World co-ordinates which I can then pass to D3DXIntersectTri() to detect if the mosue is over it?

Share this post


Link to post
Share on other sites

This topic is 4304 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this