C++ SetPixelFormat未为OpenGL创建alpha通道

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

我以前也能做到这一点,我不知道两周前和上次windows更新之间发生了什么变化,但出于某种原因,
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通道@