winapi - D3D11如何将纹理中alpha值为0的像素渲染为透明?
问题描述
我使用DrawIconEx(GDI/D3D11互操作性和CopyResource)生成了一个ID3D11Texture2D,它有许多alpha通道值为0的像素。这个纹理已经通过D3D11_USAGE_STAGING/Map验证来查看像素值和ScreenGrab保存png(相关代码需要修改:DXGI_FORMAT_B8G8R8A8_UNORM->使用 GUID_WICPixelFormat32bppBGRA 代替 GUID_WICPixelFormat24bppBGR)。
当我使用教程 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);
}
}
推荐阅读
- c++ - 决策和递归函数
- css - 后备 vars vaule 插入括号
- c# - 为什么我不能从 NUnit 项目中测试这个 DAO 项目方法?System.IO.FileNotFoundException 无法加载文件或程序集'System.Data.SqlClient
- c++ - C++ ThreadSafe 计时类
- ios - 为什么 UITableView 滚动时会更新约束?
- actions-on-google - 温度控制特性的可视化界面,谷歌设备操作
- c# - 如何将 IdentityUser 设置为 ForeignKey?
- wordpress - 加载资源失败:409(冲突)
- android - 存储用户资料图片、隐私政策问题
- javascript - 如何绑定`this`来减少?