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
Не се тревожи за това. Всеки има свой предпочитан начин на обучение. И аз обичам да се забърквам с неща. :Д - person Nard; 19.10.2014

Това може да не е точно отговорът, но се надяваме, че е полезно. Понякога е трудно да се разбере защо нещо не се изчертава само от разглеждане на кода. Може да има много причини за това и понякога те може да са някак скрити.

Обикновено, когато се сблъскам с този проблем, зареждам графичен дебъгер като този, включен във Visual Studio, и преглеждам всяко състояние, изпратено до GPU, за да разбера какво се е объркало. Това обаче може да е трудно в началото, когато не знаете точно какво прави всяка част от състоянието и какво трябва да бъде. Но в крайна сметка се научавате и са необходими догадки, за да разберете какво се е объркало.

Друго нещо, което обикновено е полезно, е да активирате режима за отстраняване на грешки на вашия ID3D11Device. За да направите това, задайте параметъра Flags на D3D11CreateDevice или D3D11CreateDeviceAndSwapChain (което от двете използвате) на 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 }

В противен случай вашият шейдър не знае къде да намери цвета във вашия върхов поток. Имайте предвид, че позицията също трябва да бъде DXGI_FORMAT_R32G32B32_FLOAT, както е споменато в отговора на Nard. Без тези две неща, CreateInputLayout ще върне нулево входно оформление, защото не съответства на входния подпис на вертексния шейдър.

Също така се уверете, че настройвате прозорец за изглед.

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

person megadan    schedule 23.10.2014
comment
Благодаря, използвах макросите за отстраняване на грешки, но не виждам достатъчно в изходния прозорец.. графичният дебъгер, dxdiag ли имате предвид? или има нещо друго, което мога да използвам, тъй като съм объркан, хаха - person Abby Turner; 26.10.2014
comment
Опитахте ли да добавите цветния елемент към входното оформление, както споменах, и да настроите прозореца за изглед? Графичният дебъгер е функция във Visual Studio под Debug-›Graphics-›Start Diagnostics. Позволява ви да заснемете кадър и след това да анализирате 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, както е споменато в отговора на Nard. Ако те не решат проблема ви, какви стойности сте използвали, когато сте създали прозореца за изглед? - 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