如何在DirectX 11中绘制/渲染不同的形状

时间:2017-07-22 15:14:12

标签: c++ directx-11

我一直在尝试使用MSDN tutorial05示例代码学习DirectX 11编程的基础知识,我遇到了一个问题,我无法在互联网上找到解决方案(我无论如何都能看到)。基本上我试图绘制和渲染一个玩家立方体对象,完成用户输入,以及玩家必须收集的金字塔状对象。

我的问题是,当我渲染场景时,只读取立方体顶点(和索引)数据,因此所有对象都是不应该的立方体。

这是制作顶点数据的函数:

PyramidVertex Pyramid[] =
{
    // Square base of the pyramid
    { XMFLOAT3( -0.5f, -0.5f, 0.5f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
    { XMFLOAT3( 0.5f, -0.5f, 0.5f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
    { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
    { XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f) },

    // The tip of the pyramid
    { XMFLOAT3(0.0f, 0.5f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
};
D3D11_BUFFER_DESC bdP;
ZeroMemory(&bdP, sizeof(bdP));
bdP.Usage = D3D11_USAGE_DEFAULT;
bdP.ByteWidth = sizeof(PyramidVertex) * 5;
bdP.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bdP.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA InitPData;
ZeroMemory(&InitPData, sizeof(InitPData));
InitPData.pSysMem = Pyramid;
hr = g_pd3dDevice->CreateBuffer(&bdP, &InitPData, &g_pVertexBufferP);
if (FAILED(hr))
    return hr;  

// Set vertex buffer
UINT pStride = sizeof(PyramidVertex);
UINT pOffset = 1;
g_pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBufferP, &pStride, &pOffset);

// create the index buffer 
DWORD pIndex[] =
{
    0, 2, 1,    
    1, 2, 3,
    0, 1, 4,    
    1, 3, 4,
    3, 2, 4,
    2, 0, 4,
};

// create the index buffer
bdP.Usage = D3D11_USAGE_DYNAMIC;
bdP.ByteWidth = sizeof(DWORD) * 18;
bdP.BindFlags = D3D11_BIND_INDEX_BUFFER;
bdP.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bdP.MiscFlags = 0;
InitPData.pSysMem = pIndex;
hr = g_pd3dDevice->CreateBuffer(&bdP, &InitPData, &g_pIndexBufferP);
if (FAILED(hr))
    return hr;

// Set index buffer
g_pImmediateContext->IASetIndexBuffer(g_pIndexBufferP, DXGI_FORMAT_R16_UINT, 0);

// Set primitive topology
g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);


// Create vertex buffer
SimpleVertex vertices[] =
{
    { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT4( 1.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT4(  1.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT4( 0.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT4(  .0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT4 (1.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT4( 1.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT4(  0.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT4( .0f, 1.0f, 1.0f, 1.0f ) },
};
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof( SimpleVertex ) * 8;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory( &InitData, sizeof(InitData) );
InitData.pSysMem = vertices;
hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
if( FAILED( hr ) )
    return hr;

// Set vertex buffer
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );

// Create index buffer
WORD indices[] =
{
    3,1,0,
    2,1,3,

    0,5,4,
    1,5,0,

    3,4,7,
    0,4,3,

    1,6,5,
    2,6,1,

    2,7,6,
    3,7,2,

    6,4,5,
    7,4,6,
};
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof( WORD ) * 36;        // 36 vertices needed for 12 triangles in a triangle list
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
InitData.pSysMem = indices;
hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer );
if( FAILED( hr ) )
    return hr;

// Set index buffer
g_pImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 );

// Set primitive topology
g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);


// Create the constant buffer
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(ConstantBuffer);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = 0;
hr = g_pd3dDevice->CreateBuffer( &bd, nullptr, &g_pConstantBuffer );
if( FAILED( hr ) )
    return hr;

// Create the constant buffer
bdP.Usage = D3D11_USAGE_DEFAULT;
bdP.ByteWidth = sizeof(ConstantBuffer);
bdP.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bdP.CPUAccessFlags = 0;
hr = g_pd3dDevice->CreateBuffer(&bdP, nullptr, &g_pConstantBufferP);
if (FAILED(hr))
    return hr;

// Initialize the world matrix
g_Player = XMMatrixIdentity();

for (int i = 0; i < 10; ++i)
{
    g_Shapes[i] = XMMatrixIdentity();
}

// Initialize the view matrix
XMVECTOR Eye = XMVectorSet( 0.0f, 1.0f, -5.0f, 0.0f );
XMVECTOR At = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
XMVECTOR Up = XMVectorSet( 0.0f, 4.0f, 0.0f, 0.0f );
g_View = XMMatrixLookAtLH( Eye, At, Up );

// Initialize the projection matrix
g_Projection = XMMatrixPerspectiveFovLH( XM_PIDIV2, width / (FLOAT)height, 0.01f, 100.0f );

我认为问题出在这里,我的理论是金字塔g_pImmediateContext在绘制立方体时会被覆盖。如果是这种情况,那么我不知道如何解决或研究这个问题。我花了一个小时的时间才弄清楚我的代码是否正确放在这个页面上却得到了奇怪的结果所以如果有人想深入了解一下,我会留下一个包含此代码的Google Drive链接原因)在代码。

这是渲染功能:

//
// Clear the back buffer
//
g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, Colors::Black);

//
// Clear the depth buffer to 1.0 (max depth)
//
g_pImmediateContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

XMMATRIX mRotate = XMMatrixRotationZ(DXGame->playerUser->getRotation());
XMMATRIX mTranslate = XMMatrixTranslation(DXGame->playerUser->getXpos(), DXGame->playerUser->getYpos(), DXGame->playerUser->getZpos());
XMMATRIX mScale = XMMatrixScaling(0.7f, 0.7f, 0.7f);
g_Player = mScale * mRotate * mTranslate;

ConstantBuffer cb1;
cb1.mWorld = XMMatrixTranspose(g_Player);
cb1.mView = XMMatrixTranspose(g_View);
cb1.mProjection = XMMatrixTranspose(g_Projection);
g_pImmediateContext->UpdateSubresource(g_pConstantBuffer, 0, nullptr, &cb1, 0, 0);

g_pImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);
g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pConstantBuffer);
g_pImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);
g_pImmediateContext->DrawIndexed(36, 0, 0);


for (int i = 0; i < 10; i++)
{   
    XMMATRIX sRotate = XMMatrixRotationY((DXGame->pickUps[i].rotation += 0.001f));
    XMMATRIX sTranslate = XMMatrixTranslation(DXGame->pickUps[i].xPos, DXGame->pickUps[i].yPos, DXGame->pickUps[i].zPos);
    XMMATRIX sScale = XMMatrixScaling(0.2f, 0.2f, 0.2f);

    g_Shapes[i] = sScale * sRotate * sTranslate;        

    ConstantBuffer constB;
    constB.mWorld = XMMatrixTranspose(g_Shapes[i]);
    constB.mView = XMMatrixTranspose(g_View);
    constB.mProjection = XMMatrixTranspose(g_Projection);
    g_pImmediateContext->UpdateSubresource(g_pConstantBufferP, 0, nullptr, &constB, 0, 0);

    g_pImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);
    g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pConstantBufferP);
    g_pImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);
    g_pImmediateContext->DrawIndexed(18, 0, 0);
}

g_pSwapChain->Present(0, 0);

我正在看的东西是常量缓冲区和HLSL,看看是否也是一个问题。

请有人至少指出我正确的方向,因为这个问题已经困扰了我差不多2个月了(我离开了这么久,因为我想为自己解决这个问题,但现在我急需一个解决方案)。

感谢您抽出宝贵的时间阅读这篇文章,对不起它很长,但我需要尽可能多地获取信息,希望它更容易阅读。

1 个答案:

答案 0 :(得分:0)

您对IASetIndexBuffer和IASetVertexBuffers的调用是在您的创建例程中,它们需要在您的渲染函数中(在调用相关的Draw函数之前,因为那些在绘制之前将这些缓冲区附加到运行时)

它们根本不需要处于创建部分(例如在DirectX11上下文中,例如构建命令和设备,例如:创建资源被解耦)。

你应该在渲染循环中:

// Set vertex buffer and index buffer for your cube
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, 
 &offset );

// Set index buffer
g_pImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 
0 );

g_pImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);
g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pConstantBuffer);
g_pImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);
g_pImmediateContext->DrawIndexed(36, 0, 0);

就在绘制所有金字塔之前:

// Set vertex buffer and index buffer for pyramids as you will draw it 10 times, you can do it once just before the loop as geometry will not change
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, 
&offset );
// Set index buffer
 g_pImmediateContext->IASetIndexBuffer(g_pIndexBufferP, DXGI_FORMAT_R16_UINT, 0);


for (int i = 0; i < 10; i++)
{ 
    //Same draw code as before 
}