Rendering a subset in DX11

Started by
2 comments, last by Hawkblood 10 years ago

How do I render only a select subset of a mesh in DX11?

I'm setting up the render like this:


void EFFECTMESH::Render(void){
	unsigned int stride;
	unsigned int offset;


	// Set vertex buffer stride and offset.
	stride = sizeof(NMVertex); 
	offset = 0;
    
	// Set the vertex buffer to active in the input assembler so it can be rendered.
	GE->devcon->IASetVertexBuffers(0, 1, &VB, &stride, &offset);

	// Set the index buffer to active in the input assembler so it can be rendered.
	GE->devcon->IASetIndexBuffer(IB, DXGI_FORMAT_R32_UINT, 0);

	// Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
	GE->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}

and then I'm calling the shader. The entire mesh renders fine, but I want to render different parts with different shaders......

Advertisement

You just have to call DrawIndexed with the correct IndexCount (the numbers of indices in the index buffer of the subset you want to draw) and StartIndexLocation (the position of the first index in the index buffer of the subset you want to draw). The other draw calls have similar arguments.


struct Subset
{
    uint index_count;
    uint start_index;
    Shader* shaders;
    Texture* textures;
    CBuffer* cbuffers;
};

void EFFECTMESH::Render(uint num_subsets, Subset* subsets){
	unsigned int stride;
	unsigned int offset;


	// Set vertex buffer stride and offset.
	stride = sizeof(NMVertex); 
	offset = 0;
    
	// Set the vertex buffer to active in the input assembler so it can be rendered.
	GE->devcon->IASetVertexBuffers(0, 1, &VB, &stride, &offset);

	// Set the index buffer to active in the input assembler so it can be rendered.
	GE->devcon->IASetIndexBuffer(IB, DXGI_FORMAT_R32_UINT, 0);

	// Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
	GE->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

        for(uint i = 0; i < num_subsets; i++)
        {
            //Set correct shaders (subsets[i].shaders)
            //Bind correct textures (subsets[i].textures)
            //Bind correct cbuffers (subsets[i].cbuffers)

            //Draw current subset
            GE->devcon->DrawIndexed(subsets[i].index_count, subsets[i].start_index, 0);
        }
}

Thanks, I was thinking I might have to create a separate index and vertex buffer for each subset. It's not exactly how you showed, but I got it to work for me. I'll post my finished code when I can make it look better (right now it's a mess).

Ok. It looks a little more intelligent now:


void EFFECTMESH::PrimeRenderVB(void){
	unsigned int stride;
	unsigned int offset;
	// Set vertex buffer stride and offset.
	stride = sizeof(NMVertex); 
	offset = 0;
  	// Set the vertex buffer to active in the input assembler so it can be rendered.
	GE->devcon->IASetVertexBuffers(0, 1, &VB, &stride, &offset);
	// Set the index buffer to active in the input assembler so it can be rendered.
//	GE->devcon->IASetIndexBuffer(IB, DXGI_FORMAT_R32_UINT, 0);//this will be done in PrimeRenderIB(..)
	// Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
	GE->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}
void EFFECTMESH::PrimeRenderIB(int index){
	if (index>=NumSubsets) return;
	GE->devcon->IASetIndexBuffer(IB, DXGI_FORMAT_R32_UINT, indexInfo[index].iStart*sizeof(UINT));
	GE->devcon->DrawIndexed(indexInfo[index].iCount,indexInfo[index].iStart,0);
}

and to render the two subsets:


	EffectMesh[testMesh].PrimeRenderVB();

	EffectMesh[testMesh].PrimeRenderIB(0);
	worldMatrix=EffectMesh[testMesh].indexInfo[0].KeyframeMatrix[int(float((GE->Timer.TotalTime/1000)%500)/100.0f)];
	worldMatrix(3,2)+=190-camloc.z;
	worldMatrix(3,1)+=-40-camloc.y;
	worldMatrix(3,0)+=-camloc.x;
	if (!NMShader.Render(GE->devcon,EffectMesh[testMesh].indexInfo[0].iCount, worldMatrix, m_Camera->m_viewMatrix, projectionMatrix,TA)) tp1++;

	EffectMesh[testMesh].PrimeRenderIB(1);
	worldMatrix=EffectMesh[testMesh].indexInfo[1].KeyframeMatrix[int(float((GE->Timer.TotalTime/1000)%500)/100.0f)];
	worldMatrix(3,2)+=190-camloc.z;
	worldMatrix(3,1)+=-40-camloc.y;
	worldMatrix(3,0)+=-camloc.x;
	if (!NMShader.Render(GE->devcon,EffectMesh[testMesh].indexInfo[1].iCount, worldMatrix, m_Camera->m_viewMatrix, projectionMatrix,TA)) tp1++;

This works nicely for my purposes. I only "setup" the common stuff once with PrimeRenderVB() and then I render each subset with PrimeRenderIB() and the appropriate shader.

This topic is closed to new replies.

Advertisement