带有opengl的GDI +可能吗?

Posted

技术标签:

【中文标题】带有opengl的GDI +可能吗?【英文标题】:Is GDI+ with opengl possible? 【发布时间】:2017-05-23 05:34:25 【问题描述】:

我试图让 gdiplus 和 opengl 在一个屏幕外 hdc 中协同工作。当前代码是这样的(不能上网)

    创建一个 gdiplus 位图 A 从 A 创建一个 gdiplus 图形作为 B 获取 B 的 HDC 为 HDC 选择合适的像素格式 从 HDC 创建 gdiplus 图形作为 C 从 HDC 创建一个 opengl 上下文作为 D 用 C 和 D 绘图 向 B 发布 HDC 在其他图形上绘制 A

需要C是因为我发现我将HDC释放到B后,opengl无法更改位图。 为了检查一切是否正常,我通过在 (9) 之前读取 gl 像素添加了位图 E

当前程序仍有问题 释放 hdc 后,位图 A 丢失其 alpha 信息。 位图 E 在正确的 alpha 下工作正常,但 GL_BGRA 无法读取 alpha,所以我必须读取 GL_RGBA 数据并将每个像素转换为 gdiplus 颜色格式。

我应该只使用E还是有其他尝试?

releasehdc alpha loss示例:

Bitmap bitmap(100,100);
Graphics graphics(&bitmap);
HDC hdc=graphics.GetHDC();
Graphics graphics2(hdc);
graphics2.Clear(Color(128,255,0,0));
graphics2.Flush();
graphics.ReleaseHDC(hdc);
//draw bitmap to other graphics

注意:我只是发现 gdiplus 实际上并没有使用 HDC 中的 alpha 通道,只有 rgb 通道是共享的,所以我想知道它如何与 BGRA 目标位图一起使用

【问题讨论】:

我不使用 GDI+,但 GDI 不知道 alpha,而是通过使用透明颜色来实现透明度。所以没有 alpha 但更像 Sprite 蒙版)如果你需要在 OpenGL 端使用 alpha .... 你可以获取 GDI 的东西作为纹理 ... 【参考方案1】:

我认为同时使用 OpenGL 和 GDI+ 的最佳方式是generate a texture in GDI+, then load that into OpenGL。

这里的要点是:

void MakeTexture(GLuint& texId)

    Bitmap offscreen(512, 512, PixelFormat32bppARGB);
    Graphics gr(&offscreen);

    gr.Clear(Color(128, 255, 0, 0));
    Gdiplus::SolidBrush brush(Color(255, 0, 0, 255));
    Pen pen(Color(128, 255, 0, 0), 16.f);
    Font font(L"Arial", 48.f);
    Rect r(25, 25, 100, 100);
    gr.DrawRectangle(&pen, r);
    gr.DrawString(TEXT("TEST STRING"), -1, &font, PointF(50, 50), &brush);

    vector<DWORD> argb;
    GetBitsLockBits(offscreen, argb, 1);
    genTexture(texId, offscreen.GetWidth(), offscreen.GetHeight(), argb);


void GetBitsLockBits(Bitmap& bmp, vector<DWORD>& argb, bool invert = 0)

    BitmapData bmpData;
    RectF rectf;
    Unit unit;
    bmp.GetBounds(&rectf, &unit);
    Rect rect(rectf.X, rectf.Y, rectf.Width, rectf.Height);
    printf("Got rect %d %d %d %d\n", rect.X, rect.Y, rect.Width, rect.Height);
    bmp.LockBits(&rect, ImageLockModeRead, PixelFormat32bppARGB, &bmpData);
    printf("BMP has w=%d h=%d stride=%d\n", bmpData.Width, bmpData.Height, bmpData.Stride);
    argb.resize(bmpData.Width * bmpData.Height);

    if (invert)
        for (int i = 0; i < bmpData.Height; i++)
            memcpy(&argb[i * bmpData.Width], (GLuint*)bmpData.Scan0 + (bmpData.Height - 1 - i) * bmpData.Width, bmpData.Width * 4);
    else if (bmpData.Stride == bmpData.Width * 4)
        memcpy(&argb[0], bmpData.Scan0, bmpData.Width * bmpData.Height * 4); // If the bmp is padded then
    // this won't read the image correctly (it will read it with pad bits between)
    else
        for (int i = 0; i < bmpData.Height; i++)
            memcpy(&argb[i * bmpData.Width], (GLuint*)bmpData.Scan0 + i * bmpData.Width, bmpData.Width * 4);
    bmp.UnlockBits(&bmpData);


void genTexture(GLuint& texId, int w, int h, const vector<DWORD>& argb)

    glGenTextures(1, &texId);  CHECK_GL;
    glBindTexture(GL_TEXTURE_2D, texId);  CHECK_GL;
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);  CHECK_GL;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  CHECK_GL;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  CHECK_GL;
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &argb[0]);  CHECK_GL;

通过直接在同一个窗口中绘制来尝试让 OpenGL 和 GDI+ 协作可能会得到非常闪烁的结果。

【讨论】:

以上是关于带有opengl的GDI +可能吗?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在已经使用 GDI+ 的窗口中使用 OpenGL?

可能不支持 OpenGL 的“弃用”功能吗?

带有 OpenGL 上下文的基于 Qt 的命令行工具

带有 OpenCV 和 OpenGL 的 AR

使用带有移动对象的 OpenGL 实例化绘图

带有 Qt 和 OpenGL 的轨迹球控件