【问题标题】:TRIANGLESTRIP works as required with DrawIndexed why not with Draw?TRIANGLESTRIP 可以根据需要使用 DrawIndexed 为什么不使用 Draw?
【发布时间】:2016-01-30 12:50:59
【问题描述】:

我试图使用 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 个三角形,没有费心去创建单独的三角形索引缓冲区

Trianglevertexbuffer 包含数组 4 的 simplevertex:

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

我没有在上面的函数中使用 UV 数据,只是用随机数据填充它们,因为颜色数据是通过常量缓冲区传递的。如您所见,我还只将 3 个第一个数组数据 memcpy 到三角形的顶点缓冲区只需要 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);

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

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

这是绘制所有三角形的唯一组合,但老实说,我不明白它是如何发生的,据我所知,STRIP 拓扑与 context->Draw 函数一起使用,而 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 函数才能得到工作结果。我希望我提供了足够的信息,如果没有,对不起,我会按需更正。谢谢:)

【问题讨论】:

    标签: c++ directx directx-11


    【解决方案1】:

    知道了。 首先,在我的光栅化设置中,我有 rasterizerState.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 模式是否会降低性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      • 2014-10-01
      相关资源
      最近更新 更多