Archived

This topic is now archived and is closed to further replies.

NeoInferno

Vertex Buffer...

Recommended Posts

I read some D3D Tutorials,where a vertex buffer is used.There the vertices of one cube are stored in the vertex buffer,then the stream source is set and so on... If i render more than one cube,for example a more complex 3D Scene,have i to use more vertext buffer,or have i to store all of my vertices used in this one vertex buffer? greez,Neo (Please use simple english,i am just a silly german *g*)

Share this post


Link to post
Share on other sites
You can use several buffers as well as use one.
If your cubes are static you can put them into one buffer, set their World Matrix and then call drawprim for every cube.
You could as well have only one cube in the buffer that is transformed and rendered.

Share this post


Link to post
Share on other sites
How many vertices or cubes or whatever can i store into one vertex buffer?
I want wo make a small 3D Engine with Visual Basic...
I think i''ll make one vertex buffer for each kind of geometry (cube,sphere,...).Then I make for each of them arrays...
Would that work?

Share this post


Link to post
Share on other sites
You should try to have as few VBs as possible. You can put all your geometry into one VB if you want, and set the world matrix according to where the object should be drawn.

Steve
DirectX Programmer
Soon to be the new Bill Gates

Share this post


Link to post
Share on other sites
Does one matrix only change the position of ONE geometric figure?Need i to set each matrix new,after one thing is drawn?
...i hope i''ll learn that as soon as possible

Share this post


Link to post
Share on other sites
Yes, you set up the VB once.
A VB defines an object with its own coordinates, usually around (0,0,0) It's then transformed to world coordinates with a world matrix. You can draw the same VB many times.

Fill the VB in the initialization function.
Then when drawing you set up the projection and viewpoint matrices.
Then in a loop, you set the world matrix, draw it, set the world matrix to something else, draw again, etc.
Then you will have different cubes on the screen.




[edited by - Fidelio_ on September 1, 2002 6:24:29 AM]

Share this post


Link to post
Share on other sites
Ok thanks
But another problem:
I wanted to draw a simple plain..i used 4 vertices and triangletrip @DrawPrimitive.
But only a triangle was drawn...whats wrong there?Probably i have the wrong "Primitive Count" @DrawPrimitive.Whats this PrimitiveCount? The Number of the vertices,the triangles or what else?
Or i use wrong coordinates.How does the coordinate-system in D3D look like?

1
^
|
|
|
0---->1

Or:

0----->1
|
|
|
1

Thanks 4 answer

Share this post


Link to post
Share on other sites
A trianglestrip has the problem that the first triangle is clockwise, but the second one is counterclockwise. If you don''t specify a normal it is facing away from the camera and not drawn. And yes I think you should specify 2 as the last parameter. Try it with a triangle list and 6 points.

You can have several vertex buffers, but it''s best if there are as many as possible triangles in one buffer. But if you use an object a few times, put that in a vertex buffer.

Share this post


Link to post
Share on other sites
Yes thank u very much
And whats the coordinate system like?Is the Point (0;0) Up/Left or Down/Left...i am not sure about that.
...its a pitty that all good forums and tutorials are in english.For me as a german its often not easy to understand

Share this post


Link to post
Share on other sites
quote:
...its a pitty that all good forums and tutorials are in english.For me as a german its often not easy to understand


Ummm, I don''t remeber the site, but I know that there is a site which has dx8 tutorials in german, actually I''ve already found a few of them, although I don''t know if they are any good ...

How big can you VBuffer be? Well, that you must specify when you create your vertex buffer. So if you want you can make a big vertex buffer or a collection of vertex buffers (although I wouldn''t recommend creating too many, by too many I mean several dozen or a few hundred, as every time you switch vertex buffer there is a small overhead while the card/dx changes it''s source and that might cut a bit down on your speed if you''re changing between 50 buffers every frame). A good rule would be to make enough buffers for your different types of FVF and then for each FVF you''d distinguish between geometry that you have to load every frame and geometry you only need to load once in the game (normally most geometry is of this type, one model which is then altered with the world matrix, trees, cars, buildings, etc) and make a different buffer for both types, ofcourse if you fell like it you can make more buffers. Then you''d have all your objects defined by a struct which keeps the world transformation matrix, start index (if your also using an index buffer) or start vert and the number of tris that defines your geometry. The main reason to keep a buffer with static geometry is to avoid loading the geometry every frame, when you actually don''t need to as it doesn''t change over many frames, if it even changes.

From here on, when you start rendering, for every object, you change the world matrix and render the relevant tris.

quote:
Does one matrix only change the position of ONE geometric figure?Need i to set each matrix new,after one thing is drawn?


Umm, the matrix transformation is applied to all the verts that are called by drawprimitive, transforming all of them to a new space... basically all this tech talk just means that it''s picking up the verts which you defined on one (central) (zyz)axis and moves them to another (xyz)axis. Think of a translation, all the verts where on some axis, using a cube the coordinates will be something like (1,1,1),(1,-1,1),(-1,1,1),(-1,-1,1),(1,1,-1) and so on, when you apply the translation all the verts are moved in some direction and now their coordinates are now specified on a different axis (if we move it with this vector(1,0,0) we get these coordinates (2,1,1),(2,-1,1),(0,1,1),(0,-1,1),(2,1,-1) ) it''s exactly the same geometry just on a different axis with which it has only different coordinates (maybe the best way to think of it is to totally distinguish all axises and when you apply a transformation, all that your doing is making a copy that geometry to a certain spot on another space difined by a different axis, trust me, with an image this is self-expalanatory with words it''s a bit harder...). A rotation uses exactly the same principal, but in this case the axis vectors are being rotated, so it is harder to visualize and understand without an image.

So for sometinh like a forest, all you do is set a world matrix for one of the trees, render the tree (sending all the relevant tris to DX8 with drawprimitve), change the world matrix for another tree, , render the tree (sending all the relevant tris to DX8 with drawprimitve), change the world matrix for another tree,, render the tree (sending all the relevant tris to DX8 with drawprimitve), change the world matrix for another tree...
So it severly simplifies work, as you can reuse the same geometry over and over and all you need to do is change a matrix. Another big advantage is that you don''t need to create all the geometry for every spot in space (for a scene with 5 to 10 cubes floating around you don''t need to make each one, you just make one and render it 5 to 10 times).

As for the direction, I''m not sure, my recomendation, try it out and if it''s wrong just switch it around.
If your not seeing tris, then try switch off backface culling (it''s one of the renderstates), if all your tris are now visible now then you need to fix your vertex order to satisfy one of the winding orders.

Oh and primitive count is how many tris you want to render, don''t use the number verts you want to render (as this value should be higher then number of tris to be rendered) or you''ll get one of those interesting DX8 errors...

Share this post


Link to post
Share on other sites
Thanks 4 this detailed description
If i have some vertices which i want to render as TriangleStrip and some other vertices which i want to render as LineList,can i store this different types in one VBuffer?I think there will be problems with DrawPrimitives..
greez,Neo

Share this post


Link to post
Share on other sites
quote:
Original post by NeoInferno
Thanks 4 this detailed description
If i have some vertices which i want to render as TriangleStrip and some other vertices which i want to render as LineList,can i store this different types in one VBuffer?I think there will be problems with DrawPrimitives..



No, a vertex buffer has a type, it either stores a pointlist, linelist, trianglelist, trianglestrip or trianglefan. If you want this you''ll have to define different vertex buffers.

Share this post


Link to post
Share on other sites
quote:
Original post by Fidelio_
No, a vertex buffer has a type, it either stores a pointlist, linelist, trianglelist, trianglestrip or trianglefan. If you want this you''ll have to define different vertex buffers.


Ummmmmmm....

I don''t know if visual basic has a radically different aproach but this is not correct...

You don''t have to have a different buffer for every type, you can happily use the same vertex buffer to render a linelist and then a trilist and then a tristrip and then some indexed type. I never had any trouble doing this, just remember to keep some good structures with the type, start index, number of primitives, as if you make one mistake you''ll most likely get a case where you don''t know why DX8 is rendering wierd shapes and after hours of debugging, reading out every vertex one by one, you''ll find out that you included or left out an incorrect vertex (so it pays to stop and think out some versatile structure and function to avoid this, a day or two of paper work to avoid weeks of debugging, and the best part is that designing it out first is actually extremely easy and fast just that everybody insists they can code it down on the go without stopping to think it out...). And don''t think that by using several vertex buffers you''ll avoid these problems.

Returning to the quote... when using a vertex buffer don''t make radical assumptions like that but stop and read the DX8 documentation. When you create a Vbuffer you need the size (which depends on the vertex type yur using), a usage flag, a FVF (more in this later) and a flag specifying memory manegement (it''s all in the documentation). So just by this definition you aren''t limiting your V buffer to rendering tri strips of tri fans (although there is a usage flag for point sprites, probably for some aditional optimizations dependant on the graphic cards driver compatibility, but I wouldn''t use it...). The only place where you use the tri/line/point list tri strip or tri fan flags is in the render calls, so you can easily assume that you can use several types with one V buffer. This is great because you can make objects with an exterior wireframe on top of it (using the SAME geometry twice) like they did in Mechwarrior or in Tron... But to make this wireframes you could also use the renderstate flag and set it to wireframe, or, well, any several other ways you can think up to do this effect.

As for the FVF, when you create a V buffer, you must give it a valid FVF which you''ll be assigning as the vertexshader so DX knows what kind of operations it needs to do on what data. There is also an option to give 0 (or something like this) so that you can interleave data from several V buffers, but that is bit more advanced, and an interesting thing to play with later on...

Share this post


Link to post
Share on other sites
quote:
Original post by Fidelio_
No, a vertex buffer has a type, it either stores a pointlist, linelist, trianglelist, trianglestrip or trianglefan. If you want this you''ll have to define different vertex buffers.


Ummmmmmm....

I don''t know if visual basic has a radically different aproach but this is not correct...

You don''t have to have a different buffer for every type, you can happily use the same vertex buffer to render a linelist and then a trilist and then a tristrip and then some indexed type. I never had any trouble doing this, just remember to keep some good structures with the type, start index, number of primitives, as if you make one mistake you''ll most likely get a case where you don''t know why DX8 is rendering wierd shapes and after hours of debugging, reading out every vertex one by one, you''ll find out that you included or left out an incorrect vertex (so it pays to stop and think out some versatile structure and function to avoid this, a day or two of paper work to avoid weeks of debugging, and the best part is that designing it out first is actually extremely easy and fast just that everybody insists they can code it down on the go without stopping to think it out...). And don''t think that by using several vertex buffers you''ll avoid these problems.

Returning to the quote... when using a vertex buffer don''t make radical assumptions like that but stop and read the DX8 documentation. When you create a Vbuffer you need the size (which depends on the vertex type yur using), a usage flag, a FVF (more in this later) and a flag specifying memory manegement (it''s all in the documentation). So just by this definition you aren''t limiting your V buffer to rendering tri strips of tri fans (although there is a usage flag for point sprites, probably for some aditional optimizations dependant on the graphic cards driver compatibility, but I wouldn''t use it...). The only place where you use the tri/line/point list tri strip or tri fan flags is in the render calls, so you can easily assume that you can use several types with one V buffer. This is great because you can make objects with an exterior wireframe on top of it (using the SAME geometry twice) like they did in Mechwarrior or in Tron... But to make this wireframes you could also use the renderstate flag and set it to wireframe, or, well, any several other ways you can think up to do this effect.

As for the FVF, when you create a V buffer, you must give it a valid FVF which you''ll be assigning as the vertexshader so DX knows what kind of operations it needs to do on what data. There is also an option to give 0 (or something like this) so that you can interleave data from several V buffers, but that is bit more advanced, and an interesting thing to play with later on...

Share this post


Link to post
Share on other sites
Thx for Help...here some other questions
1.) Where can i change the colordeph (16 bit or 32 bit) ?

2.) In the function:
Set g_D3DDevice = g_D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp)
There is the Flag D3DCREATE_SOFTWARE_VERTEXPROCESSING.

Can''t i change this flag to D3DCREATE_HARDWARE_VERTEXPROCESSING?Or would there be many cards which would have problems with that setting?I think nearly all newer cards support that,don''t they?
greez,neo

Share this post


Link to post
Share on other sites
Here one more...
I wrote a function which easily creates a Plain...but only for lit FVF...have i to write for each FVF type i use another CreatePlain() function?

Share this post


Link to post
Share on other sites
Another question (i think its no. 4 *g*):
If i have more than one element (like a cube) in my vertex buffer,does the vertex buffer always draw ALL elements which are in the buffer? Or is there a possibility to draw only one element,which is in the buffer?

I would be very lucky if somebody answers my questions
greez,Neo

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
To clear things up a bit...

A vertex buffer keeps track of a group of vertices of the same kind. For example, a 3d triangle with lighting and a texture would be stored in one Vertex Buffer, then an unlit vertex type with two textures'' coordinates would require another vertex buffer.

The SetStreamSource method of the Direct3D device determines which vertex buffer to render from, and what offset in the buffer to find the vertices to render.

DrawPrimitive''s first argument determines whether to present the vertices in the buffer as a triangle list, triangle strip, triangle fan, line list, or others. The last argument of DrawPrimitive determines how many of those triangles or lines to draw...

If you keep track of each cube, tree, or whatever stored in your VB position in the buffer, and number of vertices, and keep track of how many vertices they are made of, then you may use the same vertex buffer for all of them, as long as you make it big enough when creating it with .CreateVertexBuffer''s first argument.

Finally, to determine how many primitives you are rendering (the last argument of DrawPrimitives...

If you render Triangle List:
DrawPrimitives D3DPT_TRIANGLELIST, NumberOfVertices / 3

If you render Triangle Strip or Triangle Fan:
DrawPrimitives D3DPT_TRIANGLESTRIP, NumberOfVertices - 2

If you render Line List:
DrawPrimitives D3DPT_LINELIST, NumberOfVertices / 2

I hope that helps and I did not make it too complicated.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
As the last post said... a V buffer is only a container for a FVF (it''s main "functionality" advantages comes through automatic memory manegement, which is important for hard ware rendering, which speeds up rendering many fold), so you can put all the geometry you need into one buffer (or more) and then render only the vertices that you need for that frame.

As for the primitive count... I''m a bit reluctant to recomend using his (or her) way of caculating the primitives as using the number of vertices will work, but if later on you want to change to a indexed format then it will fail miserably (and I normally tend to try and plan a bit for what I might use in the future...).

As for the function... wellll... that''s more like a programming problem. You can make a second function, or you can add to your function with if statements that take some flag through the function, or.... But I''ll suppose that you want some kind of generic "abstract" type of a solution... well you can feed in the vertexbuffer pointer and the vertex pointer can be dynamically typecasted and the start index and number of vertices doesn''t pose any problem but in a purelly general case you''ll only be able to feed in it''s position (untransformed, as it''s the most general case) as all the other stuff (colour, normal, rhw) will bite you in the butt. So I''d recommend using several functions (or adding to that function) as you are dealing with different "objects" and it''ll probably produce cleaner code to read and understand. (then again, producing some extra functions is only a case of copy-paste-make relevant changes)

You can use D3DCREATE_HARDWARE_VERTEXPROCESSING, but the problem comes when a video card doesn''t support it, most probably it won''t work, crash or go to the ramp driver support (big OUCH). Check the video cards caps, read the documentation and try studying the DX8 examples (in this case you need to see the code for the base class from which all the D3D examples are derived) as the default treatment programmed into them is to get best hardware processing whenever possible...
(if I remember correctly)

As the bit colour depth, I don''t remember this part to well, but I think it''s one of those cases where you need find a colour format which your card supports and set in the part where the render surface is created (I REALLy don''t remeber this part). But if you see the D3D examples you''ll see that they allow you to change to colour depth and the resolution, so you should once again study the base class from which the examples are derived...

Share this post


Link to post
Share on other sites
Ok so far,u helped me well
But,what does the number (in this case 3) in this code sample mean:
DrawPrimitives D3DPT_TRIANGLELIST, NumberOfVertices / 3
If i have 2 Cubes in this Buffer,how many cubes are drawn?
Where does this number depend from?
How can i calculate the No,if i want to render only objekt X from the Buffer(which probably consists of 10 of this objects...)?
Thats my main problem.If the vertex buffer consists of many cubes or plains,and i only want to render one specific of them,how can i calculate that?
thx
neo

Share this post


Link to post
Share on other sites
quote:

DrawPrimitives D3DPT_TRIANGLELIST, NumberOfVertices / 3
If i have 2 Cubes in this Buffer,how many cubes are drawn?



No, you dont. DirectX does not know cubes. YOu have NumberOfVertices vertices (coordinate points). Triangleelists are lists of 3 corrdinate points each.

You draw NumberOfVertices / 3 Triangles.

For a cube, with 6 sides of 2 triangles each, NumberOfVertices needs to be 12*3.

But thats not the problem of this code.


Regards

Thomas Tomiczek
THONA Consulting Ltd.
(Microsoft MVP C#/.NET)

Share this post


Link to post
Share on other sites
Some minutes ago i tested something...
All vertices <= NumberOfVertices are rendered.
So far so good
If i want to render for example vertex 3 without rendering vertex 1 and 2...how do i do this?
greez,Neo

Share this post


Link to post
Share on other sites
Well, use DrawIndexecPrimitives and work with indices. That also reduces the number of vertices, as vertices can be reused. THAT also pushes your performance - in case of the cube around *3 in the T&L unit.


Regards

Thomas Tomiczek
THONA Consulting Ltd.
(Microsoft MVP C#/.NET)

Share this post


Link to post
Share on other sites
Excuse me, i am a beginner in DirectX8, i also meet this kind of problems.

First,
"So for sometinh like a forest, all you do is set a world matrix for one of the trees, render the tree (sending all the relevant tris to DX8 with drawprimitve), change the world matrix for another tree, , render the tree"

What does "World Matrix" in the statement?

Second, if i create/delete objects dynamically in a game, should i resize the vertex buffer and copy all the new object''s vertex to the vertex buffer again?

Thanks a lot of! ^_^

Share this post


Link to post
Share on other sites