我正在尝试学习如何在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);
任何人都可以帮助我理解这里发生了什么吗?
答案 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值为零不会使像素变黑。您需要打开并使用混合状态来实现这一目标。