Windows 8 Store App DirectX 11.1使用带有alpha的加载PNG纹理启用Blendstate

时间:2013-02-13 17:09:06

标签: windows-8 windows-store-apps directx-11 alphablending c++-cx

我正在使用以下代码加载具有透明度的PNG:

ComPtr<IWICStream> stream;
ComPtr<IWICBitmapDecoder> bitmapDecoder;
ComPtr<IWICBitmapFrameDecode> bitmapFrame;
ComPtr<IWICFormatConverter> formatConverter;
unsigned int width, height
D3D11_SUBRESOURCE_DATA resourceData;

ZeroMemory(&resourceData, sizeof(resourceData));

DX::ThrowIfFailed( m_wicFactory->CreateStream(&stream) );
DX::ThrowIfFailed( stream->InitializeFromMemory( rawFileBytes->Data, rawFileBytes->Length) );
DX::ThrowIfFailed( m_wicFactory->CreateDecoderFromStream( stream.Get(), nullptr, WICDecodeMetadataCacheOnDemand, &bitmapDecoder ) );
DX::ThrowIfFailed( bitmapDecoder->GetFrame(0, &bitmapFrame) );
DX::ThrowIfFailed( m_wicFactory->CreateFormatConverter(&formatConverter) );
DX::ThrowIfFailed( formatConverter->Initialize( bitmapFrame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 1.0f /* some docs set this to 0.0f */, WICBitmapPaletteTypeCustom ) );
DX::ThrowIfFailed( bitmapFrame->GetSize(&width, &height) );

std::unique_ptr<byte[]> bitmapPixels(new byte[width * height * 4]);
DX::ThrowIfFailed( formatConverter->CopyPixels( nullptr, width * 4, width * height * 4, bitmapPixels.get() ) );

resourceData.pSysMem = bitmapPixels.get();
resourceData.SysMemPitch = width * 4;
resourceData.SysMemSlicePitch = 0;

CD3D11_TEXTURE2D_DESC textureDesc( DXGI_FORMAT_B8G8R8A8_UNORM, width, height, 1, 1 );
DX::ThrowIfFailed( m_d3dDevice->CreateTexture2D( &textureDesc, &resourceData, &texture2D ) );

if ( textureView != nullptr ) {
  CD3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc( texture2D.Get(), D3D11_SRV_DIMENSION_TEXTURE2D );
  DX::ThrowIfFailed( m_d3dDevice->CreateShaderResourceView( texture2D.Get(), &shaderResourceViewDesc, &shaderResourceView ) );
}

并在代码的不同部分设置我的混合状态:

Microsoft::WRL::ComPtr<ID3D11BlendState1> blendState;

D3D11_BLEND_DESC1 desc;
ZeroMemory( &desc, sizeof( desc ) );
desc.IndependentBlendEnable = FALSE;
desc.AlphaToCoverageEnable = FALSE;
desc.RenderTarget[0].BlendEnable = TRUE;
desc.RenderTarget[0].LogicOpEnable = FALSE;
desc.RenderTarget[0].SrcBlend = D3D11_BLEND::D3D11_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend = D3D11_BLEND::D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP::D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND::D3D11_BLEND_ONE;
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND::D3D11_BLEND_ONE;
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP::D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

direct3d.device->CreateBlendState1( &desc, blendState.GetAddressOf() );
direct3d.context->OMSetBlendState( blendState.Get(), NULL, 0xffffffff );

通过所有这些设置,我仍然会得到应该有alpha的黑色背景。

澄清:我有一组48个正方形面板,从z 0.0f到48.0f彼此重叠,但我能看到的只是前面的48.0f纹理。它们不是透明区域透明,而是呈现为黑色。

编辑:这是我的像素着色器:

Texture2D Texture : register(t0);
SamplerState Sampler : register(s0);

struct sPSInput
{
    float4 pos : SV_POSITION;
    float3 norm : NORMAL;
    float2 tex : TEXCOORD0;
};

float4 SimplePixelShader(sPSInput input) : SV_TARGET
{
  float4 textured = Texture.Sample(Sampler, input.tex);
  return textured;
}

2 个答案:

答案 0 :(得分:1)

这个

    desc.RenderTarget[0].SrcBlend = D3D11_BLEND::D3D11_BLEND_ONE;

应该是这个

   desc.RenderTarget[0].SrcBlend = D3D11_BLEND::D3D11_BLEND_ALPHA;

还应根据您的需要将AlphaToCoverageEnable设置为false

此外,您必须禁用Z缓冲区。启用的Z缓冲区可以防止绘制前面对象后面的所有对象。

答案 1 :(得分:0)

您需要将Z值标准化到0.0f(近) - 1.0f(远)范围。

您是否正确设置了ViewPort?

D3D11_VIEWPORT Viewport =
{
    0.0f,                           // TopLeftX
    0.0f,                           // TopLeftY
    <width>,                        // Width
    <height>,                       // Height
    0.0f,                           // MinDepth
    1.0f };                         // MaxDepth