DirectX 11 Sprite 2D камера

Долгое время читатель. Первый раз постер. У меня есть проблема, которая уже несколько часов разрушает клетки головного мозга, и я не получаю быстро. Так что я подумал, что я должен засунуть это сюда, чтобы взглянуть на это свежо …

По сути, я пытаюсь создать 2D-игру, используя C ++ и DirectX 11. Я раньше использовал C # и XNA и сделал несколько 3D-вещей в DirectX, но ничего такого большого.

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

Здесь я устанавливаю все свои матрицы в классе камеры, и они остаются такими (пока изменится, чтобы переместиться и т. Д.):

XMStoreFloat4x4(&m_world, XMMatrixIdentity());
XMStoreFloat4x4(&m_proj, XMMatrixOrthographicOffCenterLH(0.0f, width, height, 0.0f, 0.0f, 1.0f));

m_position = XMFLOAT3(width / 2, height / 2, 0);
m_look = XMFLOAT3(0, 0, 1);
m_up = XMFLOAT3(0, 1, 0);

XMVECTOR p = XMLoadFloat3(&m_position);
XMVECTOR l = XMLoadFloat3(&m_look);
XMVECTOR u = XMLoadFloat3(&m_up);

XMStoreFloat4x4(&m_view, XMMatrixLookToLH(p, l, u));

Затем он передается в метод начала спрайта, который передает информацию в шейдер:

D3D11_MAPPED_SUBRESOURCE data;
ZeroMemory(&data, sizeof(data));
m_deviceContext->Map(m_cBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &data);
ConstantBuffer* cb = (ConstantBuffer*)data.pData;

XMMATRIX w = XMLoadFloat4x4(&world);
XMMATRIX v = XMLoadFloat4x4(&view);
XMMATRIX p = XMLoadFloat4x4(&proj);

w = XMMatrixTranspose(w);
v = XMMatrixTranspose(v);
p = XMMatrixTranspose(p);

XMStoreFloat4x4(&world, w);
XMStoreFloat4x4(&view, v);
XMStoreFloat4x4(&proj, p);

cb->World = world;
cb->View = view;
cb->Proj = proj;

m_deviceContext->Unmap(m_cBuffer, 0);

И, наконец, сам шейдер:

cbuffer ConstantBuffer : register(b0)
{
float4x4 World;
float4x4 View;
float4x4 Proj;
};

SamplerState sam : register(s0);
Texture2D tex : register(t0);

struct VertexIn
{
float3 Position : POSITION;
float2 Texture : TEXCOORD;
float4 Color : COLOR;
};

struct PixelIn
{
float4 Position : SV_POSITION;
float2 Texture : TEXCOORD;
float4 Color : COLOR;
};

PixelIn VS(VertexIn vin)
{
float4 position = float4(vin.Position, 1.0f);
position = mul(position, World);
position = mul(position, View);
position = mul(position, Proj);

PixelIn vout;
vout.Position = position;
vout.Texture = vin.Texture;
vout.Color = vin.Color;

return vout;
}

float4 PS(PixelIn pin) : SV_Target
{
float4 textureColor = tex.Sample(sam, pin.Texture);

return pin.Color * textureColor;
}

Как видите, довольно простые вещи. Но ничто не обращается к экрану вообще. Я пытался вообще не беспокоиться о матрицах, оставляя мировую матрицу, используя матрицу перспективной проекции, используя взгляд, а не взгляд на матрицу, используя (0, 0, 0) в качестве центра через XMMatrixOrthographicLH и преобразовывая позиции спрайтов в пространство экрана.

Я даже значительно упростил пакет спрайтов, ограничив его рисованием только одного спрайта за раз!

Я использую неизменный индексный буфер (0, 1, 2, 0, 2, 3) и динамический буфер вершин, который обновляется следующим образом:

D3D11_MAPPED_SUBRESOURCE data;
ZeroMemory(&data, sizeof(data));
m_deviceContext->Map(m_vBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &data);
Vertex* vertex = (Vertex*)data.pData;

for(UINT i = 0; i < sprite->Vertices.size(); ++i)
{
vertex[i] = sprite->Vertices[i];
}

m_deviceContext->Unmap(m_vBuffer, 0);

m_deviceContext->DrawIndexed(6, 0, 0);

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

Я думал, что это может быть проблемой с потерей данных где-то, но все это, кажется, проходит через все правильно вплоть до вызова метода DrawIndexed. Я дважды проверил создание и состояние буфера и в настоящее время имею его на CULL_NONE, просто чтобы убедиться, что он просто не отбракован.

Я опубликую создание буфера и создание спрайта для ясности:

HRESULT result = S_OK;

device->GetImmediateContext(&m_deviceContext);

D3D11_BUFFER_DESC cbd;
ZeroMemory(&cbd, sizeof(cbd));
cbd.ByteWidth = sizeof(ConstantBuffer);
cbd.Usage = D3D11_USAGE_DYNAMIC;
cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbd.MiscFlags = 0;
cbd.StructureByteStride = 0;

result = device->CreateBuffer(&cbd, 0, &m_cBuffer);

if (FAILED(result))
{
return 0;
}

vector<short> indices;
indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
indices.push_back(0);
indices.push_back(2);
indices.push_back(3);

D3D11_SUBRESOURCE_DATA indexData;
ZeroMemory(&indexData, sizeof(indexData));
indexData.pSysMem = &indices;

D3D11_BUFFER_DESC ibd;
ZeroMemory(&ibd, sizeof(ibd));
ibd.ByteWidth = 6 * sizeof(short);
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
ibd.StructureByteStride = 0;

result = device->CreateBuffer(&ibd, &indexData, &m_iBuffer);

if (FAILED(result))
{
return 0;
}

D3D11_BUFFER_DESC vbd;
ZeroMemory(&vbd, sizeof(vbd));
vbd.ByteWidth = 4 * sizeof(Vertex);
vbd.Usage = D3D11_USAGE_DYNAMIC;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;

result = device->CreateBuffer(&vbd, 0, &m_vBuffer);

if (FAILED(result))
{
return 0;
}

return 1;

Sprite:

ID3D11Resource* resource;
ZeroMemory(&resource, sizeof(resource));
texture->GetResource(&resource);

ID3D11Texture2D* tex = (ID3D11Texture2D*)resource;

D3D11_TEXTURE2D_DESC t;
ZeroMemory(&t, sizeof(t));
tex->GetDesc(&t);

Vertex v[4];
ZeroMemory(&v, sizeof(v));

v[0].Position = XMFLOAT3((float)destinationRectangle.value.left, (float)destinationRectangle.value.top, z);
v[1].Position = XMFLOAT3((float)destinationRectangle.value.right, (float)destinationRectangle.value.top, z);
v[2].Position = XMFLOAT3((float)destinationRectangle.value.right, (float)destinationRectangle.value.bottom, z);
v[3].Position = XMFLOAT3((float)destinationRectangle.value.left, (float)destinationRectangle.value.bottom, z);

v[0].Texture = XMFLOAT2((float)(sourceRectangle.value.left / t.Width), (float)(sourceRectangle.value.top / t.Height));
v[1].Texture = XMFLOAT2((float)(sourceRectangle.value.right / t.Width), (float)(sourceRectangle.value.top / t.Height));
v[2].Texture = XMFLOAT2((float)(sourceRectangle.value.right / t.Width), (float)(sourceRectangle.value.bottom / t.Height));
v[3].Texture = XMFLOAT2((float)(sourceRectangle.value.left / t.Width), (float)(sourceRectangle.value.bottom / t.Height));

v[0].Color = color;
v[1].Color = color;
v[2].Color = color;
v[3].Color = color;

Sprite* sprite = new Sprite();
sprite->Vertices.push_back(v[0]);
sprite->Vertices.push_back(v[1]);
sprite->Vertices.push_back(v[2]);
sprite->Vertices.push_back(v[3]);
sprite->Texture = texture;

m_sprites.push_back(sprite);

Я схожу с ума? Я глупый? Или есть просто более простой способ сделать это? Благодарю. Любая помощь приветствуется!

Также хочу отметить, что у спрайта, который я рисую, есть прямоугольник (слева = 300, справа = 500, сверху = 350, снизу = 450) на экране 800×600 с белым цветом. Текстура загружается правильно, и я даже попытался просто вывести цвет в шейдере, чтобы убедиться, что все безуспешно.

Да, и значение Z спрайта, который я пытаюсь нарисовать, установлено равным 0,5f, хотя я пытался установить его на разные значения, но это то, что я ожидал работать с ним.

3

Решение

Я нашел ответ благодаря MJP на другом сайте. Проблема была в этой строке:

indexData.pSysMem = &indices;

Как и должно было быть:

indexData.pSysMem = &indices[0];

Очевидно, я отправлял указатель на весь вектор, а не на первый экземпляр, поэтому буфер индекса не знал, о чем я!

Как я уже сказал, я только начал программирование DirectX из программирования XNA. 😉

Я надеюсь, что это помогает кому-то еще в аналогичной должности.

3

Другие решения

Вы настроили DepthStencil для использования 2D?
Также попробуйте отрицательное Z в положение камеры, вы положили его на 0

0

По вопросам рекламы [email protected]