D3D11如何将纹理中alpha值为0的像素渲染成透明的?
How does D3D11 render pixels with an alpha value of 0 in the texture as transparent?
我使用 DrawIconEx(GDI/D3D11 互操作性和 CopyResource)生成了一个 ID3D11Texture2D,它有许多 alpha 通道值为 0 的像素。此纹理已通过 D3D11_USAGE_STAGING/Map 验证查看像素值并ScreenGrab保存png(相关代码需要修改:DXGI_FORMAT_B8G8R8A8_UNORM->使用GUID_WICPixelFormat32bppBGRA代替GUID_WICPixelFormat24bppBGR)。
当我使用Tutorial 5: Texturing的渲染纹理方法时,0像素的alpha值会渲染成黑色,这不是我想要的,我希望这些像素渲染成透明的。将做什么来实现目标?这是我的相关代码:
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;
}
问题已解决:在渲染“alpha”贴图前进行OMGetBlendState(_blend_state...设置,渲染后恢复默认blendstate
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);
}
}
我使用 DrawIconEx(GDI/D3D11 互操作性和 CopyResource)生成了一个 ID3D11Texture2D,它有许多 alpha 通道值为 0 的像素。此纹理已通过 D3D11_USAGE_STAGING/Map 验证查看像素值并ScreenGrab保存png(相关代码需要修改:DXGI_FORMAT_B8G8R8A8_UNORM->使用GUID_WICPixelFormat32bppBGRA代替GUID_WICPixelFormat24bppBGR)。
当我使用Tutorial 5: Texturing的渲染纹理方法时,0像素的alpha值会渲染成黑色,这不是我想要的,我希望这些像素渲染成透明的。将做什么来实现目标?这是我的相关代码:
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; }
问题已解决:在渲染“alpha”贴图前进行OMGetBlendState(_blend_state...设置,渲染后恢复默认blendstate
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);
}
}