Jump from directdraw to d3d

Started by
4 comments, last by jollyjeffers 18 years ago
Hello everyone, first post. Going to attempt to learn direct3d by remaking, and adding features to, a game I made in directdraw. I’m interested in doing 2d graphics with the 3d hardware, then moving on to 3d graphics from there [using the 2d stuff to learn the 3d functionality differences]. But when I read up on direct3d, some things really worries me, like the functions involving changing textures [specifically the word ‘slow’ and it’s use with this function, I don’t want to kill my program performance over something so stupid], and the use of floats to specify texture coordinates. So here are my questions. If I am going to be making a tiled game with d3d, how should I store the tile set? A single texture for each tile [a lot of changing of the texture, and no drawing in sets, which seems to be the recommended way of doing things], or a single texture with a bunch of tiles [in which case, how do I make sure that the floating point texture coordinate doesn’t attempt to draw the edge of one tile while drawing another tile, how do I make sure there is no overlapping, since the measures are not so discrete]. How much does changing the texture actually hurt performance [I’m paranoid about this kind of thing, if it says ‘hurt performance’, I’m going to try to find a way to never do it], and how best can I minimize this sort of problem occurring. For the tiled ground, what is the best way to store the tiles. Should I draw each tile separate, or attempt to draw the entire ground as a single object, or segment it into a few objects [like 4 by 4 tile chunks]. Concerning animated sprites, how is best to break these up into textures [or draw them as one big texture] and how is best to handle the need to constantly change the texture coordinates? Or should I just use a vertex buffer defining each animation frame separately, and treat it sort of like how I treated animation in direct draw [call each frame separate.] Thanks for the input.
Advertisement
i believe this question would be better answered in the DirectX forum.

edit: thanks jolly [smile]

Beginner in Game Development?  Read here. And read here.

 

Quote:Original post by Peachy keen
Hello everyone, first post.
Welcome [smile]

Quote:Original post by Peachy keen
I’m interested in doing 2d graphics with the 3d hardware, then moving on to 3d graphics from there [using the 2d stuff to learn the 3d functionality differences].
Sounds like a good plan to me.

Quote:Original post by Peachy keen
But when I read up on direct3d, some things really worries me, like the functions involving changing textures [specifically the word ‘slow’ and it’s use with this function, I don’t want to kill my program performance over something so stupid]
SetTexture() isn't a general sort of slow - calling it won't just automagically knock your applications performance. A better way of thinking about it might be "excessive use of SetTexture() can become a performance problem".

Quote:Original post by Peachy keen
the use of floats to specify texture coordinates.
Get familiar with the "Directly Mapping Texels To Pixels" article in the SDK [wink]

Quote:Original post by Peachy keen
If I am going to be making a tiled game with d3d, how should I store the tile set? A single texture for each tile [a lot of changing of the texture, and no drawing in sets, which seems to be the recommended way of doing things]
I wouldn't advise this. You'll also start hitting the overhead of Draw**() calls as well if you split things up like this [oh]

Quote:Original post by Peachy keen
a single texture with a bunch of tiles [in which case, how do I make sure that the floating point texture coordinate doesn’t attempt to draw the edge of one tile while drawing another tile, how do I make sure there is no overlapping, since the measures are not so discrete].
You need to be very careful with the texture coordinates and the filtering options. The aforementioned article should clear a few things up.

A tricky situation is where incorrect coordinates cause the linear filtering to fetch texels from the neighbouring tile. If you've got your texture coordinates aligned properly then it shouldn't be a problem (add/subtract a 0.5px offset to target the center of the texel). Sometimes a simple "gutter" between tiles sorts some of these problems out.

In my experience the best way of getting good performance from a tile renderer in Direct3D is to:

1. Store all tiles on a "texture palette". If your tiles are 30x30 then store a 16x16 grid of tiles inside a 512x512 texture. This way you need only change the texture *once* for the whole tile rendering

2. Store all geometry in a vertex buffer, probably as a triangle-list. With correct texture coordinates you can render all the tiles in a single DrawPrimitive() call.

3. If you want animated tiles, then just still keep them on the larger "texture palette" - just make it 1024x1024 (etc..) until it stores enough tiles. Make sure that the vertex buffer is set with appropriate flags (D3DUSAGE_DYNAMIC), and don't update the animations on every frame. Running a simple timer so you only update at 15hz/20hz/30hz should mean you can avoid an expensive Lock() call on a large percentage of the frames.

In my personal experience as well as what I've seen on these forums, people trying to use Direct3D the same way they did DirectDraw get performance problems. Yes, they're both graphics API's - but they do require different mentalities and usage [smile]

hth
Jack

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

Quote:Original post by Alpha_ProgDes
i believe this question would be better in the DirectX forum.
I thought it was when I clicked on it [lol]. I'll move it over now for you...

Cheers,
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

1. Store all tiles on a "texture palette". If your tiles are 30x30 then store a 16x16 grid of tiles inside a 512x512 texture. This way you need only change the texture *once* for the whole tile rendering

2. Store all geometry in a vertex buffer, probably as a triangle-list. With correct texture coordinates you can render all the tiles in a single DrawPrimitive() call.
This is what I was thinking, but the thought of my tiles pulling any sort of residual color over from neighboring tiles made the hair on the back of my neck stand up, and looked to just be a huge mess. I'm reading that bit in the sdk now though, looks like it'll help. This also means that it would be impossible to have the verteces representing the corners of my tiles be shared by neighboring tiles [since the texture coordinates would be different] right?

Quote:Original post by jollyjeffers
3. If you want animated tiles, then just still keep them on the larger "texture palette" - just make it 1024x1024 (etc..) until it stores enough tiles. Make sure that the vertex buffer is set with appropriate flags (D3DUSAGE_DYNAMIC)...
Wasn't really thinking about animated tiles, but animated characters, but suppose that would work similarly, but instead of using dynamic vertexs, can I store them as individual frames in the vertex buffer? [perhaps a better question is, would this be better]. And as far as drawing the entire tile set in one draw call, is it actually efficient to let the graphics hardware do the culling on that sort of thing? or should I take the time to throw out as much as I can first, then let it pick up the scraps [seems like for a large tile map, I'd have to at least throw some out with space partitioning, so the graphics hardware doesn't end up drawing 100 tiles on a 100K tile chunk of data, not that my levels are that big, but for future reference]. Seems like it would make sense to not even have the whole level in geometric form at a given time [leave some tiles as just single byte representation on a sort of old style 2d grid when they are far enough out of sight]

Oh, and sorry about posting in the wrong section. I usually try to hold onto my 'forgive the retarded newbie' token a little longer than that. First post and I have already goofed up :P
Quote:Original post by Peachy keen
This also means that it would be impossible to have the verteces representing the corners of my tiles be shared by neighboring tiles [since the texture coordinates would be different] right?
Yes, but for a tile-based renderer I wouldn't worry about it too much. The number of triangles (especially if they're pre-transformed) used in a 2D tile game is not likely to get close to stressing out even a low-end 3D card [smile]

Quote:Original post by Peachy keen
can I store them as individual frames in the vertex buffer? [perhaps a better question is, would this be better].
That would be an interesting way of doing it, and yes, probably would be faster. One of the big things you want to avoid when using D3D is modifying resources - e.g. ::Lock() calls. If you can re-arrange your data so that you need only change the parameters to a Draw**() call then thats A Good Thing™.

Quote:Original post by Peachy keen
And as far as drawing the entire tile set in one draw call, is it actually efficient to let the graphics hardware do the culling on that sort of thing?
Yes and no... there isn't really a clear-cut answer to this. Complex algorithms to guarantee that only visible polys get rendered and absolutely nothing else are often worse for performance. Throwing a few 100 extra triangles at the screen and keeping the algorithm simple/efficient is better. However, if you throw 1000's or millions of extra triangles then you might start to get problems...

It all depends how big your whole 2D tilemap is, and what proportion of that you'll actually see on screen at any given time.

Quote:Original post by Peachy keen
or should I take the time to throw out as much as I can first, then let it pick up the scraps [seems like for a large tile map, I'd have to at least throw some out with space partitioning, so the graphics hardware doesn't end up drawing 100 tiles on a 100K tile chunk of data, not that my levels are that big, but for future reference].
I would recommend a Quad-Tree algorithm. Works amazingly well with terrain engines, and you can combine it with index buffers to make it stupidly fast when it comes to rendering [grin]

Quote:Original post by Peachy keen
Seems like it would make sense to not even have the whole level in geometric form at a given time [leave some tiles as just single byte representation on a sort of old style 2d grid when they are far enough out of sight]
Unless your level is absolutely huge (and I mean several 1000 tiles in height/width) this would be an overkill optimization. The VRAM consumption for geometry is pretty insignificant compared to both texture usage as well as the huge amount most hardware has installed these days...

Quote:Original post by Peachy keen
Oh, and sorry about posting in the wrong section. I usually try to hold onto my 'forgive the retarded newbie' token a little longer than that. First post and I have already goofed up :P
[lol] You didn't "goof up" as such; just that with so many sub-forums on GDNet its not always easy to pick the best place for questions. Nothing wrong with putting it in "For Beginners", but you'd normally get a better response to this from "DirectX"...

hth
Jack

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

This topic is closed to new replies.

Advertisement