سؤال

I've been following a book about basics for game programming with D3D11. I now understand the absolute basics of Direct3D :)

but... I have a question. In the book, I always had to make one demo at a time. Now, I'm trying to make a 2D game with it. Since I don't want to get used to bad habits so I need your advice.

In the book, I always had to define a (struct VertexPos with texcoord and position members) OR (struct VertexPos with only a XMFLOAT3 position member). In the game I'm making, I want to be able to draw both solid surfaces without textures and surfaces with textures. I'm not sure how to do this, let alone do this efficiently.

Here is my rendering function:

void GameSpriteDemo::Render()
{
    if (m_pD3DContext == 0)
    {return;}

    float ClearColor[4] = {0.0f, 0.0f, 0.25f, 1.0f};
    m_pD3DContext->ClearRenderTargetView(m_pBackBufferTarget,ClearColor);

    UINT stride = sizeof(VertexPos);
    UINT offset = 0;

    m_pD3DContext->IASetInputLayout(m_pInputLayout);
    m_pD3DContext->IASetVertexBuffers(0,1,&m_pVertexBuffer, &stride, &offset);
    m_pD3DContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    m_pD3DContext->VSSetShader(m_pSolidColorVS,0,0);
    m_pD3DContext->PSSetShader(m_pSolidColorPS,0,0);
    m_pD3DContext->PSSetShaderResources(0,1,&m_pColorMap);
    m_pD3DContext->PSSetSamplers(0,1,&m_pColorMapSampler);

    for(int i=0; i < 2; ++i)
    {
        XMMATRIX world = m_Sprites[i].GetWorldMatrix();
        XMMATRIX mvp = XMMatrixMultiply( world, m_VpMatrix );
        mvp = XMMatrixTranspose(mvp);

        m_pD3DContext->UpdateSubresource(m_pMvpCB,0,0,&mvp,0,0);
        m_pD3DContext->VSSetConstantBuffers(0,1,&m_pMvpCB);

        m_pD3DContext->Draw(6,0);
    }

    m_pSwapChain->Present(0,0);
}

So, how should I handle this efficiently with multiple vertex buffers, input layouts, Shaders, Blenders, etc?

Should I just create multiple versions of those, and then set reset the input assembly, shaders and such after the Draw call? Or does this not work/ is this not efficient?

Thanks :)

هل كانت مفيدة؟

المحلول

The simple answer is yes, you should create multiple vertex buffers, input layouts, shaders, etc. and set the appropriate ones before each corresponding draw call. This will work and is reasonably efficient (should be efficient enough for a 2D game on modern hardware).

Things tend to get a bit more complicated in a full 3D game engine. Typically the rendering engine will have some additional internal levels of abstraction layered on top of primitive objects like vertex and index buffers, input layouts, shaders etc.

A reasonably common simple way of structuring things is to have a Mesh class which knows about all of the vertex buffers, index buffers, input layouts, shaders, textures, etc. which make up a bit of a 3D model that can be drawn in a single draw call and is responsible for setting them all (often along with other bits of render state like blend modes, culling modes, etc.) and issuing the corresponding draw call.

There is a cost associated with changing any device state and so rendering engines are often designed to try and sort all the objects that need drawing in a particular frame so as to minimize the number of state changes required. In the Dawn of War 2 renderer for example we sorted all of the mesh geometry so that we could draw e.g. all of the space marine helmets with minimal state changes required before drawing all of the space marine bodies with different vertex and index buffers, textures, etc.

Modern 3D hardware and APIs have somewhat less overhead for changing state than in the past so sorting to minimize state changes is a bit less important than it once was but it is still common practice for games that need to get maximum performance on the PC.

In a data driven rendering engine that supports a flexible lighting and material model along with skinned animation, terrain, particle systems, full screen effects, 2D UI, etc. a suitable design for managing all of the state required to draw the game objects and for sorting it so it can be drawn with maximum efficiency can get quite complex and there are many different approaches to structuring things. The code for everything that could be classed as 'renderer state management' often makes up a significant portion of the code in a typical rendering engine.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top