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

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

  1. 创建一个 gdiplus 位图 A
  2. 从 A 创建一个 gdiplus 图形作为 B
  3. 获取 B 的 HDC
  4. 为 HDC 选择合适的像素格式
  5. 从 HDC 创建 gdiplus 图形作为 C
  6. 从 HDC 创建一个 opengl 上下文作为 D
  7. 用 C 和 D 绘图
  8. 向 B 发布 HDC
  9. 在其他图形上绘制 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 的东西作为纹理 ...

标签: c++ windows opengl 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+ 协作可能会得到非常闪烁的结果。

【讨论】:

    猜你喜欢
    • 2014-06-15
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 2014-09-24
    • 2014-11-01
    • 2013-07-18
    • 2015-03-03
    • 1970-01-01
    相关资源
    最近更新 更多