【问题标题】:How can i render OpenGL to a semi transparent Win32 window? [duplicate]如何将 OpenGL 渲染到半透明的 Win32 窗口? [复制]
【发布时间】:2020-07-12 03:31:12
【问题描述】:

我正在为 C 和 C++ 编写一个窗口库来处理 OpenGL 的无边界和非矩形窗口。我有一个问题:我希望库让用户绘制到 RGBA,我的意思是没有背景,那么窗口可以有任何形状。我做了很多研究,我认为我必须使用 DWM api 并模糊窗口(参见下面的代码)我使用 glClearColor(0.0f, 0.0f, 0.0f. 0.0f);它应该显示一个完全透明的窗口(所以什么都没有),但它仍然看到一个黑色的半透明矩形(就像 alpha chanel 是 ~0.1f),如果我改变颜色,窗口的颜色会改变,如果我设置一个更高阿尔法香奈儿,窗口更明显,所以它似乎工作但不正确。这是一个问题,我希望能够拥有完全透明的窗口。我正在使用 DWM,但如果有更好的解决方案,请告诉我。这个问题也可能来自OpenGL混合状态,我不知道。

代码:

#define UNICODE

#define GLEW_STATIC

#include <windows.h>
#include <dwmapi.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

#include <glew.h>

LRESULT CALLBACK wnd_proc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp);

int main(void){
    int initial_clock = clock();

    WNDCLASSEX wcx = {};
    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.lpszClassName = L"win32_class";
    wcx.lpfnWndProc = wnd_proc;
    RegisterClassEx(&wcx);

    HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, L"win32_class", L"Title",
        WS_POPUP, 100, 100, 800, 400, NULL, NULL, NULL, NULL);

    ShowWindow(hWnd, 1);

    HDC device_context = GetDC(hWnd);

    PIXELFORMATDESCRIPTOR pfd = {};
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 8;

    int pixel_format = ChoosePixelFormat(device_context, &pfd);
    SetPixelFormat(device_context, pixel_format, &pfd);
    HGLRC rendering_context = wglCreateContext(device_context);
    wglMakeCurrent(device_context, rendering_context);

    glewInit();

    DWM_BLURBEHIND blur = {};
    blur.dwFlags = DWM_BB_ENABLE;
    blur.fEnable = 1;
    blur.hRgnBlur = NULL;
    DwmEnableBlurBehindWindow(hWnd, &blur);

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

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0)){
        DispatchMessage(&msg);
        glClear(GL_COLOR_BUFFER_BIT);
        wglSwapLayerBuffers(device_context, WGL_SWAP_MAIN_PLANE);
    }
}

LRESULT CALLBACK wnd_proc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
    switch(uMsg){
        case WM_NCHITTEST: return HTCAPTION;
        default:           return DefWindowProc(hWnd, uMsg, wp, lp);
    }
}

【问题讨论】:

    标签: c++ c winapi opengl


    【解决方案1】:

    你可以使用SetLayeredWindowAttributes函数。

    设置分层窗口的不透明度和透明度颜色键。

    添加:

    LONG Style = GetWindowLong(hWnd, GWL_EXSTYLE); 
    SetWindowLong(hWnd, GWL_EXSTYLE, Style | WS_EX_LAYERED);
    SetLayeredWindowAttributes(hWnd, 0, 10, LWA_ALPHA);
    

    当 bAlpha 为 0 时,窗口是完全透明的。当 bAlpha 为 255 时,窗口是不透明的。

    调试(bAlpha = 10):

    完整代码:

    #define UNICODE
    
    #define GLEW_STATIC
    
    #include <windows.h>
    #include <dwmapi.h>
    #include <stdlib.h>
    #include <time.h>
    #include <stdio.h>
    
    #include <glew.h>
    
    LRESULT CALLBACK wnd_proc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp);
    
    int main(void){
        int initial_clock = clock();
    
        WNDCLASSEX wcx = {};
        wcx.cbSize = sizeof(WNDCLASSEX);
        wcx.lpszClassName = L"win32_class";
        wcx.lpfnWndProc = wnd_proc;
        RegisterClassEx(&wcx);
    
        HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, L"win32_class", L"Title",
            WS_POPUP, 100, 100, 800, 400, NULL, NULL, NULL, NULL);
    
        ShowWindow(hWnd, 1);
    
        HDC device_context = GetDC(hWnd);
    
        PIXELFORMATDESCRIPTOR pfd = {};
        pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
        pfd.nVersion = 1;
        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
        pfd.iPixelType = PFD_TYPE_RGBA;
        pfd.cColorBits = 32;
        pfd.cDepthBits = 24;
        pfd.cStencilBits = 8;
    
        int pixel_format = ChoosePixelFormat(device_context, &pfd);
        SetPixelFormat(device_context, pixel_format, &pfd);
        HGLRC rendering_context = wglCreateContext(device_context);
        wglMakeCurrent(device_context, rendering_context);
    
        glewInit();
    
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    
        MSG msg;
        while(GetMessage(&msg, NULL, 0, 0)){
            DispatchMessage(&msg);
            glClear(GL_COLOR_BUFFER_BIT);
            wglSwapLayerBuffers(device_context, WGL_SWAP_MAIN_PLANE);
        }
    }
    
    LRESULT CALLBACK wnd_proc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
        switch(uMsg){
            case WM_CREATE:
            {
                LONG Style = GetWindowLong(hWnd, GWL_EXSTYLE); 
                SetWindowLong(hWnd, GWL_EXSTYLE, Style | WS_EX_LAYERED);
                SetLayeredWindowAttributes(hWnd, 0, 10, LWA_ALPHA);
            }
            break;
            case WM_NCHITTEST: return HTCAPTION;
            default:           return DefWindowProc(hWnd, uMsg, wp, lp);
        }
    }
    

    【讨论】:

    • 这不是我需要的,它将所有像素与相同的 alpha 混合。但我现在找到了怎么做。还是谢谢你。
    • @linternetsansfil 好的,你可以发布你的答案并标记它。
    猜你喜欢
    • 1970-01-01
    • 2018-10-08
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 2019-07-15
    • 2014-08-12
    • 2014-08-07
    • 2011-12-26
    相关资源
    最近更新 更多