RGBA请求时,ABGR格式的Direct3D 11纹理

时间:2014-06-03 23:37:11

标签: direct3d hlsl texture-mapping direct3d11

我正在尝试学习如何在Direct3D 11中进行纹理映射。

我已成功将纹理映射到四边形。问题是Direct3D将我的像素数据解释为ABGR,当我特意请求DXGI_FORMAT_R8G8B8A8时,我不明白为什么。

以下是我用来创建ID3D11Texture2D对象的代码:

UINT pixels[] = {
    0xff00ff00, 0xff0000ff,
    0xffff0000, 0xffffffff,
};

D3D11_SUBRESOURCE_DATA subresourceData;
subresourceData.pSysMem = pixels;
subresourceData.SysMemPitch = 8;
subresourceData.SysMemSlicePitch = 16;

D3D11_TEXTURE2D_DESC texture2dDesc;
texture2dDesc.Width = 2;
texture2dDesc.Height = 2;
texture2dDesc.MipLevels = 1;
texture2dDesc.ArraySize = 1;
texture2dDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texture2dDesc.SampleDesc.Count = 1;
texture2dDesc.SampleDesc.Quality = 0;
texture2dDesc.Usage = D3D11_USAGE_DEFAULT;
texture2dDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texture2dDesc.CPUAccessFlags = 0;
texture2dDesc.MiscFlags = 0;

ID3D11Texture2D *texture;
device->CreateTexture2D(&texture2dDesc, &subresourceData, &texture);

创建ID3D11ShaderResourceView对象的代码:

D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
memset(&shaderResourceViewDesc, 0, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
shaderResourceViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;

ID3D11ShaderResourceView *shaderResourceView;
device->CreateShaderResourceView(texture, &shaderResourceViewDesc, &shaderResourceView);

创建ID3D11SamplerState对象的代码:

D3D11_SAMPLER_DESC samplerDesc;
memset(&samplerDesc, 0, sizeof(D3D11_SAMPLER_DESC));
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;

ID3D11SamplerState *samplerState;
device->CreateSamplerState(&samplerDesc, &samplerState);

最后是HLSL像素着色器:

Texture2D image;
SamplerState samplerState;

float4 PixelMain(float4 position: SV_POSITION, float2 texel: TEXCOORD): SV_TARGET {
    return image.Sample(samplerState, texel);
}

渲染纹理的颜色为

green  red
blue   white

但他们应该

black  red
black  white

当然,我记得曾致电deviceContext->PSSetShaderResources(0, 1, &shaderResourceView);deviceContext->PSSetSamplers(0, 1, &samplerState);

任何人都可以帮助我理解这里发生了什么吗?

1 个答案:

答案 0 :(得分:2)

这是一个endianness问题。您可能会处理的大多数处理器都存储整数和小端"订购。这意味着0xAABBCCDD的整数值在内存中以四个字节0xDD, 0xCC, 0xBB, 0xAA的顺序结束。我知道这是违反直觉的,所以我建议您使用Visual Studio内存窗口来查看像素数组在内存中的最终结果。

Direct3D /您的GPU不会将像素视为32位整数,而是将其视为四个连续的8位整数,因此在从纹理读取时不会再次交换字节并且会看到有效像素值0xDDCCBBAA。解决方案是在一个字节数组中指定您的图像,每个像素有四个条目,每个组件一个。在你的情况下:

BYTE pixels[] = {
    0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff,
    0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
};

此外,SysMemSlicePitch参数与2D纹理无关。无需将其设置为16.并且alpha值为零不会使像素变黑。您需要打开并使用混合状态来实现这一目标。