C++ DirectX 11 从第二个顶点缓冲区渲染问题

Posted

技术标签:

【中文标题】C++ DirectX 11 从第二个顶点缓冲区渲染问题【英文标题】:C++ DirectX 11 Trouble Rendering from a second vertex buffer 【发布时间】:2017-06-25 22:10:59 【问题描述】:

我正在开发我的第一个 3D 游戏引擎,并且刚刚完成“绘制彩虹立方体”阶段。我的下一步是能够绘制一个地面网格。我想使用多个不同的顶点缓冲区来存储位置数据。我基本上复制了用于为立方体生成顶点和索引缓冲区的代码(只是更改了缓冲区/输入数据的名称)。然后我改变了我的渲染函数来接受一个源值来告诉它要设置哪个缓冲区。当我第一次尝试它时,我的旋转立方体变成了一个巨大的可怕毁容的形状。后来做了一些小改动,现在我的立方体可以正确显示,但是看不到地面。如果有人能给我一些关于我在这个谜题中缺少什么的见解,我将不胜感激。我找不到能完全描述我的问题的任何内容。

void DXDEngine::Render(UINT numIndices, XMMATRIX VPMat, XMMATRIX worldMat,  UINT source) //source: 1 = squareVertBuffer, 2 = ground buffer

//Called each frame to present the buffer
bool validSource = false;
UINT stride = sizeof(Vertex);
UINT offset = 0;
UINT stride2 = sizeof(Vertex);
UINT offset2 = 0;

switch (source)

case(1):
    //Set the cube vertex buffer

    devcon->IASetVertexBuffers(0, 1, &squareVertBuffer, &stride, &offset);
    devcon->IASetIndexBuffer(squareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
    validSource = true;

    break;

case(2):
    //Set the vertex buffer

    devcon->IASetVertexBuffers(1, 0, &groundVertBuffer, &stride2, &offset2);
    devcon->IASetIndexBuffer(groundIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

    validSource = true;
    break;

default:
    validSource = false;
    break;


if (validSource == true)

    XMMATRIX WVPMat = worldMat * VPMat;
    //Insert the transpose of the world view projection matrix into the per object structure
    cbPerObj.WVP = XMMatrixTranspose(WVPMat);

    //pass the per object structure to the buffer
    devcon->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0);

    //Update the vertex shader to use the constant buffer
    devcon->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer);


    // do 3D rendering on the back buffer here
    devcon->DrawIndexed(numIndices, 0, 0);



方缓冲区的初始化: D3D11_BUFFER_DESC vertexBufferDesc; ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));

vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(Vertex) * vLen;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA vertexBufferData;

ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
vertexBufferData.pSysMem = v;
hr = dev->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &squareVertBuffer);

//Set the vertex buffer
UINT stride = sizeof(Vertex);
UINT offset = 0;
devcon->IASetVertexBuffers(0, 1, &squareVertBuffer, &stride, &offset);

D3D11_BUFFER_DESC indexBufferDesc;
ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));

indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(DWORD) * indicesLen;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA iinitData;

iinitData.pSysMem = indices;
dev->CreateBuffer(&indexBufferDesc, &iinitData, &squareIndexBuffer);

devcon->IASetIndexBuffer(squareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

和地面顶点缓冲区

D3D11_BUFFER_DESC gVertexBufferDesc;
ZeroMemory(&gVertexBufferDesc, sizeof(gVertexBufferDesc));

gVertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
gVertexBufferDesc.ByteWidth = sizeof(Vertex) * grndVertLen;
gVertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
gVertexBufferDesc.CPUAccessFlags = 0;
gVertexBufferDesc.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA gVertexBufferData;

ZeroMemory(&gVertexBufferData, sizeof(gVertexBufferData));
gVertexBufferData.pSysMem = grndVert;
hr = dev->CreateBuffer(&gVertexBufferDesc, &gVertexBufferData, &groundVertBuffer);

//Set the vertex buffer
UINT stride = sizeof(Vertex);
UINT offset = 0;
devcon->IASetVertexBuffers(1, 1, &groundVertBuffer, &stride, &offset);

D3D11_BUFFER_DESC gIndexBufferDesc;
ZeroMemory(&gIndexBufferDesc, sizeof(gIndexBufferDesc));

gIndexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
gIndexBufferDesc.ByteWidth = sizeof(DWORD) * indicesLen;
gIndexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
gIndexBufferDesc.CPUAccessFlags = 0;
gIndexBufferDesc.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA iinitData;

iinitData.pSysMem = grndIndex;
dev->CreateBuffer(&gIndexBufferDesc, &iinitData, &groundIndexBuffer);

devcon->IASetIndexBuffer(groundIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

【问题讨论】:

按照本网站的 DX10 或 DX11 教程,它应该可以帮助您如何渲染多个对象...rastertek.com 我看到了一个可能的错误,在案例 (2) 中,IASetVertexBuffers(1, 0, ...)。它应该是 IASetVertexBuffers(*, 1, ...)。注意:您不必在初始化时调用 IASetVertexBuffers。 Geza,你能解释一下你所说的 (*, 1,...) 是什么意思吗?单独使用星号在语法上是不正确的,并且输入另一个像 2 这样的数字也不起作用。到目前为止,还没有设置顶点缓冲区的组合对我有用,这是我缺少什么的主要问题之一。 你可能想看看DirectX Tool Kit 【参考方案1】:

在玩了一些之后,我发现了它不起作用的两个原因。原因之一是每个人最喜欢的朋友,顶点的正确逆时针索引。我最终不得不使用 IASetVertexBuffer(0,1...) 设置地面缓冲区,这与方形缓冲区完全相同。我还将地面网格大大简化为一个正方形,以便更容易看到发生了什么。

【讨论】:

以上是关于C++ DirectX 11 从第二个顶点缓冲区渲染问题的主要内容,如果未能解决你的问题,请参考以下文章

DirectX 大型模型 > 64k C++

将 FBX 顶点和索引缓冲区导入 DirectX 11

DirectX 11 中是不是可以有 SoA 顶点缓冲区?

使用 DirectX11 更新非 UI 线程中的顶点缓冲区

DirectX11--深入理解与使用缓冲区资源

(DirectX 11) 单个顶点缓冲区可以一次绑定到多个 IA 输入槽吗?