Skip to main content
GameDev.net gamedev.net
🔒 Locked

2D DrawPrimitive

Started by Turtlebread Oct 11, 2001 at 7:20 PM 10 replies 1.9k views
Original Post
Turtlebread
Turtlebread
Using DX8 to do 2D, I''ve got a question with DrawPrimitive. Since I''m doing a 2D game, only the world matrix changes and each object is a quad. However, it needs to change for each object, as they need to be rendered in different locations. Anyway, I''ve heard that around 200+ triangles *should* be sent in one call. Should I worry about this? Calling the DrawPrimitive for each quad seems fairly wasteful. Let me know what you think. -Chris
WarMachine
WarMachine
I don''t think I understand what your problem is but let me try.

Only update the world matrix when your main character(or whatever) moves, requiring the entire screen to scroll.

Any enemies that move forward, or whatever it is you have in your game that all the individual quads represent, should be moved individually, not using the world matrix, but using your own translation and/or rotation matrices that need to be applied to them.

The world matrix is called that because it handles the movement of the entire world, it is not designed to be used to move each individual object.

Remember, DirectX doesn''t provide everything for you, there are times when you actually need to get your hands dirty.


"You can get out of prison, but not out of the cemetery"
"You can get out of prison, but not out of the cemetery"
CrazedGenius
CrazedGenius
optimally, you want to batch as much as possible and send as many things (within reason) in one call as possible. But sometimes it''s just not possible to send alot through and that''s ok.

Some people might say that you should use pretransformed vertices. Process them in bulk and them send them en masse to the GPU. In my experience, it''s been better to reset the matrix each time than to lock and manipulate vertices on the CPU.
Turtlebread
Turtlebread
Thanks for the response.

My whole problem was that I thought the world matrix was the main transformer, ie, you changed it for each moving object and set that one object through it. I guess it would make more sense to create individual transformation matrices, rather than resetting the world matrix each time.

Thank you,
-Chris

[EDIT]Hmm..I've been doing some reading, and I don't understand it as much as I thought. A fair number of people suggest using the world mat to transform individual objects, rather than just the main view. Can anyone clarify this matter?


Edited by - Turtlebread on October 13, 2001 2:15:42 PM
DrunkenHyena
DrunkenHyena
G''day!

The world matrix is used to transform an object from Model Space to World Space. It is typically used to move individual objects. However in most 3D programs your individual objects are fairly complex, so you do end up batching a lot of triangles with this method. In your case you''re only drawing a quad for each object, so this is a special case.

The easiest way is to do what you''re doing and rebuild the World matrix for each object and do a separate DrawPrim call for each. Though incredibly simple, it''s very inefficient. Depending on how much you''re drawing it may be good enough, and if it is, then don''t worry about it.

The next simplest is to have a vertex buffer quad and before each object is drawn, you lock the buffer, manually set the coordinates, unlock and then draw. This is also pretty inefficient.

A much better way is to have a vertex buffer that is large enough to hold a bunch of your quads. When drawing your enemies (for example) you lock your vertex buffer and then loop through your enemy list building them into your buffer with their appropriate coordinates. Then you unlock your buffer and draw all your enemies in one go. You can do a lot to optimize this technique. You''ll likely want to do this in layers.

Say you''re doing a 2D tile-based game. All your terrain squares are put into a single texture, then you set texture once and use the texture coordinate offsets to choose which tile is drawn. Then with a single call you draw all the terrain. Then you process your next ''layer'', maybe it''s your enemies layer.

There is another technique involving Vertex Shaders to utilize multiple world matrices in a single call, but that''s pretty advanced stuff.


Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena</FON
RomanR
RomanR
OK a question on the topic...
Being an ultimate newbie in game dev. I followed the advice of the wiser ones and started building a Tetris game to play around with different things. I decided to start with DX8 in VB since I know VB much better than C/C++ although I will be learning it later because obviously VB is not synonymous with the word "performance". But for a Tetris game I think it''s more then enough. Ok on to my question ...

I have the whole thing working already with blocks falling, lines dropping, piece rotation and stuff...even scores This game being more of a DX8 learning experience I am planning to add some nifty things to it. Such as 3D pieces later, cool particle system effects using DX8 point sprites for blowing up complete lines and field rotation. The field is now in 2D and I want to start playing around with the rotation allowing the 2d game "field" to be rotated by say 45deg left and right (round the Y axis I s''pose that is). the FVF is defined as D3DFVF_XYZRHW Or D3DFVF_DIFFUSE. so with x,y,z and rhw which is always 1.
When I try to call
D3DXMatrixRotationY matWorld, angle
device.SetTransform D3DTS_WORLD, matWorld
before I draw the board and the current piece and then
device.SetTransform D3DTS_WORLD, matId << identity matrix
to draw the rest of the screen normally I dont get any rotation.
Some help with this would be greatly appreciated.

Cheers

Roman
roman_rodov@hotmail.com
Romanroman_rodov@hotmail.com
Turtlebread
Turtlebread
DrukenHyena: I was shooting for the large VB plan. I think I understand what you''re saying: I should create a large VB, transform each of my individual enemy vertices and store them in the buffer, and then draw the buffer.

However, won''t locking the VB each frame really slow everything down? It would only be one call, but I''ve heard that locking the VB once a frame should be avoided at all costs. Also, what did you mean when you said you''ll want to do them in "layers"?

-Chris
DrunkenHyena
DrunkenHyena
G''day!

Yup, that''s the Big VB idea. Generally works quite well.

Locking your VB once per frame is not a big deal if you do it right. Create the VB as write only and dynamic (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) and when you lock the VB pass the D3DLOCK_DISCARD flag. I wrote a quick class to do fast Text output (it''s not pretty, but it''s FAST, for those times when you need to display stuff and don''t care if it''s pretty) and I lock and re-write the buffer 5 or 6 times per frame and I''m getting almost 500 FPS on a fairly average computer. So I don''t think locking your VB once per frame will matter. Locking it once for each object might be an issue, but you''re using th Big VB method, so you''ll have minimal locking.

The layers idea doesn''t seem to fit what you''re doing. I was thinking of a game like Zelda, or the early Ultimas, where you have a map made up of tiles and guys running around on top. You''d have a texture with all the terrain tiles, set it then Lock/Fill/Draw your terrain, then set your BadGuys texture and Lock/Fill/Draw that ''layer''. Don''t think that''d work for you in a Tetris game (unless you do some weird stuff).

As for why you can''t rotate, it''s your D3DFVF_XYZRHW. That states that your vertices are already transformed (already in screen coordinates). These vertices ignore the World matrix. You have 3 options, the first being don''t bother with the rotation, but that''s not a fun one so ignore it.

2) Othographic projection. You can set things up so you''re dealing with ''real'' 3D coordinate but the coordinate system is shifted so they appear to be in screen coordinates. I''ve never actually done this, but I think there are some helper functions in D3DX to set this up. Since I haven''t done it, I won''t comment more.

3)Take the leap into ''proper'' 3D coordinates. Set your camera back a ways on the Z axis (say 0,0,-10) aim it at 0,0,0 (which is where you center your play area), and go crazy. This is the hardest method, but I think it''s also the most flexible. You can arbitrarily transform ANYTHING without (more) hassle. If you want the game ''board'' to turn upside down every few minutes, it''s trivial, either rotate stuff around, or just turn the camera up side down (set Up vector to 0,-1,0).

The BIG VB works with your current way of doing things, but when you have to transform each object arbitrarily I kinda falls down. Though with #2 or #3, you can still do the translation (movement along the axis) yourself, and transform the camera position to get special effects, that might be your best bet.

Disclaimer:I may not know what I''m talking about, so take it with a small truck-load of salt.


Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena</FON
Turtlebread
Turtlebread
Thanks for the response. I think you got me and RomanR mixed up, but its fine. I got what I needed.

Thanks,
-Chris
DrunkenHyena
DrunkenHyena
quote:
Original post by Turtlebread
Thanks for the response. I think you got me and RomanR mixed up, but its fine. I got what I needed.

Thanks,
-Chris


Oops, sorry about that.



Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena</FON

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.