簡體   English   中英

DirectX 11 精靈 2D 相機

[英]DirectX 11 Sprite 2D Camera

長期讀者。 第一次海報。 我遇到了一個問題,它已經破壞了腦細胞幾個小時了,而且速度很快。 所以我想我會把它推到這里以獲得一雙新的眼睛......

基本上,我正在嘗試使用 C++ 和 DirectX 11 創建一個 2D 游戲。我之前使用過 C# 和 XNA,並且我已經在 DirectX 中制作了一些 3D 東西,但沒有這么大。

我現在正在嘗試使用基本相機和基本精靈批處理在我的屏幕中央繪制一個精靈,但沒有出現任何東西,我一生都無法弄清楚原因。 我會發布一些代碼來提供一個想法。

這是我在相機類中設置所有矩陣的地方,它們保持這種狀態(目前,稍后將更改為移動等):

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;   
}

如您所見,非常簡單的東西。 但根本沒有任何東西被吸引到屏幕上。 我試過根本不打擾矩陣,省略世界矩陣,使用透視投影矩陣,使用查看而不是查看矩陣,通過 XMMatrixOrthographicLH 使用 (0, 0, 0) 作為中心並將精靈位置轉換為屏幕空間。

我什至大大簡化了精靈批次,將其限制為一次只能繪制一個精靈!

我正在使用一個不可變的索引緩沖區 (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;

精靈:

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);

我要瘋了嗎? 我傻嗎? 或者有沒有更簡單的方法來做到這一點? 謝謝。 任何幫助表示贊賞!

還要指出的是,我正在繪制的精靈在 800x600 屏幕上有一個全白色的矩形(左 = 300,右 = 500,頂部 = 350,底部 = 450)。 紋理被正確加載,我什至嘗試在着色器中輸出顏色只是為了確保沒有運氣。

哦,我嘗試繪制的精靈的 Z 值設置為 0.5f,雖然我嘗試將其設置為不同的值,但這是我期望使用它的值。

感謝 MJP,我在另一個網站上找到了答案。 問題是這一行:

indexData.pSysMem = &indices;

本來應該是這樣的:

indexData.pSysMem = &indices[0];

顯然,我發送的是指向整個向量而不是第一個實例的指針,因此索引緩沖區不知道我在做什么!

就像我說的,我剛剛從 XNA 編程開始 DirectX 編程。 ;)

我希望這可以幫助處於類似位置的其他人。

您是否配置了 DepthStencil 以使用 2D? 還可以嘗試將 Z 軸設為負值,將其設置為 0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM