C++ SetPixelFormat未为OpenGL创建alpha通道
我以前也能做到这一点,我不知道两周前和上次windows更新之间发生了什么变化,但出于某种原因,C++ SetPixelFormat未为OpenGL创建alpha通道,c++,windows,opengl,C++,Windows,Opengl,我以前也能做到这一点,我不知道两周前和上次windows更新之间发生了什么变化,但出于某种原因,SetPixelFormat没有创建alpha通道 gDebugger显示窗口的后缓冲区只有3个通道 白色+0 alpha渲染为白色 因此,我所做的事情本身就存在一些问题,或者是一次更新破坏了它 下面的代码应该可以粘贴到一个空的VS项目中 #include <Windows.h> #include <dwmapi.h> #include <gl/GL.h> #pr
SetPixelFormat
没有创建alpha通道
gDebugger显示窗口的后缓冲区只有3个通道
白色+0 alpha渲染为白色 因此,我所做的事情本身就存在一些问题,或者是一次更新破坏了它 下面的代码应该可以粘贴到一个空的VS项目中
#include <Windows.h>
#include <dwmapi.h>
#include <gl/GL.h>
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"dwmapi.lib")
HWND hWnd = 0;
HDC hDC = 0;
HGLRC hRC = 0;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = WndProc;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.lpszClassName = TEXT("why_class");
RegisterClassEx(&wcex);
// no errors
hWnd = CreateWindowEx(
NULL,
TEXT("why_class"),
TEXT("why_window"),
WS_OVERLAPPEDWINDOW,
128,128,
256,256,
NULL,
NULL,
hInstance,
NULL
);
// no errors
PIXELFORMATDESCRIPTOR pfd = {0};
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW|
PFD_SUPPORT_OPENGL|
PFD_DOUBLEBUFFER|
PFD_SUPPORT_COMPOSITION;
pfd.cColorBits = 32;
pfd.cAlphaBits = 8; // need an alpha channel
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
hDC = GetDC(hWnd);
int i = ChoosePixelFormat(hDC,&pfd);
SetPixelFormat(hDC,i,&pfd);
// no errors
hRC = wglCreateContext(hDC);
// no errors
wglMakeCurrent(hDC,hRC);
// no errors
// EDIT: Turn on alpha testing (which actually won't
// fix the clear color problem below)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// EDIT: Regardless of whether or not GL_BLEND is enabled,
// a clear color with an alpha of 0 should (or did at one time)
// make this window transparent
glClearColor(
0,0,0, // if this is (1,1,1), the window renders
// solid white regardless of the alpha
0 // changing the alpha here has some effect
);
DWM_BLURBEHIND bb = {0};
bb.dwFlags = DWM_BB_ENABLE|DWM_BB_TRANSITIONONMAXIMIZED;
bb.fEnable = TRUE;
bb.fTransitionOnMaximized = TRUE;
DwmEnableBlurBehindWindow(hWnd,&bb);
// no errors
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
// no errors
MSG msg = {0};
while(true){
GetMessage(&msg,NULL,NULL,NULL);
if(msg.message == WM_QUIT){
return (int)msg.wParam;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
// this vertex should be transparent,
// as it was when I last built this test
//
// it renders as white
glColor4f(1,1,1,0);
glVertex2f(0,0);
glColor4f(0,1,1,1);
glVertex2f(1,0);
glColor4f(1,0,1,1);
glVertex2f(0,1);
glEnd();
SwapBuffers(hDC);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
}return 0;
default:
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
#包括
#包括
#包括
#pragma注释(lib,“opengl32.lib”)
#pragma注释(lib,“dwmapi.lib”)
HWND-HWND=0;
HDC-HDC=0;
HGLRC hRC=0;
LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM);
int APICENTRY WinMain(
HINSTANCE HINSTANCE,
HINSTANCE HPPrevenstance,
LPSTR lpCmdLine,
国际nCmdShow
)
{
WNDCLASSEX wcex={0};
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.lpfnWndProc=WndProc;
wcex.hCursor=LoadCursor(空,IDC_箭头);
wcex.lpszClassName=文本(“为什么_类”);
注册类别(&wcex);
//没有错误
hWnd=CreateWindowEx(
无效的
文本(“为什么上课”),
文本(“为什么窗口”),
WS_重叠窗口,
128,128,
256,256,
无效的
无效的
hInstance,
无效的
);
//没有错误
像素格式描述符pfd={0};
pfd.nSize=sizeof(pfd);
pfd.inversion=1;
pfd.dwFlags=pfd\u DRAW\u TO\u窗口|
PFD_支持_OPENGL|
双缓冲器|
PFD_支持_组成;
pfd.cColorBits=32;
pfd.cAlphaBits=8;//需要alpha通道
pfd.cDepthBits=24;
pfd.cStencilBits=8;
hDC=GetDC(hWnd);
int i=选择像素格式(hDC和pfd);
SetPixelFormat(hDC、i和pfd);
//没有错误
hRC=wglCreateContext(hDC);
//没有错误
wglMakeCurrent(hDC,hRC);
//没有错误
//编辑:启用alpha测试(实际上不会
//修复下面的清晰颜色问题)
glEnable(GL_混合物);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_减去GL_SRC_ALPHA);
//编辑:无论是否启用了GL_混合,
//alpha为0的清晰颜色应(或一次显示)
//使这个窗口透明
glClearColor(
0,0,0,//如果这是(1,1,1),则窗口渲染
//纯白,不考虑阿尔法
0//在此处更改alpha会产生一些效果
);
DWM_bb={0};
bb.dwFlags=DWM_bb_启用| DWM_bb_转换未最大化;
bb.fEnable=TRUE;
bb.ftTransitionOnMaximized=真;
DWMEnableBluhindWindow(hWnd和bb);
//没有错误
显示窗口(hWnd、SW_显示正常);
更新窗口(hWnd);
//没有错误
MSG={0};
while(true){
GetMessage(&msg,NULL,NULL,NULL);
如果(msg.message==WM\u退出){
返回(int)msg.wParam;
}
翻译信息(&msg);
发送消息(&msg);
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
glBegin(GL_三角形);
//这个顶点应该是透明的,
//就像我上次做这个测试时一样
//
//它呈现为白色
gl4f(1,1,1,0);
glVertex2f(0,0);
gl4f(0,1,1,1);
glVertex2f(1,0);
gl4f(1,0,1,1);
glVertex2f(0,1);
格伦德();
SwapBuffers(hDC);
}
返回(int)msg.wParam;
}
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM)
{
开关(信息)
{
案例WM_销毁:
{
PostQuitMessage(0);
}返回0;
违约:
打破
}
返回DefWindowProc(hWnd、message、wParam、lParam);
}
通常无法获得同时具有32位颜色和8位alpha的帧缓冲区
我没有试过你的代码,但是我建议把颜色位切换到24
pfd.cColorBits = 24;
pfd.cAlphaBits = 8;
如果要使用混合,只需调用:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
虽然要使其工作,您必须在三角形后面有一些东西来混合(黑色背景不算!)“白色+0 alpha渲染为白色。”当然,它会渲染白色;你没有打开混合。Alpha并不意味着“透明”。它意味着你想表达的意思。所以,如果你想让alpha表示“透明”,你必须让它表示“透明”。通常通过使用混合模式。我真的没有注意到这里没有alpha测试。。。我希望我以前有过它的截图,但我想我是在处理一个bug,它允许以这种方式直接渲染到帧缓冲区。我启用了alpha测试以查看这是否可行,但是它不会影响所指示的顶点(它仍然呈现白色,刚才只是略微透明)。然而,我的问题是,为什么我的窗口突然没有alpha通道,或者为什么我渲染的所有内容看起来都像是windows需要预乘alpha。@NicolBolas:我认为OP是指用于窗口合成的alpha通道,即透明窗口。(PFD_支持_合成标志集)。对合成器处理alpha通道的方式几乎没有影响,但通常假定为不透明度。有些排字器假定预乘alpha,而另一些排字器则假定预乘alpha。有关X11/GLX的等效示例,请参阅。在MSDN的文档页上的
PIXELFORMATDESCRIPTOR
,在cAlphaBits
下,它说:“指定每个RGBA颜色缓冲区中的alpha位平面数。不支持alpha位平面。”这是不是意味着你无法获得阿尔法频道?@JWWalker:我不知道那个段文档是什么意思。谢谢你的回答。我仍然会得到一个没有alpha的24位颜色缓冲区,即使我只是将整个内容保留为0(除了标志、版本和大小)。唯一的区别是,如果我为cAlphaBits指定任何数字,窗口实际上是透明渲染的(使用愚蠢的预乘alpha无意义),我只是无法访问alpha通道@