1

我正在尝试学习如何在 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);

谁能帮我理解这里发生了什么?

4

1 回答 1

4

这是一个字节顺序问题。大多数处理器您可能会以“小端”顺序处理存储整数。这意味着整数值以四个字节的顺序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 值不会使您的像素变黑。您需要打开并使用混合状态来实现这一点。

于 2014-06-04T00:20:41.543 回答