Index count for vertex buffers

Started by
7 comments, last by bababooey 13 years, 11 months ago
Hi, I'm using a vertex buffer to draw a curved line in my scene, and apparently don't understand how many indices are required for a vertex buffer of a given size. My code is as follows:

//defines
#define NUMVERTS 16
struct WIREVERTEX{
	D3DXVECTOR3 pos;
	D3DCOLOR color;
};
#define WIREFVF (D3DFVF_XYZ|D3DFVF_DIFFUSE)

//create the vertex/index buffers:
LPDIRECT3DVERTEXBUFFER9 wireVB;
LPDIRECT3DINDEXBUFFER9 wireIB;
device->CreateVertexBuffer(sizeof(WIREVERTEX)*NUMVERTS,0,WIREFVF,D3DPOOL_MANAGED,&wireVB,NULL);
//for line list, there should be twice as many indices as vertices, 2 for each segment, right?
device->CreateIndexBuffer(NUMVERTS*2,0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&wireIB,NULL);


//set the vertices
INT i;
FLOAT t;
WIREVERTEX *vert;
WORD *ind;
wireVB->Lock(0,0,(void**)&vert,NULL);
for(i=0;i<NUMVERTS;i++){
	//set each vertex's "pos" and "color"
}
wireVB->Unlock();
wireIB->Lock(0,0,(void**)&ind,NULL);//compute indices
for(i=0;i<NUMVERTS-1;i++){
	ind[i*2]=WORD(i);
	ind[i*2+1]=WORD(i+1);
}
wireIB->Unlock();

//here we draw, after setting up world matrices and such:
device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
device->SetVertexShader(NULL);
device->SetPixelShader(NULL);
device->SetFVF(WIREFVF);
device->SetTexture(0,NULL);
device->SetMaterial(&myMaterial);//has no effect - another problem...
device->SetStreamSource(0,wireVB,0,sizeof(WIREVERTEX));
device->SetIndices(wireIB);
device->DrawIndexedPrimitive(D3DPT_LINELIST,0,0,NUMVERTS,0,(NUMVERTS-1)*2);
device->SetVertexShader(regularVS);
device->SetPixelShader(regularPS);
device->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);


When executed, the DrawIndexedPrimitive call fails with:
Quote: Direct3D9: (ERROR) :Index stream does not have required number of indices. DrawIndexedPrimitive failed.
I can get it to draw only by increasing the "Length" parameters of both CreateVertexBuffer and CreateIndexBuffer by something absurdly large like 10*NUMVERTS, but it ignores what material I have set, leaving it only the color of the vertices, and also spews this line a few dozen times:
Quote: Direct3D9: (WARN) :Stream 0 stride and vertex size, computed from the current vertex declaration or FVF, are different, which might not work with pre-DX8 drivers
Isn't twice the number of indices as vertices correct for a D3DPT_LINELIST render? Thanks, -- Bababooey [Edited by - bababooey on April 26, 2010 7:30:38 PM]
Advertisement
I'm not quite sure why you're using DrawIndexed rather than just DrawPrimitive...

But see if this helps....

Vertex buffer:

Vertices 0, 1, 2, 3

Index buffer:

Indices 0, 1, 1, 2, 2, 3

To give lines from 0 -> 1, 1 -> 2, 2 -> 3...so 3 lines in total (or number of vertices - 1)

So 4 vertices and 6 indices to "link" them together.

I think that's right.

The size you specify when creating the index buffer is in bytes, not in indices. Since you're using 16-bit indices, each index will be 2 bytes. So you want 2 * 2 * NUMVERTS.

Your other problem seems to be that the stride computed from your FVF code doesn't match the stride you specified when setting the vertex stream (sizeof(WIREVERTEX)). I haven't used FVF codes in a very long time, so I'm not sure what your mistake is. However I can recommend that you switch to vertex declarations, since:

A. Vertex declarations are inherently more flexible
B. Vertex declarations map directly to vertex shader inputs, making them easier to work with
C. With vertex declarations you explicitly specify the entire vertex layout, which makes them less error-prone.
Greg: I was feeding (NUMVERTS-1)*2 to the "PrimCount" parameter above, and now realize it should just be the number of lines.

Quote:Original post by MJP
The size you specify when creating the index buffer is in bytes, not in indices. Since you're using 16-bit indices, each index will be 2 bytes. So you want 2 * 2 * NUMVERTS.


Combining this with the note from Greg, I pass (NUMVERTS-1)*2*2 to CreateIndexBuffer and now just (NUMVERTS-1) to DrawIndexedPrimitive, and it works. ^^

The second issue, however, still persists and this spews out like a thousand times:

Quote:
Direct3D9: (WARN) :Stream 0 stride and vertex size, computed from the current vertex declaration or FVF, are different, which might not work with pre-DX8 drivers


I'll look into this vertex declaration thing but my obsessive compulsive inclinations would have me still itching to know what's wrong with it the way it is.

On a side note, any idea why materials don't work on the line list? For example, in the code above I use "SetMaterial(&myMaterial)" before drawing, which has red and dark ambient/diffuse components, but it still just draws the line list as solid white or whatever the "color" components of its vertices are.

You're using shaders, aren't you? SetMaterial is only for fixed-function processing. For shaders, you'll have to either use your vertex data or specify additional data through shader constants.
Generally yes, but for drawing this particular line list, I specifically turn them off so as to use fixed-function effects. From my code snippet above:

device->SetVertexShader(NULL);device->SetPixelShader(NULL);device->SetFVF(WIREFVF);device->SetTexture(0,NULL);device->SetMaterial(&myMaterial);//has no effect - another problem...device->SetStreamSource(0,wireVB,0,sizeof(WIREVERTEX));device->SetIndices(wireIB);device->DrawIndexedPrimitive(D3DPT_LINELIST,0,0,NUMVERTS,0,NUMVERTS-1);//changed PrimCount here
Are you setting the D3DRS_DIFFUSEMATERIALSOURCE render state to D3DMCS_MATERIAL?
Wasn't, but now tried it with this before the DrawIndexedPrimitive call above:
device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE,D3DMCS_MATERIAL);

and now it draws them all solid white, no regard to the vertex color or material color. Tried also setting D3DRS_AMBIENTMATERIALSOURCE to D3DMCS_MATERIAL.

To give more detail, I am drawing a curving line that is colored with RGB values and decreasing alpha values from full to 0, so that it gets more transparent toward the end. I'd like to be able to color this with any material so as to draw the same vertices with different colors. What's weird is that it does the alpha of the vertices correctly (while not setting D3DRS_*MATERIALSOURCE's above), and if I leave a texture set it uses it, but it ignores the colors of the vertices and the material, drawing it white every time.

[Edited by - bababooey on April 27, 2010 1:43:43 AM]
And I can get it to heed the vertex's color by setting:
graphDevice->SetRenderState(D3DRS_LIGHTING,FALSE);

Still ignores material though.

This topic is closed to new replies.

Advertisement