0
\$\begingroup\$

Recently I have tried adding rendering with multiple meshes in my program. This did not go too well. The attempt I currently have goes like this

    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof(VERTEX)* nVertices.at(i);
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = 0;
    bd.MiscFlags = 0;
    bd.StructureByteStride = 0;

    vertexData.pSysMem = vertices.at(i);
    vertexData.SysMemPitch = 0;
    vertexData.SysMemSlicePitch = 0;

    dev->CreateBuffer(&bd, &vertexData, &pVBuffer);

looping through the meshes and doing like wise for the index buffer. Similar to this, the render code loops through the mesh data as well:

        UINT stride = sizeof(VERTEX);
        UINT offset = 0;
        devcon->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);
        devcon->IASetIndexBuffer(pIBuffer, DXGI_FORMAT_R32_UINT, 0);

        devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

        devcon->DrawIndexed(nIndices.at(i), 0, 0);

But all of this only ends up rendering one of the meshes. Does anyone know what I need to change to fix this or whether I need to have a completely different approach? Thanks in advance!

\$\endgroup\$
9
  • \$\begingroup\$ You should be calling create once per mesh, then draw once per mesh per frame. If you're really only storing the created buffer in the single pVBuffer object, you'll only have access to one for drawing. What does the code between your two posted segments look like? \$\endgroup\$
    – MooseBoys
    Sep 6 '14 at 3:39
  • \$\begingroup\$ There's nothing in between really however I guess this might interest you: for (int i = 0; i < modelCount; i++), std::vector<VERTEX*> vertices and std::vector<DWORD*> indices. \$\endgroup\$
    – Tyson May
    Sep 6 '14 at 5:09
  • \$\begingroup\$ Should also mention that was basically saying that it loops the creation and render for each mesh data set. \$\endgroup\$
    – Tyson May
    Sep 6 '14 at 5:21
  • \$\begingroup\$ @MooseBoys w/r/t "You should be calling create once per mesh..." While I don't know much about DX, in GL best practice is to use the same buffer as many meshes as possible, as long as they have the same vertex format and usage (ie. don't put static meshes in the same buffer with dynamically updated or streamed meshes, etc.) \$\endgroup\$
    – bcrist
    Sep 6 '14 at 6:00
  • \$\begingroup\$ Thanks, the only problem now is knowing how to put them in the buffers. \$\endgroup\$
    – Tyson May
    Sep 6 '14 at 8:03
1
\$\begingroup\$

ok im not a c++ developer but i do this all the time in c#.

Essentially you need to wrap up a vbo and a ibo in to some container like this ...

class Mesh {
   public VertexBuffer Vertices;
   public IndexBuffer  Indices;
}

Then run your code generate a bunch of mesh objects ...

List<Mesh> Meshes = GetMeLotsOfMeshes();

Then you do something like ...

Apply Shader state to context foreach mesh { Set vert and index buffer call draw indexed }

My c# code for this works something like this ...

I have a material class which basically wraps up the creation and management of a shader stack in which i do something like this once before i begin dealing with any meshes ...

public void Apply(DeviceContext context, Matrix world)
{
    if (LastMaterial == null || LastMaterial != ClassName)
    {
        //apply material and buffers to device context
        context.InputAssembler.PrimitiveTopology = Topology;
        context.InputAssembler.InputLayout = layout;
        context.VertexShader.Set(vertexShader);
        context.PixelShader.Set(pixelShader);
        if (sampler != null) context.PixelShader.SetSampler(0, sampler);
        LastMaterial = ClassName;
    }
    ApplyConstants(context, world);
}

After thats been done once I begin looping through my meshes first i apply the shader constants for the buffers im about to render (world matrix for the object) then I go in to the mesh class and call draw which sets the right buffers and then calls draw on them ...

protected override void ApplyConstants(DeviceContext context, Matrix world)
{
    context.PixelShader.SetShaderResource(0, textureView);
    wvp = world * camera.ViewProjection;
    wvp.Transpose();
    context.VertexShader.SetConstantBuffer(0, constantBuffer);
    context.UpdateSubresource(ref wvp, constantBuffer);
}

public void DrawTo(DeviceContext context)
{
    context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VertexBuffer, Utilities.SizeOf<T>(), 0));
    context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
    context.DrawIndexed(Indices.Count, 0, 0);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.