DirectX9中ColorFill与DrawString调用时D3DCOLOR的Alpha值不生效问题
DirectX9自定义绘图Alpha透明失效问题解决方案
问题核心原因
DrawFilledBox逻辑问题
- 你使用
StretchRect复制离屏Surface到后备缓冲的方案本身不支持Alpha混合,该API只会做像素的直接覆盖拷贝,哪怕源Surface带Alpha通道,也不会和后备缓冲已有像素做混合计算,所以Alpha值直接失效。同时该方案需要频繁创建销毁临时Surface,性能损耗极大,不适用于高频绘制场景。
DrawString逻辑问题
ID3DXFont::DrawText方法第一个参数传nullptr时,不会走Sprite的Alpha混合管线,你设置的Sprite的D3DXSPRITE_ALPHABLEND参数完全不会生效,而且你当前先End Sprite再绘制文本的逻辑顺序也是错误的。
修复方案
1. 填充矩形绘制逻辑重构
改用顶点绘制方案,主动开启Alpha混合渲染状态即可实现透明效果:
bool DrawFilledBox(int x, int y, int w, int h, BYTE r, BYTE g, BYTE b, BYTE a) { if (!this->m_pDevice) return false; // 先End Sprite避免状态冲突 if (FAILED(this->m_pSpriteMgr->End())) return false; // 保存原有渲染状态,避免影响其他绘制逻辑 DWORD oldAlphaEnable, oldSrcBlend, oldDestBlend, oldFvf; m_pDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &oldAlphaEnable); m_pDevice->GetRenderState(D3DRS_SRCBLEND, &oldSrcBlend); m_pDevice->GetRenderState(D3DRS_DESTBLEND, &oldDestBlend); m_pDevice->GetFVF(&oldFvf); // 开启标准Alpha混合 m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); m_pDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); // 构建矩形顶点 struct RectVertex { float x, y, z, rhw; D3DCOLOR color; } vertices[4] = { {(float)x, (float)y, 0.0f, 1.0f, D3DCOLOR_ARGB(a, r, g, b)}, {(float)x + w, (float)y, 0.0f, 1.0f, D3DCOLOR_ARGB(a, r, g, b)}, {(float)x, (float)y + h, 0.0f, 1.0f, D3DCOLOR_ARGB(a, r, g, b)}, {(float)x + w, (float)y + h, 0.0f, 1.0f, D3DCOLOR_ARGB(a, r, g, b)} }; // 绘制矩形 bool drawResult = SUCCEEDED(m_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(RectVertex))); // 恢复原有渲染状态 m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, oldAlphaEnable); m_pDevice->SetRenderState(D3DRS_SRCBLEND, oldSrcBlend); m_pDevice->SetRenderState(D3DRS_DESTBLEND, oldDestBlend); m_pDevice->SetFVF(oldFvf); // 重启Sprite绘制 if (FAILED(this->m_pSpriteMgr->Begin(D3DXSPRITE_ALPHABLEND))) return false; return drawResult; }
2. DrawString逻辑修复
调整调用逻辑,将Sprite对象传入DrawText即可利用已有的Alpha混合配置:
bool DrawString(const d3dfont_s* pFont, const std::wstring& wszText, int x, int y, BYTE r, BYTE g, BYTE b, BYTE a) { if ((!this->m_pDevice) || (!wszText.length()) || (!pFont)) return false; RECT rect = { x, y, x, y }; D3DCOLOR d3dcColor = D3DCOLOR_ARGB(a, r, g, b); // 直接传入Sprite对象,不需要提前End Sprite INT iResult = pFont->pFont->DrawText(this->m_pSpriteMgr, wszText.c_str(), (int)wszText.length(), &rect, DT_NOCLIP, d3dcColor); return iResult != 0; }
额外检查项
- 确认设备初始化时
D3DPRESENT_PARAMETERS的BackBufferFormat参数设置为带Alpha的格式,比如D3DFMT_A8R8G8B8,不要使用无Alpha的D3DFMT_X8R8G8B8格式。 - 如果有其他自定义绘制逻辑,注意绘制完成后及时恢复渲染状态,避免状态污染影响后续绘制。
内容的提问来源于stack exchange,提问作者frontend-newb
相关产品推荐
相关产品推荐

