Abstract
Keywords OpenGL  C++ 
Citation Yao Qing-sheng.如何制作透明背景的 OpenGL 渲染上下文?.FUTURE & CIVILIZATION Natural/Social Philosophy & Infomation Sciences,20220613. https://yaoqs.github.io/20220613/ru-he-zhi-zuo-tou-ming-bei-jing-de-opengl-xuan-ran-shang-xia-wen/

转载自腾讯云社区

这是一个古老的问题,但由于新版本的 Windows 有合成和对 opengl 的支持,正如 datenwolf 所暗示的那样,我们可以使用一些特殊的调料来实现这一点。尽管这对于 DirectX 来说也是微不足道的 (如图所示) 微软确实在 opengl 上下文中添加了合成提示。耶,反垄断的恐惧!

因此,您必须使用指定 alpha 通道的像素格式创建一个 opengl 上下文,并且它应该使用合成 (第 82 行)。然后,使用 DwmApi.h 例程启用一个模糊窗口 (第 179 行),其中指定了一个完全无效的区域,这将模糊任何内容并使窗口保持透明。(您需要在窗口类上指定一个 black+transparent 笔刷!奇怪!) 然后,您实际上只是使用 opengl,就像您习惯使用它一样。在事件循环中,只要有机会,您就可以绘制和交换缓冲区 (第 201 行),并记住启用 GL_BLEND!😃

请查看 /fork https://gist.github.com/3644466,或者只查看基于 OP 自己的答案的以下代码片段,而不是使用此技术 (您可以将其放在一个空项目中):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <windowsx.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include <dwmapi.h>

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")

#pragma comment (lib, "dwmapi.lib")

#include <assert.h>
#include <tchar.h>

#ifdef assert
#define verify(expr) if(!expr) assert(0)
#else verify(expr) expr
#endif

const TCHAR szAppName[]=_T("TransparentGL");
const TCHAR wcWndName[]=_T("TransparentGL");

HDC hDC;
HGLRC m_hrc;
int w = 240;
int h = 240;

BOOL initSC() {
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);

return 0;
}

void resizeSC(int width,int height) {
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glMatrixMode(GL_MODELVIEW );
glLoadIdentity();
}

BOOL renderSC() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glPushMatrix();

glColor3f(0, 1, 1);
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd();

glPopMatrix();
glFlush();

return 0;
}

BOOL CreateHGLRC(HWND hWnd) {
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_SUPPORT_COMPOSITION | // Format Must Support Composition
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
32, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
8, // An Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
24, // 16Bit Z-Buffer (Depth Buffer)
8, // Some Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};

HDC hdc = GetDC(hWnd);
int PixelFormat = ChoosePixelFormat(hdc, &pfd);
if (PixelFormat == 0) {
assert(0);
return FALSE ;
}

BOOL bResult = SetPixelFormat(hdc, PixelFormat, &pfd);
if (bResult==FALSE) {
assert(0);
return FALSE ;
}

m_hrc = wglCreateContext(hdc);
if (!m_hrc){
assert(0);
return FALSE;
}

ReleaseDC(hWnd, hdc);

return TRUE;
}

LRESULT CALLBACK WindowFunc(HWND hWnd,UINT msg, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;

switch(msg) {
case WM_CREATE:
break;

case WM_DESTROY:
if(m_hrc) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(m_hrc) ;
}
PostQuitMessage(0) ;
break;

default:
return DefWindowProc(hWnd,msg,wParam,lParam);
}

return 0;
}

int WINAPI _tWinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR str,int nWinMode) {
WNDCLASSEX wc;
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowFunc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hThisInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(0x00000000);
wc.lpszClassName = szAppName;

if(!RegisterClassEx(&wc)) {
MessageBox(NULL, _T("RegisterClassEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}

HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, szAppName, wcWndName,
WS_VISIBLE | WS_POPUP, 200, 150, w, h,
NULL, NULL, hThisInst, NULL);

if(!hWnd) {
MessageBox(NULL, _T("CreateWindowEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}

DWM_BLURBEHIND bb = {0};
HRGN hRgn = CreateRectRgn(0, 0, -1, -1);
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
bb.hRgnBlur = hRgn;
bb.fEnable = TRUE;
DwmEnableBlurBehindWindow(hWnd, &bb);

CreateHGLRC(hWnd);

HDC hdc = GetDC(hWnd);
wglMakeCurrent(hdc, m_hrc);
initSC();
resizeSC(w, h);
ReleaseDC(hWnd, hdc);

MSG msg;
while(1) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
HDC hdc = GetDC(hWnd);
wglMakeCurrent(hdc, m_hrc);

renderSC();

SwapBuffers(hdc);
ReleaseDC(hWnd, hdc);
}
}

return (FALSE);
}
References