DX11三角形列表根本不呈现

问题描述

我有一个装入了vert缓冲区的4个verts列表,以及一个装入了索引缓冲区的索引。

我遇到的问题是,虽然LineList渲染模式显示四边形就很好(请参见下文),但TriangleList不显示任何内容(请参见下文)

void BLX::Model::load(std::filesystem::path path,Model* model,ID3D11Device* d3dDevice,ID3D11DeviceContext* d3dContext)
{
    // tmp: just making a quad
    float num = 0.5f;
    std::vector<BLX::Vertex> vertices = {
        BLX::Vertex { DirectX::XMFLOAT3(-num,-num,0.0f),DirectX::XMFLOAT3(0.0f,0.0f,0.5f),},// 0 = TL
        BLX::Vertex { DirectX::XMFLOAT3(num,0.5f,// 1 = TR
        BLX::Vertex { DirectX::XMFLOAT3(num,num,DirectX::XMFLOAT3(0.5f,// 2 = BR
        BLX::Vertex { DirectX::XMFLOAT3(-num,// 3 = BL
    };

    // line list
    //std::vector<unsigned int> indices = { 0,1,2,3,0 };

    // triangle list
    std::vector<unsigned int> indices = { 0,2 };

    model->vertexCount = vertices.size();
    model->indexCount = indices.size();

    // Vertex Buffer

    D3D11_BUFFER_DESC vbd = {};
    vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd.Usage = D3D11_USAGE_DEFAULT;
    vbd.CPUAccessFlags = 0u;
    vbd.MiscFlags = 0u;
    vbd.ByteWidth = sizeof(BLX::Vertex) * model->vertexCount;

    vbd.StructureByteStride = sizeof(BLX::Vertex);

    D3D11_SUBRESOURCE_DATA vsd = {};
    vsd.pSysMem = &vertices[0];
    vsd.SysMemPitch = 0;
    vsd.SysMemSlicePitch = 0;

    d3dDevice->CreateBuffer(&vbd,&vsd,&model->vertexBuffer);

    /// Index Buffer
    
    D3D11_BUFFER_DESC ibd = {};
    ibd.Usage = D3D11_USAGE_DEFAULT;
    ibd.ByteWidth = sizeof(unsigned int) * model->indexCount;
    ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    ibd.CPUAccessFlags = 0;
    ibd.MiscFlags = 0;

    D3D11_SUBRESOURCE_DATA isd = {};
    isd.pSysMem = &indices[0];
    isd.SysMemPitch = 0;
    isd.SysMemSlicePitch = 0;

    d3dDevice->CreateBuffer(&ibd,&isd,&model->indexBuffer);


    // IA = Input Assembly

    // pixel shader
    D3DReadFileToBlob(L"PixelShader2.cso",&model->pBlob);
    d3dDevice->CreatePixelShader(model->pBlob->GetBufferPointer(),model->pBlob->GetBufferSize(),nullptr,&model->pPixelShader);

    // Vertex Shader
    D3DReadFileToBlob(L"VertexShader2.cso",&model->pBlob);
    d3dDevice->CreateVertexShader(model->pBlob->GetBufferPointer(),&model->pVertexShader);

    const D3D11_INPUT_ELEMENT_DESC ied[] =
    {
        // "Position" correcponds to Vertex Shader Semantic Name
                    // semantic index
                        // data type format
                                                  // Input slot
                                                     // Aligned byte offset
                                                        // Input slot class
                                                                                     // Instance data step rate
        { "POSITION",DXGI_FORMAT_R32G32B32_FLOAT,D3D11_INPUT_PER_VERTEX_DATA,0},{ "COLOR",12,0 },};
    // needs vertex shader blob
    d3dDevice->CreateInputLayout(ied,ARRAYSIZE(ied),model->pBlob->GetBufferPointer(),&model->pInputLayout);
}

void BLX::Model::render(ID3D11Device* d3dDevice,ID3D11DeviceContext* d3dContext,D3D11_VIEWPORT * vp)
{
    const UINT stride = sizeof(Vertex);
    const UINT offset[] = { 0u,0u };

    d3dContext->IASetVertexBuffers(0u,1u,vertexBuffer.GetAddressOf(),&stride,&offset[0]);
    d3dContext->IASetIndexBuffer(*indexBuffer.GetAddressOf(),DXGI_FORMAT_R32_UINT,offset[1]);

    d3dContext->PSSetShader(pPixelShader.Get(),0u);
    d3dContext->VSSetShader(pVertexShader.Get(),0u);

    d3dContext->IASetInputLayout(pInputLayout.Get());

    d3dContext->RSSetViewports(1u,vp);

    //d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY::D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
    d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    d3dContext->DrawIndexed(indexCount,0);
}

使用LineList索引和拓扑时:

enter image description here

使用TriangleList索引和拓扑时:

enter image description here

但是当我这样做时:

    // tmp: just making a quad
    float num = 0.5f;
    std::vector<BLX::Vertex> vertices = {
        BLX::Vertex { DirectX::XMFLOAT3(0.0f,BLX::Vertex { DirectX::XMFLOAT3(num,BLX::Vertex { DirectX::XMFLOAT3(-num,};

    // triangle list
    std::vector<unsigned int> indices = { 0,2 };

(其他所有东西都一样)我得到了:

enter image description here

当我试图渲染两个三角形组成一个正方形时,我真的很好奇我没有看到或得到的东西

解决方法

您的矩形具有按顺时针方式组织的索引,这些索引由默认的光栅化器剔除(因为您未指定它会顺时针方向的图元被剔除)

您的三角形顶点顺序是逆时针方向,因此图元没有被剔除。

要解决此问题,有两种解决方法:

  • 更改索引顺序:

      std::vector<unsigned int> indices = { 0,3,1,2,1 };
    
  • 在光栅化器状态下禁用剔除:

首先创建一个Rasterizer Description

D3D11_RASTERIZER_DESC raster_desc;
raster_desc.FillMode = D3D11_FILL_SOLID;
raster_desc.CullMode= D3D11_CULL_NONE;
raster_desc.FrontCounterClockwise = false;
raster_desc.DepthBias = 0;
raster_desc.DepthBiasClamp= 0.0f;
raster_desc.SlopeScaledDepthBias= 0.0f;
raster_desc.DepthClipEnable= true;
raster_desc.ScissorEnable= false;
raster_desc.MultisampleEnable= false;
raster_desc.AntialiasedLineEnable= false;

然后使用您的设备创建光栅化器状态:

   ID3D11RasterizerState* raster_state;
   HRESULT hr =d3dDevice->CreateRasterizerState(&raster_desc,&raster_state);

在绘制之前,将光栅化器状态分配给上下文:

   d3dContext->RSSetState(raster_state);
,

您的两个网格三角形和四边形具有相反的三角形缠绕顺序。就是这样。

enter image description here

By default,D3D11使用CullMode = Back和FrontCounterClockwise = FALSE。 这意味着它仅渲染正面,并且正面被定义为“当顶点逆时针旋转时”。

从上图中可以看到,三角形确实具有逆时针顺序,但是四边形的两个三角形都是顺时针方向,GPU会将它们视为背面,并跳过两个三角形。

您有多种修复方法,以下任何一种方法都可以。

  1. 重新排列顶点缓冲区中的顶点。
  2. 将索引缓冲区中的三角形翻转到{ 0,2 }
  3. 更改光栅化器状态以禁用背面剔除CullMode=D3D11_CULL_NONE
  4. 更改光栅化器状态以切换正面缠绕方向FrontCounterClockwise=TRUE
  5. 更改传递给顶点着色器的矩阵以包含镜像组件,例如向量[ -1,1 ]的比例表示翻转X的镜像变换,这将翻转整个网格的缠绕顺序。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...