You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 11:57:02