Direct3D 11 — Рисование треугольника

Я инициализировал весь 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< /а>

Вызовы выполняются правильно при выполнении программы, но не отображаются. На всякий случай, если мой вопрос забыт сверху, почему не отображается треугольник?

Я надеюсь, что кто-то может помочь.. :)


person Abby Turner    schedule 19.10.2014    source источник
comment
Обратите внимание, что все версии D3DX устарели. Я бы посоветовал вам избегать использования устаревшей библиотеки D3DXMath и использовать DirectXMath вместо этого. Вам не нужно использовать D3DX11 для компиляции шейдера, так как вы можете использовать D3DCompile напрямую. Вы также можете ознакомиться с этим руководством по Direct3D 11.   -  person Chuck Walbourn    schedule 23.10.2014


Ответы (3)


Я не гуру в DirectX11 (на самом деле я только начал), но кажется, что даже если вашему вершинному шейдеру будет присвоено D3DXVECTOR3 для позиции вершины, вы говорите ему, что POSITION

Четырехкомпонентный формат 32-битного нормализованного целого числа без знака, который поддерживает 8 бит на канал, включая альфа-канал.

в вашем макете ввода. Теперь это сбивает с толку!

Вы должны использовать DXGI_FORMAT_R32G32B32_FLOAT.

Спасибо за чтение.

person Nard    schedule 19.10.2014
comment
Спасибо за повтор, я изменил формат на DXGI_FORMAT_R32G32B32_FLOAT. Но все равно ничего, однако спасибо, и я буду продолжать в том же духе, пока не добьюсь успеха. - person Abby Turner; 19.10.2014
comment
Без проблем. Когда вы программируете графику, отлаживать сложно, потому что все, что вы знаете, это то, что она выглядит неправильно, поэтому вы должны быть очень уверены в том, что делаете (например, в типах данных и конвейере рендеринга). - person Nard; 19.10.2014
comment
Я признаю, что не совсем следовал учебнику, который читал, и делал все по-своему. Я полагаю, что наилучшей практикой будет придерживаться книги до буквы. И да, программирование gfx сложно, я до сих пор не могу получить список режимов отображения, связанных с устройствами вывода. Я доберусь туда. :) - person Abby Turner; 19.10.2014
comment
Не беспокойтесь об этом. У каждого свой предпочтительный способ обучения. Я тоже люблю возиться с вещами. :D - person Nard; 19.10.2014

Возможно, это не совсем ответ, но, надеюсь, он будет полезен. Иногда трудно сказать, почему что-то не отрисовывается, просто взглянув на код. Причин может быть несколько, и иногда они могут быть скрытыми.

Как правило, когда я сталкиваюсь с этой проблемой, я загружаю графический отладчик, подобный включенному в Visual Studio, и просматриваю каждую часть состояния, отправленную на графический процессор, чтобы выяснить, что пошло не так. Однако поначалу это может быть сложно, когда вы точно не знаете, что делает каждый элемент состояния и каким он должен быть. Но, в конце концов, вы учитесь, и вам приходится гадать, чтобы понять, что пошло не так.

Другая вещь, которая обычно бывает полезна, — это включить режим отладки на вашем ID3D11Device. Для этого установите параметр Flags для D3D11CreateDevice или D3D11CreateDeviceAndSwapChain (в зависимости от того, что вы используете) на D3D11_CREATE_DEVICE_DEBUG. Это выведет предупреждения, если что-то пойдет не так.

В конце концов вы захотите научиться пользоваться графическим отладчиком, но прежде чем вы дойдете до этого момента, я бы порекомендовал сначала попробовать точно следовать руководству, а затем вернуться и изменить его по своему вкусу. После каждого существенного изменения запускайте программу, чтобы убедиться, что она все еще работает. Когда это не так, вы знаете, что пошло не так.

К вашей проблеме. Одна проблема, которую я вижу, заключается в том, что вы не объявили свой цветной элемент в макете ввода. Вам нужно будет добавить это после вашего элемента position:

{ "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 }

В противном случае ваш шейдер не знает, где найти цвет в вашем потоке вершин. Обратите внимание, что позиция также должна быть DXGI_FORMAT_R32G32B32_FLOAT, как указано в ответе Нард. Без этих двух вещей CreateInputLayout вернет нулевой входной макет, потому что он не соответствует входной сигнатуре вершинного шейдера.

Также убедитесь, что вы настраиваете окно просмотра.

Могут быть и другие проблемы, но трудно сказать, не видя каждый выполненный вызов API.

person megadan    schedule 23.10.2014
comment
Спасибо, я использовал макрос отладки, но я не вижу достаточно в окне вывода .. отладчик графики, вы имеете в виду dxdiag? или есть что-то еще, что я могу использовать, поскольку я сбит с толку, лол - person Abby Turner; 26.10.2014
comment
Вы пытались добавить элемент цвета в макет ввода, как я уже упоминал, и настроить область просмотра? Отладчик графики — это функция Visual Studio, которая находится в разделе Отладка->Графика->Начать диагностику. Он позволяет вам захватить кадр, а затем проанализировать состояние D3D. Это в версии Pro, но я не уверен, что это в бесплатной версии Express. - person megadan; 27.10.2014
comment
Да, я добавил это, я также следовал учебнику до точной буквы. Это загадка .. Я установил D3D11_APPEND_ALIGNED_ELEMENT, он уже был установлен для отладки, и я скачал бесплатную пробную версию графического отладчика, но мне все равно не повезло ни с одним из них. Завтра я вытащу все геометрические данные и перезапущу конвейер и буду надеяться на лучшее, так как я действительно много вложил в этот маленький проект. - person Abby Turner; 28.10.2014
comment
Извините, я понял, что допустил опечатку в своем фрагменте кода. Формат записи COLOR должен быть DXGI_FORMAT_R32G32B32A32_FLOAT, потому что у вас есть 4 записи с плавающей запятой для цвета. Я обновил свой ответ. Также убедитесь, что для POSITION установлено значение DXGI_FORMAT_R32G32B32_FLOAT, как указано в ответе Нард. Если это не решит вашу проблему, какие значения вы использовали при создании области просмотра? - person megadan; 28.10.2014

Обратите внимание, что на самом деле вы не выполняли никаких преобразований в вершинном шейдере, согласно моему опыту, добавление трех матриц преобразования в вершинный шейдер должно выполнить эту работу.

 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> для управления матрицей, например, используйте XMMatrixTranslation и XMMatrixRotation для изменения mWorld, используйте XMMatrixLookAtLH для изменения mView, используйте XMMatrixPerspective для изменения mProjection.

после того, как вы получите матрицу в памяти процессора, вам нужно использовать ID3D11DeviceContext::UpdateSubresource для обновления данных в памяти GPU (постоянные буферы, которые вы создали выше). не забудьте сделать XMMatrixTranspose перед передачей матрицы.

person Clones1201    schedule 26.11.2014