带有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 +可能吗?的主要内容,如果未能解决你的问题,请参考以下文章