How does D3D11 render pixels with an alpha value of 0 in the texture as transparent?

0
  • I used DrawIconEx (GDI/D3D11 interoperability and CopyResource) to generate an ID3D11Texture2D which has many pixels with an alpha channel value of 0. this texture has been verified by D3D11_USAGE_STAGING/Map to view the pixel value and ScreenGrab save png (relevant code needs to be modified: DXGI_FORMAT_B8G8R8A8_UNORM->Use GUID_WICPixelFormat32bppBGRA instead of GUID_WICPixelFormat24bppBGR).

  • When I use the rendering texture method of Tutorial 5: Texturing, the alpha value of 0 pixels will be rendered as black, which is not what i want, I hope these pixels render to be transparent. What will be done to achieve the goal? Here is my relevant code:

     HRESULT CGraphRender::Init()
     {
         ...
    
         // Create an alpha enabled blend state description.
         _blend_state = nullptr;
    
         D3D11_BLEND_DESC blendDesc;
         ZeroMemory(&blendDesc, sizeof(D3D11_BLEND_DESC));
    
         blendDesc.RenderTarget[0].BlendEnable = TRUE;   
         blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
         blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
         blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
         blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
         blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
         blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
         blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
    
         hr = _d3d_device->CreateBlendState(&blendDesc, &_blend_state);
         RETURN_ON_FAIL(hr);
    
         ....
     }
    
     HRESULT CGraphRender::Clear_3D(float color[])
     {
         ID3D11RenderTargetView* rtv[] = { _back_rendertarget_view };
         _immediate_context->OMSetRenderTargets(_countof(rtv), rtv, nullptr);
         _immediate_context->ClearRenderTargetView(_back_rendertarget_view, color);
    
         float blendFactor[4] = { 1.f, 1.f, 1.f, 1.f };
         _immediate_context->OMSetBlendState(_blend_state, blendFactor, 0xffffffff);
    
         return S_OK;
     }
    
winapi
gdi
direct3d
direct3d11
asked on Stack Overflow Nov 1, 2020 by fredirty2017 • edited Nov 7, 2020 by Acorn

1 Answer

0

The problem has been solved: Perform the OMGetBlendState(_blend_state... setting before rendering the "alpha" texture, and restore the default blendstate after rendered

HRESULT CGraphRender::DrawTexture(const std::shared_ptr<CDrawTextureShader>& texture, const RECT& dst_rect, const BOOL& is_blend_alpha)
{
    CComPtr<ID3D11DeviceContext> immediate_context;
    _d3d_device->GetImmediateContext(&immediate_context);
    if (!immediate_context)
    {
        return E_UNEXPECTED;
    }

    if (is_blend_alpha)
    {
        CComPtr<ID3D11BlendState> old_blend_state;
        FLOAT   old_blend_factor[4] = { 0.f };
        UINT    old_sample_mask = 0;

        immediate_context->OMGetBlendState(&old_blend_state, old_blend_factor, &old_sample_mask);

        float blend_factor[4] = { 1.f, 1.f, 1.f, 1.f };
        immediate_context->OMSetBlendState(_blend_state, blend_factor, 0xffffffff);

        HRESULT hr = texture->Render(immediate_context, dst_rect);

        immediate_context->OMSetBlendState(old_blend_state, old_blend_factor, old_sample_mask);

        return hr;
    }
    else
    {
        return texture->Render(immediate_context, dst_rect);
    }
}
answered on Stack Overflow Nov 11, 2020 by fredirty2017

User contributions licensed under CC BY-SA 3.0