【问题标题】:Using PrimitiveBatch::DrawIndexed with ID3D11DeviceContext::DrawIndexed?将 PrimitiveBatch::DrawIndexed 与 ID3D11DeviceContext::DrawIndexed 一起使用?
【发布时间】:2020-01-03 02:19:23
【问题描述】:

我正在创建一个游戏引擎,并且我想要绘制用于调试的线框形状(碰撞器、触发器、光线投射等)。我以前使用带有线框光栅化器状态的网格,但现在我想将系统迁移到 DirectXTK's example using their PrimitiveBatch class 以便我可以绘制光线。

但是,当我调用批处理的 DrawIndexed() 方法时,我遇到了一个问题,在该方法中,我绘制该框架的所有内容,包括来自 ID3D11DeviceContext 的 DrawIndexed() 的对象,都变成了线框。

Here's what the scene is supposed to look like.

Here's what it looks like after activating the debug drawing.

我的调试绘图方法:

void Renderer::DrawDebugShapes(ID3D11DeviceContext* context, Camera* camera, float deltaTime)
{
    if (debugObjs[0].size() < 1 && debugObjs[1].size() < 1 && debugObjs[2].size() < 1
        && debugObjs[3].size() < 1)
        return;

    db_effect->SetView(XMLoadFloat4x4(&camera->GetViewMatrix()));
    db_effect->SetProjection(XMLoadFloat4x4(&camera->GetProjectionMatrix()));

    context->OMSetBlendState(db_states->Opaque(), nullptr, 0xFFFFFFFF);
    context->OMSetDepthStencilState(db_states->DepthNone(), 0);
    context->RSSetState(db_states->CullNone());

    db_effect->Apply(context);

    context->IASetInputLayout(db_inputLayout.Get());

    db_batch->Begin();

    //Loop through all debug objs
    //0 = cubes, 1 = spheres, 2 = cylinders, 3 = rays
    for (short i = 0; i < 4; i++)
    {
        if (debugObjs[i].size() > 0)
        {
            for (auto iter = debugObjs[i].end() - 1; iter > debugObjs[i].begin(); iter--)
            {
                switch (i)
                {
                    case 0:
                        DrawShape(db_batch.get(), iter->world);
                        break;
                    case 1: 
                        //Draw sphere
                        break;
                    case 2:
                        //Draw capsule
                        break;
                    case 3:
                        //Draw rays
                        break;
                    default: break;
                }
                if (iter->type == DebugDrawType::ForDuration)
                    iter->duration -= deltaTime;

                //Erase objs that need to be
                if (iter->type == DebugDrawType::SingleFrame ||
                    (iter->type == DebugDrawType::ForDuration && iter->duration <= 0))
                    iter = debugObjs[i].erase(iter);
            }
        }
    }

    db_batch->End();
    context->RSSetState(0);
    context->OMSetDepthStencilState(0, 0);
    context->OMSetBlendState(0, 0, 0xFFFFFFFF);
    context->IASetInputLayout(0);
}

可以注释掉 case 0 中的 DrawShape() 调用以消除问题。我的正常渲染是基本的网格前向渲染,每个对象都调用 context->DrawIndexed() 并在绘制所有内容(包括调试形状)后调用 swapChain->Present(0,0)。我尝试将调试图移到交换链之后,但这并没有解决问题。

DrawShape() 只是将世界矩阵发送到使用原始批处理 (from the DirectXTK wiki) 绘制立方体的函数:

inline void XM_CALLCONV DrawCube(PrimitiveBatch<VertexPositionColor>* batch,
    CXMMATRIX matWorld,
    FXMVECTOR color)
{
    static const XMVECTORF32 s_verts[8] =
    {
        { -1.f, -1.f, -1.f, 0.f },
        {  1.f, -1.f, -1.f, 0.f },
        {  1.f, -1.f,  1.f, 0.f },
        { -1.f, -1.f,  1.f, 0.f },
        { -1.f,  1.f, -1.f, 0.f },
        {  1.f,  1.f, -1.f, 0.f },
        {  1.f,  1.f,  1.f, 0.f },
        { -1.f,  1.f,  1.f, 0.f }
    };

    static const WORD s_indices[] =
    {
        0, 1,
        1, 2,
        2, 3,
        3, 0,
        4, 5,
        5, 6,
        6, 7,
        7, 4,
        0, 4,
        1, 5,
        2, 6,
        3, 7
    };

    VertexPositionColor verts[8];
    for (size_t i = 0; i < 8; ++i)
    {
        XMVECTOR v = XMVector3Transform(s_verts[i], matWorld);
        XMStoreFloat3(&verts[i].position, v);
        XMStoreFloat4(&verts[i].color, color);
    }

    batch->DrawIndexed(D3D_PRIMITIVE_TOPOLOGY_LINELIST, s_indices, _countof(s_indices), verts, 8);
}

我也尝试在调试绘图完成后重置状态,但无济于事。有人有什么想法吗?

【问题讨论】:

  • 使用 RenderDoc 进行帧捕获并检查 GPU 状态以进行绘制调用以查看问题所在。

标签: c++ graphics game-engine directx-11 directxtk


【解决方案1】:

D3D_PRIMITIVE_TOPOLOGY_LINELIST 绘制线条,而不是三角形。如果你想要三角形,请使用D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST

【讨论】:

  • 更多信息:我必须使用context-&gt;IASetPrimitiveTopology() 将拓扑设置回D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,因为批处理会将其切换到LINELIST
  • 它设置为行列表,因为你告诉它:batch-&gt;DrawIndexed(D3D_PRIMITIVE_TOPOLOGY_LINELIST, s_indices, _countof(s_indices), verts, 8);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多