TRIANGLESTRIP可以根据需要与DrawIndexed一起使用,为什么不使用Draw

TRIANGLESTRIP works as required with DrawIndexed why not with Draw?

本文关键字:一起 Draw 为什么不 DrawIndexed TRIANGLESTRIP      更新时间:2023-10-16

>我试图使用 Directx 11 使用用户定义的坐标创建三角形绘图:

void triangle(float anchorx, float anchory, float x1, float y1, float x2, float y2, XMFLOAT4 _color)
{
XMMATRIX scale;
XMMATRIX translate;
XMMATRIX world;
simplevertex framevertices[3] = { XMFLOAT3(anchorx, ui::height - anchory, 1.0f), XMFLOAT2(0.0f, 0.0f),
                                   XMFLOAT3(x1, ui::height - y1, 1.0f), XMFLOAT2(1.0f, 0.0f),
                                   XMFLOAT3(x2, ui::height - y2, 1.0f), XMFLOAT2(1.0f, 1.0f) };
world = XMMatrixIdentity();
dx11::generalcb.world = XMMatrixTranspose(world);// XMMatrixIdentity();
dx11::generalcb.fillcolor = _color;
dx11::generalcb.projection  = XMMatrixOrthographicOffCenterLH( 0.0f, ui::width, 0.0f, ui::height, 0.01f, 100.0f );
// copy the vertices into the buffer
D3D11_MAPPED_SUBRESOURCE ms;
dx11::context->Map(dx11::vertexbuffers::trianglevertexbuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
memcpy(ms.pData, framevertices, sizeof(simplevertex) * 3);                 
dx11::context->Unmap(dx11::vertexbuffers::trianglevertexbuffer, NULL);  
dx11::context->VSSetShader(dx11::shaders::simplevertexshader, NULL, 0);
dx11::context->IASetVertexBuffers(0, 1, &dx11::vertexbuffers::trianglevertexbuffer, &dx11::verticestride, &dx11::verticeoffset);
dx11::context->IASetInputLayout(dx11::shaders::simplevertexshaderlayout);
dx11::context->PSSetShader(dx11::shaders::panelpixelshader, NULL, 0);
dx11::context->UpdateSubresource(dx11::general_cb, 0, NULL, &dx11::generalcb, 0, 0);
dx11::context->IASetIndexBuffer(dx11::indexbuffers::triangleindexbuffer, DXGI_FORMAT_R16_UINT, 0);
dx11::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
dx11::context->DrawIndexed(4, 0, 0);
//dx11::context->Draw(3, 0);
};

填充 pos.y 数据时在 Y 轴上进行的解释:

XMFLOAT3(anchorx, ui::height - anchory, 1.0f)
XMFLOAT3(x1, ui::height - y1, 1.0f)
XMFLOAT3(x2, ui::height - y2, 1.0f)

我的正交投影将坐标零设置为屏幕的左下角,因此我从窗口的高度减去传递的 Y 坐标以获得 y 轴上的正确位置。不确定它会影响我的问题,因为它适用于所有其他基元(矩形、纹理、填充矩形、线条和圆形(。

索引缓冲区中定义的索引顺序:

unsigned short                  triangleindices[6] = { 0, 1, 2, 0, 2, 3 };

我实际上使用此索引缓冲区来渲染矩形,因此创建它以渲染形成四边形的 2 个三角形,没有费心创建单独的三角形索引缓冲区

三角形顶点缓冲区包含简单顶点的数组 4:

//A VERTEX STRUCT
struct simplevertex
{  
    XMFLOAT3 pos; // pixel coordintes
    XMFLOAT2 uv; // corresponding point color coordinates in texture
};

我没有在上面的函数中使用UV数据,只是用随机数据填充它们,因为颜色数据是通过常量缓冲区传递的。如您所见,我也只将 3 个第一个数组数据发送到三角形的顶点缓冲区只需要 3

顶点着色器:

    // SIMPLE VERTEX SHADER 
    cbuffer buffer : register(b0) // constant buffer, set up as 0 in set constant buffers command
    {
        matrix world; // world matrix
        matrix projection; // projection matrix, is orthographic for now 
        float4 bordercolor;
        float4 fillcolor;
        float blendindex;
    };
    // simple vertex shader
    float4 main(float4 input : POSITION) : SV_POSITION
    {
        float4 output = (float4)0; // setting variable fields to zero, may be skipped?
    output = mul(input, world); // multiplying vertex shader output by world matrix passed in the constant buffer
    output = mul(output, projection); // multiplying on by projection passed in the constant buffer (2d for now), resulting in final output data(.pos)
    return output;
}

像素着色器:

    // SIMPLE PIXEL SHADER RETURNING COLOR PASSED IN CONSTNT BUFFER
cbuffer buffer : register(b0) // constant buffer, set up as 0 in set constant buffers command
{
    matrix world; // world matrix
    matrix projection; // projection matrix, is orthographic for now
    float4 bordercolor;
    float4 fillcolor;
    float blendindex;
};
// pixel shader returning preset color in constant buffer
float4 main(float4 input : SV_POSITION) : SV_Target
{
    return fillcolor; // and we just return the color passed to constant buffer
}

函数中使用的布局:

{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 };

在那里,我在渲染周期中创建了下一行:

if (ui::keys[VK_F1]) tools::triangle(700, 100, 400, 300, 850, 700, colors::blue);
if (ui::keys[VK_F2]) tools::triangle(400, 300, 700, 100, 850, 700, colors::blue);
if (ui::keys[VK_F3]) tools::triangle(700, 100, 850, 700, 400, 300, colors::blue);
if (ui::keys[VK_F4]) tools::triangle(850, 700, 400, 300, 700, 100, colors::blue);
if (ui::keys[VK_F5]) tools::triangle(850, 700, 700, 100, 400, 300, colors::blue);
if (ui::keys[VK_F6]) tools::triangle(400, 300, 850, 700, 700, 100, colors::blue);

此设置的目的是实现形成用于渲染的三角形的任何随机坐标顺序,但这实际上是这个问题的重点 - 我没有在某些坐标变化下渲染这个三角形,所以我得出的结论是它来自拓扑,正如你所看到的我目前:

dx11::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
dx11::context->DrawIndexed(4, 0, 0); 

这是绘制所有三角形的唯一组合,但老实说,我不明白它是如何发生的,据我所知,STRIP 拓扑与上下文>绘制函数一起使用,而 LIST 与索引缓冲区设置一起使用。接下来尝试:

dx11::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
dx11::context->DrawIndexed(4, 0, 0);

三角形 F1、F5、F6 没有被绘制。哎呀,接下来:

dx11::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
//dx11::context->DrawIndexed(4, 0, 0);
dx11::context->Draw(3, 0);

同样的故事,F1、F5 和 F6 不会渲染。

无法理解正在发生的事情,您可能会发现代码有点原始,但我只想知道为什么我只通过 STRIP 拓扑和 DrawIndexed 函数的组合才能获得工作结果。我希望我提供了足够的信息,如果没有,对不起,按需不正确。谢谢:(

知道了。首先,在我的光栅器设置中,我有光栅器状态.CullMode = D3D11_CULL_FRONT,不记得为什么我只是复制粘贴了其他人的稳定代码,所以我将其更改为D3D11_CULL_NONE并且都按预期工作。

dx11::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
dx11::context->Draw(3, 0);
其次,我发现基元的朝向或不朝向取决于绘制方向,如果绘制顶点逆时针方向(顶点

2 "更右",然后起点的顶点 1(,则基元被视为面向视图,如果它顺时针 - 而不是我们看到它的"背面"。

所以我决定保留D3D11_CULL_NONE而不是添加一些数学逻辑来定义顶点的顺序,不确定D3D11_CULL_NONE模式是否会降低性能。