Direct3D 11 - 绘制三角形

3
我已经初始化了所有Direct3D 11,但是当我尝试绘制一些几何图形时,它们没有显示出来。
我已经创建了管线、几何和一个绘制函数来绘制几何体。我的主要问题是,有谁能帮我理解为什么三角形没有在窗口中绘制出来?
void cSystem::Draw(UINT count)
{
    // draw stuff...    
    UINT stride = sizeof(Vertex);
    UINT offset = 0;
    p_D3D11DeviceContext->IASetVertexBuffers(0, 1, &p_VertextBuffer, &stride, &offset);

    p_D3D11DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    p_D3D11DeviceContext->Draw(3, 0);

    if (count == 0)
    {
        INFO(L"Draw() Complete");
    }   
}

void cSystem::InitGeometry() // initialise the geometry for the scene
{   
    Vertex vertices[] =
    {
        { D3DXVECTOR3(0.0f, 0.5f, 0.5f), D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f) },
        { D3DXVECTOR3(0.5f, -0.5f, 0.5f), D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f) },
        { D3DXVECTOR3(-0.5f, -0.5f, 0.5f), D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f) }
    };

    D3D11_BUFFER_DESC bdsc;
    ZeroMemory(&bdsc, sizeof(D3D11_BUFFER_DESC));
    bdsc.Usage = D3D11_USAGE_IMMUTABLE;
    bdsc.ByteWidth = sizeof(Vertex) * 3;
    bdsc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bdsc.CPUAccessFlags = 0;
    bdsc.MiscFlags = 0;
    D3D11_SUBRESOURCE_DATA vinitdata;
    ZeroMemory(&vinitdata, sizeof(D3D11_SUBRESOURCE_DATA));
    vinitdata.pSysMem = vertices;

    p_D3D11Device->CreateBuffer(&bdsc, &vinitdata, &p_VertextBuffer);   

    /*D3D11_MAPPED_SUBRESOURCE ms;
    p_D3D11DeviceContext->Map(p_VertextBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
    memcpy(ms.pData, vertices, sizeof(Vertex));
    p_D3D11DeviceContext->Unmap(p_VertextBuffer, NULL);*/

    INFO(L"InitGeometry() Complete");
}

void cSystem::InitPipeline(void)
{   
#if defined(DEBUG) || (_DEBUG)
    DWORD shaderflags = 0;
#endif
    //p_D3D11Device->GetFeatureLevel() == D3D_FEATURE_LEVEL_11_0;
    ID3D10Blob *VS_, *PS_ = NULL;
    D3DX11CompileFromFile(L"Shader.shader", 0, 0, "VS", "vs_5_0", 0, 0, 0, &VS_, 0, 0);
    D3DX11CompileFromFile(L"Shader.shader", 0, 0, "PS", "ps_5_0", 0, 0, 0, &PS_, 0, 0);

    p_D3D11Device->CreateVertexShader(VS_->GetBufferPointer(), VS_->GetBufferSize(), NULL, &p_VS);
    p_D3D11Device->CreatePixelShader(PS_->GetBufferPointer(), PS_->GetBufferSize(), NULL, &p_PS);

    p_D3D11DeviceContext->VSSetShader(p_VS, 0, 0);
    p_D3D11DeviceContext->PSSetShader(p_PS, 0, 0);

    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT NumElements = ARRAYSIZE(layout);

    p_D3D11Device->CreateInputLayout(layout, NumElements, VS_->GetBufferPointer(),
    VS_->GetBufferSize(), &p_InputLayout);

    p_D3D11DeviceContext->IASetInputLayout(p_InputLayout);

    VS_->Release();
    PS_->Release();

    INFO(L"InitPipeline() Complete");
}

void cSystem::D3D11RenderFrame_(void)
{
    // clear the back buffer
    p_D3D11DeviceContext->ClearRenderTargetView(p_D3D11RenderTargetView, m_BackBufferColour[0]);
    // clear the depth buffer
    p_D3D11DeviceContext->ClearDepthStencilView(p_D3D11DepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0.0f);  

    // draw 
    Draw(count++);

    // switch the back buffer and the front buffer
    p_D3D11SwapChain->Present(0, 0);
}

着色器(或.fx文件)是一个用于渲染图形的程序。
struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

VOut VS(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = position;
    output.color = color;

    return output;
}


float4 PS(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

这里有程序截图的链接:http://i.imgur.com/JyNkPqQ.png 程序执行时调用了正确的函数,但没有显示出三角形。 如果我的问题被遗忘了,请问为什么三角形没有显示出来? 希望有人能够帮忙解决 :)

请注意,所有版本的D3DX都已过时。我建议您避免使用传统的D3DXMath库,而是使用DirectXMath。您不需要使用D3DX11来编译着色器,因为您可以直接使用D3DCompile。您可能还想查看这个Direct3D 11教程 - Chuck Walbourn
3个回答

2

虽然我最近才开始接触DirectX11,但是从我的了解来看,即使你的顶点着色器会给出一个D3DXVECTOR3作为顶点位置的输入,你仍然在输入布局中将POSITION定义为

一个四分量、32位无符号整数格式,支持每个通道8位,包括Alpha。

这很令人困惑!

你应该使用DXGI_FORMAT_R32G32B32_FLOAT

感谢您的阅读。


谢谢您的回复,我已将格式更改为DXGI_FORMAT_R32G32B32_FLOAT。但仍然没有效果,不过还是感谢您,我会继续努力直到成功。 - Abby Turner
没问题。当你编写图形程序时,调试会变得困难,因为你只知道它看起来不对,所以你必须特别确定你正在做什么(例如数据类型和渲染管线)。 - Nard
我承认我没有完全按照我正在阅读的教程去做,而是用自己的方式去做了。我想最好的做法是严格按照书本上的要求去做。而且,图形编程确实很难,我仍然无法获取与输出设备相关联的显示模式列表。不过我会努力的。 :) - Abby Turner
不用担心,每个人都有自己喜欢的学习方式。我也喜欢折腾这些东西。 :D - Nard

0

注意到你的顶点着色器没有实际执行任何转换,根据我的经验,在顶点着色器中添加三个变换矩阵应该就可以完成任务。

 cbuffer Transform
 {
     matrix mWorld;
     matrix mView;
     matrix mProjection;
 }

然后在顶点着色器中,执行以下操作

output.position= mul(position, mWorld);
output.position= mul(output.position, mView);
output.position= mul(output.position, mProjection);

你需要创建一个D3D11_BIND_CONSTANT_BUFFER缓冲区,并使用ID3D11DeviceContext::VSSetConstantBuffers来绑定它。

你可以使用#include <DirectXMath.h>来控制矩阵,例如,使用XMMatrixTranslationXMMatrixRotation来改变mWorld,使用XMMatrixLookAtLH来改变mView,使用XMMatrixPerspective来改变mProjection。

在你获取cpu内存中的矩阵后,你需要使用ID3D11DeviceContext::UpdateSubresource将数据更新到gpu内存(即上面创建的常量缓冲区)。记得在传递矩阵之前进行XMMatrixTranspose


0

这可能不是答案,但希望它有所帮助。仅从代码上看,很难确定为什么某些东西没有绘制出来。可能有多个原因,有时它们可能隐藏得比较深。

通常,当我遇到这个问题时,我会加载一个图形调试器,例如 Visual Studio 中包含的那个,并查看发送到 GPU 的每个状态以找出问题所在。起初可能有些困难,因为您不知道每个状态的作用及其应该是什么。但是,最终您会学会并且可以消除猜测,找出问题所在。

另一个通常有帮助的方法是在您的 ID3D11Device 上启用调试模式。要做到这一点,请将 D3D11CreateDeviceD3D11CreateDeviceAndSwapChain(取决于您使用哪个)的 Flags 参数设置为 D3D11_CREATE_DEVICE_DEBUG。这将在出现问题时输出警告。

最终,您会想要学习如何使用图形调试器,但在达到那个点之前,我建议您首先尝试完全按照教程操作,然后再返回并根据自己的喜好进行更改。每次进行重大更改时,请运行程序以确保它仍然有效。当它无法正常工作时,您就知道出了什么问题。

针对您的问题,我看到一个问题是您没有在输入布局中声明颜色元素。您需要在位置元素之后添加此元素:

{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }

否则,您的着色器不知道在顶点流中找到颜色的位置。请注意,如Nard的答案中所述,位置也必须是DXGI_FORMAT_R32G32B32_FLOAT。如果没有这两个条件,CreateInputLayout将返回空输入布局,因为它与顶点着色器的输入签名不匹配。
此外,请确保您设置了视口。
可能还有其他问题,但是如果没有看到每个API调用,很难判断。

谢谢,我已经使用了调试宏,但是在输出窗口中看不到足够的信息。你说的图形调试器是指dxdiag吗?还是有其他工具可以使用,因为我感到困惑。 - Abby Turner
你尝试过像我提到的那样将颜色元素添加到输入布局并设置视口吗?图形调试器是Visual Studio中Debug->Graphics->Start Diagnostics下的一个功能。它允许您捕获一帧,然后分析D3D状态。它在Pro版本中,但我不确定它是否在免费的Express版本中。 - megadan
是的,我已经添加了它,我还完全按照教程去做了。这真的很神秘...我设置了D3D11_APPEND_ALIGNED_ELEMENT,它已经被设置为debug,我还下载了免费试用版的图形调试器,但所有这些都没有起作用。明天我会把所有的几何数据和管线重启全部清除,并希望能有所改善,因为我已经在这个小项目中投入了很多心血。 - Abby Turner
抱歉,我意识到我的代码片段中有一个打字错误。 "COLOR" 条目的格式应为 DXGI_FORMAT_R32G32B32A32_FLOAT,因为您有 4 个浮点条目用于颜色。 我已更新我的答案。 还请确保将 "POSITION" 设置为 DXGI_FORMAT_R32G32B32_FLOAT,如 Nard 的答案所述。 如果这些都无法解决您的问题,请问在创建视口时使用了哪些值? - megadan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接