Rendering Vertex Buffers Made Up Of Lots Different Meshes

Started by
5 comments, last by ankhd 12 years, 8 months ago
Hello All.

How would I go about rendering this buffer at the monent Im rendering it like so.


DX10Device->DrawIndexedInstanced( pMesh->GetFaceCount() *3, NumberUnitsToDraw, 0, 0, 0);


this renders the object at there world location but they all look the same like its only using the first objects vertices.

Im only passing in one Index buffer(they all use the same index buffer but they are pre skinned)


(DX10)
Ok I have this large vertex buffer(ID3D10Buffer * VB) , I pack this VB with the same mesh pre skinned, up to 30 at a time .
this is so I can do shadow and colour passes with only doing the skinning once, this all works fine I think.
I stream the buffer out with the offset passed to Device->SOSetTargets( 1, pBuffers, offset ); set ot -1
An offset of -1 will cause the stream output buffer to be appended, continuing after the last location written to the buffer in a previous stream output pass.
this is how I fill my large VB.


I'm thinking I may need to set the index buffer up to match each new objects vertices that have been placed.
How would I calculate the index buffer for the second an later meshes when there added to the large vertex buffer.

I hope this makes sence.

Advertisement
What I understood about your problem is that you have a vertex buffer and a index buffer, and every object has uses the same index buffer but since all objects are in the same vertex buffer only the first object is drawn. So you have to create a larger index buffer and put add an offset to each index so it matches the correct vertex. See this example (the offset is meshStartIndex):

int nextVertex = 0;
int nextIndex = 0;
int meshStartIndex = 0;

for(int i = 0; i < numMeshes; i++)
{
meshStartIndex = nextVertex;

for(int x = 0; x < meshes->numVertices; x++)
{
vertexBuffer[nextVertex++] = meshes.vertices[x];
}
for(int x = 0; x < meshes->numIndices; x++)
{
indexBuffer[nextIndex++] = meshes.indices[x] + meshStartIndex;
}
}


The meshStartIndex variable keeps track of how many vertices are in the vertex buffer but you must only update it on the beginning of each mes.

However it appears you want to use instancing, if so all objects you want to instance should use the same vertices/indices and you should have two vertex buffers one containing the vertices and another containing instance data.

What I understood about your problem is that you have a vertex buffer and a index buffer, and every object has uses the same index buffer but since all objects are in the same vertex buffer only the first object is drawn. So you have to create a larger index buffer and put add an offset to each index so it matches the correct vertex. See this example (the offset is meshStartIndex):

int nextVertex = 0;
int nextIndex = 0;
int meshStartIndex = 0;

for(int i = 0; i < numMeshes; i++)
{
meshStartIndex = nextVertex;

for(int x = 0; x < meshes->numVertices; x++)
{
vertexBuffer[nextVertex++] = meshes.vertices[x];
}
for(int x = 0; x < meshes->numIndices; x++)
{
indexBuffer[nextIndex++] = meshes.indices[x] + meshStartIndex;
}
}


The meshStartIndex variable keeps track of how many vertices are in the vertex buffer but you must only update it on the beginning of each mesh


However it appears you want to use instancing, if so the vertex buffer should only contain the vertices of one object and you should create a vertex buffer containing instance data like an ID to choose the correct world matrix in the vertex shader...
Im useing a large vertex buffer and instancing for the world positions



here is the creation of the index buffer.
It has over 900,000 indices this really slow it down, in fact rendering 30 single buffers looks faster.
[source]
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//we need to create our index buffer once
//IndexBuffer_Body

MAX_UNIT_BATCH_SIZE = 30;

// Create the index buffer

D3D10_BUFFER_DESC bufferDesc;
ZeroMemory( &bufferDesc, sizeof( D3D10_BUFFER_DESC ) );

//set how many indeices we have for one object
DefaultIndexCountBody = (pMesh->GetFaceCount() *3);

//we want to create a off set for each lot of indexes until the buffer to be full
DWORD IndexCountBodyBatch = DefaultIndexCountBody * MAX_UNIT_BATCH_SIZE;
DWORD *wIndices = new DWORD[IndexCountBodyBatch];
if(wIndices == NULL)
{
OutPutDebugText("No Memory for Index buffer ",//the message to display
"cUnitRenderBatch::CreateUnitTypeBatch()",//the location the message was called Eg. what function
true);//bool cUnitRenderBatch = false);//true if you also want to display it in a messagebox

return false;
}



//get the index buffer of the defualt object

//===============================================================
// Get Index Buffer
IndexBuffer<DWORD> IB(pMesh);// = new cIndexBuffer<DWORD>(mesh);
if(IB.Error)
{
OutPutDebugText("Failed To Get Index buffer frome defualt UnitInstance Body",//the message to display
"cUnitRenderBatch::CreateUnitTypeBatch()",//the location the message was called Eg. what function
true);//bool Usewindowmsgbox = false);//true if you also want to display it in a messagebox

//free our temp index buffer
SAFE_DELETE_ARRAY(wIndices);


return false;
}





DWORD IndexObjOffSet = 0;//we in creas this for each object that gets added to the index buffer


//we now need to copy the index buffer of max uint instancing using the size of the defualt index as the off set
for(DWORD ctr = 0; ctr < IndexCountBodyBatch; ctr++)
{
//for all current objects index buffer add the offset
for(DWORD cnt = 0; cnt < DefaultIndexCountBody; cnt++)
{
//add the offset to each inxed
wIndices[ctr] = IB.pSourceindices[cnt] + IndexObjOffSet;


}//end all index defualts

//increase the index offset
IndexObjOffSet += DefaultIndexCountBody;

}//end for whole large index buffer


//release index buffer
IB.UnLock();


bufferDesc.ByteWidth = IndexCountBodyBatch * sizeof( DWORD );
bufferDesc.Usage = D3D10_USAGE_DEFAULT;
bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;

D3D10_SUBRESOURCE_DATA ibInitData;
ZeroMemory( &ibInitData, sizeof( D3D10_SUBRESOURCE_DATA ) );
ibInitData.pSysMem = wIndices;

HRESULT hr = Device->CreateBuffer( &bufferDesc, &ibInitData, &IndexBuffer_Body );
if(FAILED(hr))
{
OutPutDebugText("Failed To create buffer Index",//the message to display
"cUnitRenderBatch::CreateUnitTypeBatch()",//the location the message was called Eg. what function
true);//bool cUnitRenderBatch = false);//true if you also want to display it in a messagebox

return false;
}


//free our temp index buffer
SAFE_DELETE_ARRAY(wIndices);


[/source]
You should only use instancing if you want to render multiple instances of the same geometry...

Can explain what are you trying to do?


It has over 900,000 indices this really slow it down, in fact rendering 30 single buffers looks faster.[/quote]
Do you really need that much indices? You should really tell what you are trying to render...
well What Im tring to to do is render a lot of meshes(my units) in batches of 30 at a time. But my mesh for the unit has the folloing data

vertex count = 8736
Indices = 30612(faces * 3)
faces = 10204

thirty of these units = 918360 indices I only create them once at start up but it takes 3 minutes to load and 80 milliseconds to render(and thats 30).



what i'm doing with this big vertext buffer is using the stream out in shader 4 model HLSL to streamout the skinned meshes to this buffer and I dont need to do skinning anymore

I then pass this buffer to a new shader that does shadow and colour rendering and thats pretty much it. But its so slow may be I should skin them with there worlds position and just render with no index buffer
or is it the meshes are far to big to render(in vertex size)

well What Im tring to to do is render a lot of meshes(my units) in batches of 30 at a time. But my mesh for the unit has the folloiwng data


But do all of your units use the same mesh? Are they all the same? If so you "have" to use instancing...


thirty of these units = 918360 indices.

Have you ran your program on nVidia PerfHUD or AMD PerfStudio to see in which part of the pipeline is your bottleneck? Uploading that many indices to the GPU probably takes lots of time...


80 milliseconds to render(and thats 30)

WOW, you should at least keep it at 30ms..

Take a look at the Skinning10 example of the DirectX SDK.
Can you post an screenshot of your scene?

Also, post some code (maybe the shaders)...
Im trying to skin them once only im using the sdks skinning10 to stream the buffers.

I can render 30 using the sdks skinning but any thing after say about 80 uints it slows down not as much as the above way.

Im woundering if I transform the verts to there world post in the stream out stage I could then just render the vertex buffer with draw auto or draw.

This topic is closed to new replies.

Advertisement