Index Buffering

Started by
7 comments, last by billconan 18 years, 5 months ago
I'm drawing a terrain (for now, let's say 128x128 vertices). I have a vertex buffer of the 128x128 vertices, and I'm using an index buffer to create a triangle list with each corner of each triangle indexing into the single vertex buffer (so right now I have 128*128*6 indices). This is working fine by drawing the entire terrain at once using a DrawIndexedPrimitive call. However, I am trying to optimize by having a list of 16x16 vertex patches, and drawing only the patches that are visible. I have an index buffer for each patch that contains the 16*16*6 indices into the single vertex buffer. I tested this out by drawing two patches. It works fine in that I can see the patches and they render flawlessly. However, I've found that the framerate is staggeringly higher when I render the whole terrain at once than it is when I render only these two 16x16 patches! I'm not really sure why this is, but I suspect it's because my DrawIndexedPrimitive call still passes 128*128 for numVertices. However, if I use 16*16 for numVertices, I get an error that the indices are illegal. Even setting minVertexIndex to the first vertex of the patch doesn't help alleviate this error. I suppose I could rework the code to create a vertex buffer for each patch instead of trying to index into the single master VB. But it seems like there should be a way to get it to index into the main VB without slowing down so much. In fact, I ran a test, and it is only a few FPS slower to draw the entire terrain TWICE than it is to just draw those two patches! What's a coder to do? Thanks for any tips you can give me!
Advertisement
Here is the code I am using to draw a single patch:

	//this->terrainVB is a vertex buffer of 128*128 vertices	pD3DDevice->SetStreamSource(0, this->terrainVB, 0, sizeof(D3DVERTEX));		//this->quadIB[x][y] is an index buffer of 16*16*6 indices ( 16*16*2 triangles forming 16*16 quadrilaterals)	pD3DDevice->SetIndices(this->quadIB[x][y]);	//texturing stuff snipped	//this->width and this->height are both 128	int err = pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, this->width * this->height, 0, 16 * 16 * 2);


Apparently it borks the > sign... so where it says -> what it actually means is -> (i.e. this-> == this->)
Not sure if it will help (but maybe)...
int n = 16*16;
int triangleCount = n*2;
//Draw first patch
pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0,n,0,triangleCount);
//Draw another
pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, startVertex,n,startIndex,triangleCount);

You could change the triangle list to a triangle strip to save a bit of space.
Insufficent Information: we need more infromationhttp://staff.samods.org/aiursrage2k/
Thanks for your reply. I think the reason that won't work is because the patch is in the middle of a larger array of vertices. So when the rightmost edge of the patch is reached, and you want to skip to the next row of triangles, you cannot simply ignore the vertices between the edge of the patch and the edge of the entire terrain. That is, there will be a large jump in the index whenever the end of a row of vertices in the patch is reached. If the next index is therefore larger than minIndex + numVertices, D3D will throw an error.

I guess the only thing I can do is create a vertex buffer for each patch :-/
Why not create a massive vertex buffer with all your points, and then make yourself a dynamic IB and rebuild that each frame depending on what's visible, etc.?
That's surely possible, but it involves recalculating and memcpying the index data every frame, which seems like it would be expensive.

But I'll try it and find out :-) Thanks for the suggestion.
Masterworks: I tried your suggestion, and guess what? It's WAY faster. Thanks!

In fact, I can render every single patch this way and hardly lose any framerate. Which means the overhead is much lower than I expected. You genius, you! :-)
Glad it worked out, I would figure the overhead of just uploading indices to be minimal compared to the overhead of having multiple drawprimitive calls. This is a pretty small amount of data to send to the card, and then your render call is very fast since the vertex data is ready to go (if you use static VB especially). If you are using WRITEONLY locking flag except when full (and DISCARD otherwise) with as large an index buffer as possible you will get extremely good performace.
hi there, i've heard that the performance of rendering Primitive is just the same regardless the complexity of the data, which means rendering lots of little indexbuffers may be a lag. i've a same problem, see: http://www.gamedev.net/community/forums/topic.asp?topic_id=355337

This topic is closed to new replies.

Advertisement