Rendering 2 objects - questions

Started by
3 comments, last by Namethatnobodyelsetook 19 years, 8 months ago
Okay, I have a question about rendering multiple objects from a single vertex buffer. This is my situation: I have a cube mesh, and I have two instances of it. So my two instances (One and Two) have the same x, y, and z values. I know that I'm supposed to keep track of the x and y in a vector (Pos), and then use D3DXMatrixTranslation() to move each object before rendering. Pseudo-code:

Mesh CMesh;
Cube/*(x, y, size, mesh)*/ One(0, 0, 1, &CMesh), Two(3, 0, 1, &CMesh);

//...
g_pEngine.Begin();
g_pEngine.ApplyMatrix(MAT_WORLD, One.GetMatrix());
g_pScene.DrawCube(One);
g_pEngine.ApplyMatrix(MAT_WORLD, Two.GetMatrix());
g_pScene.DrawCube(Two);
g_pEngine.End();

But this requires multiple calls to DrawPrimitive() (I know, I can't draw them all with one call), and since no 2 objects are ever in the same position, there has to be a different way. So, how do I render the same mesh at two positions/orientation with 1 call to DrawPrimitive()? Thanks! (DirectX9 and C++)
Advertisement
There is no way to render with only one DrawPrimitive. The card must have all geometric information to the scene.
Prior to DirectX 9c there is no way to draw multiple meshes in different locations with one DrawPrimitive() call while still taking advantage of the hardware - i.e. you could do all your transformation on the CPU then submit the transformed vertices all at once, but that's the only way I would figure it.

However, with DX9c there is a little feature called 'geometry instancing' which uses the stream frequency capability on very new hardware. Basically, in addition to your geometry streams, you have an instance stream that holds per-instance data such as a world transform, or maybe a specific colour.

I can't explain it very well so I'll just point you to the DX documentation (which has a good explanation and example) it's under
DirectX Graphics -> Programming Guide -> Advanced Topics -> Efficiently Drawing Multiple Instances of Geometry

Enjoy.

-Mezz
Okay, thanks guys. I've had a good night sleep and realized that my question was dumb. So, I think I'll answer my own question (correct me if I'm wrong):

I've totally misunderstood the point of combining vertices. The point is, if you have a mesh that is 500 vertices, you can render it with one call, instead of rendering each triangle with a call to DrawPrimitive().

Thanks again!
Another good reason to put multiple meshes into one buffer is that changing buffers takes time. If you put 5 types of meshes in one buffer, and do 5 draws, it's still faster than 5 meshes in 5 different buffers, and 5 draws.

As mentioned, with dx9.0c and a GeForce6 card you can do instancing with their fancy new API. However, any card that supports vertex shaders will let you do your own instancing.

Doing your own instancing is fairly easy if you're comfy with shaders. In your vertex format, add an entry for "instance number". This will let you choose your matrix. Then in your vertex buffer, put n copies of your mesh, and fill in instance numbers for each copy. In you index buffer, place n copies of the data, each set of indices offset to point to the next set of vertices. When you render, program as many world matrices as you need, and update your primitive count and vertexcount in your drawindexedprimitive call. In your shader, read the instance number, scale it if necessary, put it into a0.x, and transform your vertices using the addressing (a0.x) register.

for example:

mov r0,v2 // fetch instance number
mov a0.x, r0.x // I think a0.x likes to come from r regs only.
// transform world
dp4 r1.x, v0, [a0.x + 10]
dp4 r1.y, v0, [a0.x + 11]
dp4 r1.z, v0, [a0.x + 12]
dp4 r1.w, v0, [a0.x + 13]
// transform normal
dp3 r2.x, v1, [a0.x + 10]
dp3 r2.y, v1, [a0.x + 11]
dp3 r2.z, v1, [a0.x + 12]
...

This topic is closed to new replies.

Advertisement