DirectX 11 Sprite 2D相机

时间:2013-01-06 02:43:14

标签: c++ camera directx 2d sprite

长时间读者。第一次海报。我遇到了一个问题,这个问题已经在几个小时内摧毁了脑细胞并且没有快速到达。所以我以为我会把它推到这里以获得一双新鲜的眼睛......

基本上我正在尝试使用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;   
}

正如你所看到的,非常简单的东西。但根本没有任何东西被吸引到屏幕上。我已经尝试过根本不打扰矩阵,使用透视投影矩阵,使用透视投影矩阵,而不是查看矩阵,使用(0,0,0)作为中心通过XMMatrixOrthographicLH并将精灵位置转换为屏幕空间。

我甚至大大简化了sprite批处理,限制它一次只绘制一个sprite!

我正在使用不可变索引缓冲区(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);
我生气了吗?我是傻瓜吗?或者只是一个简单的方法来做到这一点?谢谢。任何帮助表示赞赏!

同样要指出我正在绘制的精灵在800x600屏幕上有一个全白色的矩形(左= 300,右= 500,顶部= 350,底部= 450)。纹理正确加载,我甚至尝试在着色器中输出颜色,以确保没有运气。

哦,我想要绘制的精灵的Z值设置为0.5f,虽然我已经尝试将其设置为不同的值,但这是我期望使用它的那个。

2 个答案:

答案 0 :(得分:3)

我感谢MJP在另一个网站上找到了答案。问题是这一行:

indexData.pSysMem = &indices;

应该是这样的:

indexData.pSysMem = &indices[0];

显然,我发送了一个指向整个向量而不是第一个实例的指针,因此索引缓冲区不知道我在做什么!

就像我说的,我刚刚从XNA编程开始Dir​​ectX编程。 ;)

我希望这可以帮助处于类似位置的其他人。

答案 1 :(得分:0)

您是否配置了DepthStencil以使用2D? 同时尝试负Z到相机位置,你把它放在0