问题描述
我有一个装入了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);
}
但是当我这样做时:
// 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 };
当我试图渲染两个三角形组成一个正方形时,我真的很好奇我没有看到或得到的东西
解决方法
您的矩形具有按顺时针方式组织的索引,这些索引由默认的光栅化器剔除(因为您未指定它会顺时针方向的图元被剔除)
您的三角形顶点顺序是逆时针方向,因此图元没有被剔除。
要解决此问题,有两种解决方法:
-
更改索引顺序:
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);
,
您的两个网格三角形和四边形具有相反的三角形缠绕顺序。就是这样。
By default,D3D11使用CullMode = Back和FrontCounterClockwise = FALSE。 这意味着它仅渲染正面,并且正面被定义为“当顶点逆时针旋转时”。
从上图中可以看到,三角形确实具有逆时针顺序,但是四边形的两个三角形都是顺时针方向,GPU会将它们视为背面,并跳过两个三角形。
您有多种修复方法,以下任何一种方法都可以。
- 重新排列顶点缓冲区中的顶点。
- 将索引缓冲区中的三角形翻转到
{ 0,2 }
- 更改光栅化器状态以禁用背面剔除
CullMode=D3D11_CULL_NONE
- 更改光栅化器状态以切换正面缠绕方向
FrontCounterClockwise=TRUE
- 更改传递给顶点着色器的矩阵以包含镜像组件,例如向量
[ -1,1 ]
的比例表示翻转X的镜像变换,这将翻转整个网格的缠绕顺序。