Direct3D 11 - Рисование треугольника
Я инициализировал все Direct3D 11, но когда я пришел нарисовать некоторую геометрию, геометрия не показывается.
Я создал Pipeline, Geometry и создал функцию рисования для геометрии, которую нужно нарисовать. Мой главный вопрос: может ли кто-нибудь помочь мне понять, почему в окне не нарисован треугольник?
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
Вызовы выполняются правильно при выполнении программы, но не отображаются. На всякий случай, если мой вопрос забыт сверху, почему не отображается треугольник?
Я надеюсь, что кто-то может помочь..:)
3 ответа
Я не гуру в DirectX11 (на самом деле я только недавно начал), но кажется, что даже если ваш вершинный шейдер получит D3DXVECTOR3
для положения вершины, вы говорите, что POSITION
является
Четырехкомпонентный 32-битный формат unsigned-normalized-integer, поддерживающий 8 бит на канал, включая альфа-канал.
в вашей структуре ввода. Теперь это сбивает с толку!
Вы должны использовать DXGI_FORMAT_R32G32B32_FLOAT
,
Спасибо за чтение.
Это может быть не совсем ответ, но, надеюсь, это полезно. Иногда трудно понять, почему что-то не рисуется, просто глядя на код. Причин может быть несколько, а иногда они могут быть как бы скрытыми.
Обычно, когда я сталкиваюсь с этой проблемой, я загружаю графический отладчик, подобный тому, который включен в Visual Studio, и просматриваю каждый фрагмент состояния, отправляемый в графический процессор, чтобы выяснить, что пошло не так. Однако вначале это может быть сложно, если вы не знаете точно, что делает каждый кусочек государства и каким он должен быть. Но, в конце концов, вы учитесь, и вам нужно угадать догадки, выясняя, что пошло не так.
Еще одна полезная вещь - включить режим отладки на вашем компьютере. 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
как упоминалось в ответе Нарда. Без этих двух вещей, CreateInputLayout
вернет нулевой входной макет, потому что он не соответствует входной сигнатуре вершинного шейдера.
Также убедитесь, что вы настраиваете область просмотра.
Могут быть и другие проблемы, но это трудно понять, не видя каждый сделанный вызов API.
Обратите внимание, что на самом деле вы не делали никаких преобразований в вершинном шейдере, согласно моему опыту, добавьте три матрицы преобразования в вершинный шейдер, который должен выполнить эту работу.
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
прежде чем пройти матрицу.