C 如何创建具有透明背景的OpenGL渲染上下文?

C 如何创建具有透明背景的OpenGL渲染上下文?,c,winapi,opengl,transparency,C,Winapi,Opengl,Transparency,渲染上下文的背景通常为纯色黑色或其他颜色,请参见下图: 我想知道是否可以设置一个没有装饰和透明背景的窗口,同时允许我在上面渲染OpenGL的东西 这会产生三角形在屏幕上浮动的错觉。透明背景应允许您查看桌面或其他可能在其后面的应用程序 你能举例说明一下源代码吗 平台:仅限Windows win32我知道这在Windows 7中是可能的,但不确定早期版本 要去除窗口边框,需要从窗口中删除WS_OVERLAPPEDWINDOW样式,并添加WS_弹出式样式: 要使OpenGL窗口的背景透明,需要使用Dw

渲染上下文的背景通常为纯色黑色或其他颜色,请参见下图:

我想知道是否可以设置一个没有装饰和透明背景的窗口,同时允许我在上面渲染OpenGL的东西

这会产生三角形在屏幕上浮动的错觉。透明背景应允许您查看桌面或其他可能在其后面的应用程序

你能举例说明一下源代码吗


平台:仅限Windows win32

我知道这在Windows 7中是可能的,但不确定早期版本

要去除窗口边框,需要从窗口中删除WS_OVERLAPPEDWINDOW样式,并添加WS_弹出式样式:

要使OpenGL窗口的背景透明,需要使用DwmEnableBlurBehindWindow函数:

DWM_BLURBEHIND bb = {0};
bb.dwFlags = DWM_BB_ENABLE;
bb.fEnable = true;
bb.hRgnBlur = NULL;
DwmEnableBlurBehindWindow(hWnd, &bb);
调用glClearColor时,还需要为alpha值指定0

此外,在创建OpenGL上下文时,请确保分配alpha通道


现在你的背景应该是完全透明的。如果保留窗口装饰,则背景将使用Aero blur外观,您可以使用glClearColor中的alpha值调整透明度级别。

如果允许OpenGL窗口分层,这将非常容易。但是他们不是,所以你必须去做别的事情

你可以做的是创建一个分层窗口WS_EX_layered+SetLayeredWindowAttributes——如果你不知道如何处理透明度,就用谷歌搜索它们,并创建一个隐藏的OpenGL窗口进行渲染。将OpenGL场景渲染到屏幕外缓冲区,将其读回并与分层窗口共享,然后使用bitblt GDI函数将其渲染到分层窗口

这对于非常复杂的东西来说可能太慢了,但是会给你想要的效果,并且可以在Windows2000和更高版本上工作

编辑:在创建实际的屏幕外缓冲区时,帧缓冲区对象FBO可能是最好的选择。你可以在隐藏的OpenGL窗口上画图,尽管我想我记得有人在帖子中提到,由于像素所有权,会遇到麻烦,建议使用FBO。您也可以使用像素缓冲区pbuffer,但这是一种过时的传统,FBO被认为是实现这一点的现代方式。FBO应该为您提供硬件加速(如果支持的话),并且不会将您限制在特定的OpenGL版本。您需要一个OpenGL上下文来使用它,因此您必须创建隐藏的OpenGL窗口并从那里设置FBO

以下是有关FBO的一些资源:
对于mac,但可能会有帮助

您可以将3d场景渲染到pbuffer,然后使用颜色键将其显示到屏幕上。

在一次失败的悬赏上花费了一些声誉以获得有关此问题的帮助后,我终于意识到我感兴趣的问题有多复杂

完成这项任务的少数人。在我的研究中,我发现了不同的方法来实现我所寻找的目标。其中最有趣的是AeroGL,它显示了使用一种到目前为止还没有提到的技术,即将图形渲染到DIB

要永久关闭此线程,下面的源代码实现了该技术。代码本身是对Andrei Sapronov Y.提出的一个应用程序的轻微修改

最终结果如下图所示:

该代码已在Windows XP 32位和Windows 8.1 32位上进行了测试。 享受吧


ClanLib游戏SDK就是这样做的

如果只需要静态透明边框,请使用以下技术:

创建5个窗口

AAAA

卑诗省

卑诗省

DDD

A、 B、C、D是分层窗口

这是主窗口


请参阅-

伟大的演示集底部的图片,其中source将逐步介绍:


由于到目前为止给出的所有答案都只针对Windows,但肯定也有人要求在X11上使用复合窗口管理器进行此操作,作为参考,我在这里发布示例代码,也可以在


主要技巧是获得正确的FBConfig。您需要请求alpha通道并测试相关的XRenderPictFormat是否存在alpha掩码。

这是一个老问题,但由于较新版本的Windows具有opengl的合成和支持(如datenwolf提示),因此我们可以使用一些特殊的调料来实现这一点。虽然DirectX的go figure也很简单。。。微软确实向opengl上下文添加了合成提示。反托拉斯恐惧

因此,我们可以让合成引擎了解如何利用opengl上下文,而不是低效的复制到物理内存操作

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

请根据OP自己的回答,使用此技术查看/分叉或仅查看以下代码段,您可以在空项目中重复此操作:

定义_WIN32_WINNT 0x0500 包括 包括 包括 包括 包括 pragma注释库,opengl32.lib pragma注释库,glu32.lib pragma注释库,dwmapi.lib 包括 包括 ifdef断言 定义verifyexpr if!expr资产0 else verifyexpr expr 恩迪夫 const TCHAR szAppName[]=\u tttransparentgl; const TCHAR wcWndName[]=\u tttransparentgl; HDC-HDC; HGLRC m_hrc; int w=240; int h=240; 布尔初始化{ glEnableGL_α_试验; glEnableGL_深度试验; glEnableGL_颜色_材料; glEnableGL_照明; glEnableGL_LIGHT0; glEnableGL_混合物; glBlendFuncGL_SRC_ALPHA,GL_ONE_减去SRC_ALPHA; glClearColor0,0,0,0; 返回0; } 空隙大小调整间隙宽度,内部高度{ glViewport0,0,宽度,高度; glMatrixModeGL_投影; glLoadIdentity; glMatrixModeGL_模型视图; glLoadIdentity; } 布尔渲染器{ glClearGL_颜色_缓冲_位| GL_深度_缓冲_位; GLP矩阵; GL3F0,1,1; glBeginGL_三角形;//使用三角形绘制 glColor3f1.0f,0.0f,0.0f;//将颜色设置为红色 glVertex3f 0.0f、1.0f、0.0f;//顶部 glColor3f0.0f、1.0f、0.0f;//将颜色设置为绿色 glVertex3f-1.0f,-1.0f,0.0f;//左下角 glColor3f0.0f、0.0f、1.0f;//将颜色设置为蓝色 glVertex3f 1.0f,-1.0f,0.0f;//右下角 格伦德; GLPOP矩阵; glFlush; 返回0; } BOOL CreateHGLRCHWND hWnd{ 像素格式描述符pfd={ sizeofPIXELFORMATDESCRIPTOR, 1,//版本号 PFD_DRAW_TO_WINDOW |//格式必须支持WINDOW PFD_支持_OPENGL |//格式必须支持OPENGL PFD_支持_合成|//格式必须支持合成 PFD_DOUBLEBUFFER,//必须支持双缓冲 PFD_TYPE_RGBA,//请求RGBA格式 32,//选择我们的颜色深度 0,0,0,0,0,0,//忽略颜色位 8、//一个Alpha缓冲区 0,//已忽略移位位 0,//无累积缓冲区 0,0,0,0,//忽略累加位 24,//16位Z缓冲区深度缓冲区 8,//一些模具缓冲区 0,//没有辅助缓冲区 PFD_主平面,//主绘图层 0,//保留 0,0,0//忽略图层遮罩 }; HDC HDC=GetDChWnd; int PixelFormat=选择像素格式(&pfd); 如果PixelFormat==0{ 资产0; 返回FALSE; } BOOL-bResult=SetPixelFormathdc、PixelFormat和pfd; 如果bResult==FALSE{ 资产0; 返回FALSE; } m_hrc=wglCreateContexthdc; 如果{ 资产0; 返回FALSE; } 释放DCHWND、hdc; 返回TRUE; } LRESULT回调窗口funchwnd hWnd,UINT msg,WPARAM WPARAM,LPARAM LPARAM{ PAINTSTRUCT-ps; 开关味精{ 案例WM_创建: 打破 案例WM_销毁: ifm_hrc{ wglMakeCurrentNULL,NULL; wglDeleteContextm_hrc; } PostQuitMessage0; 打破 违约: 返回DefWindowProchWnd、msg、wParam、lParam; } 返回0; } int WINAPI\u tWinMainHINSTANCE HthiInst、HINSTANCE hPrevInst、LPSTR str、int nWinMode{ WNDCLASSEX wc; memset&wc,0,sizeofwc; wc.cbSize=sizeofWNDCLASSEX; wc.hIconSm=加载图标,IDI_应用程序; wc.style=CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc=WNDPROCWindowFunc; wc.cbClsExtra=0; wc.cbWndExtra=0; wc.hInstance=hThisInst; wc.hIcon=加载图标,IDI_应用程序; wc.hCursor=LoadCursorNULL,IDC_箭头; wc.hbrBackground=HBRUSHCreateSolidBrush0x00000000; wc.lpszClassName=szAppName; 如果!注册类(&wc){ MessageBoxNULL,_TRegisterClassEx-失败,_恐怖,MB_正常| MB|i错误; 返回FALSE; } HWND HWND=CreateW indowExWS_EX_APPWINDOW、szAppName、wcWndName、, WS|U可见| WS|U弹出窗口,200、150、w、h、, NULL,NULL,hThisInst,NULL; 如果hWnd{ MessageBoxNULL,TCreateWindowEx-失败,TError,MB_OK | MB_ICONERROR; 返回FALSE; } DWM_bb={0}; HRGN HRGN=CreateRectRgn0,0,-1,-1; bb.dwFlags=DWM_bb_启用| DWM_bb_区域; bb.hRgnBlur=hRgn; bb.fEnable=TRUE; DWMEnableBluhindWindowHWnd和&bb; 创建hglrchwnd; HDC HDC=GetDChWnd; wglMakeCurrenthdc,m_hrc; initSC; resizeSCw,h; 释放DCHWND、hdc; 味精; while1{ 如果peek消息和消息为空,则为0,0,PM_删除{ 翻译信息&msg; DispatchMessage&msg; } 否则{ HDC HDC=GetDChWnd; wglMakeCurrenthdc,m_hrc; renderSC; SwapBuffershdc; 释放DCHWND、hdc; } } 返回FALSE; }
我知道这很旧,但我正试图将Xlib解决方案移植到Gtk+。经过大量的研究,我终于做到了,所以我真的很想在这里分享给有需要的人

#include <gtk/gtk.h>
#include <gdk/gdkscreen.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtkgl.h>
#include <GL/gl.h>
#include <GL/glu.h>

static gboolean supports_alpha = FALSE;

/***
 *** Configure the OpenGL framebuffer.
***/
static GdkGLConfig* configure_gl(void)
{
    GdkGLConfig* glconfig;

    /* Try double-buffered visual */
    glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGBA |
        GDK_GL_MODE_ALPHA |
        GDK_GL_MODE_DEPTH |
        GDK_GL_MODE_DOUBLE);
    if (glconfig == NULL)
    {
        printf("Cannot find the double-buffered visual.\n");
        printf("No appropriate OpenGL-capable visual found.\n");
        exit(1);
    }
    printf("Find GLConfig with alpha channel.\n");
    return glconfig;
}

static void screen_changed(GtkWidget* widget, GdkScreen* old_screen, gpointer userdata)
{
    /* To check if the display supports alpha channels, get the colormap */
    GdkScreen* screen = gtk_widget_get_screen(widget);
    GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);

    if (!colormap)
    {
        printf("Your screen does not support alpha channels!\n");
        colormap = gdk_screen_get_rgb_colormap(screen);
        supports_alpha = FALSE;
    }
    else
    {
        printf("Your screen supports alpha channels!\n");
        supports_alpha = TRUE;
    }

    gtk_widget_set_colormap(widget, colormap);
}

static gboolean expose(GtkWidget* widget, GdkEventExpose* event, gpointer userdata)
{
    GdkGLContext* glcontext = gtk_widget_get_gl_context(widget);
    GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(widget);

    if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
    {
        return FALSE;
    }

    glDrawBuffer(GL_BACK);

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glBegin(GL_QUADS);
    glColor4f(1.0f, 0.0f, 0.0f, 0.3f);
    glVertex3f(-0.5f, -0.5f, 0);
    glVertex3f(+0.5f, -0.5f, 0);
    glVertex3f(+0.5f, +0.5f, 0);
    glVertex3f(-0.5f, +0.5f, 0);
    glEnd();

    gdk_gl_drawable_swap_buffers(gldrawable);

    gdk_gl_drawable_gl_end(gldrawable);
    return TRUE;
}

int main(int argc, char** argv)
{
    gtk_init(&argc, &argv);

    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    /* Added to config GLConfig */
    GdkGLConfig* glconfig = configure_gl();
    gtk_widget_set_gl_capability(window,
        glconfig,
        NULL,
        TRUE,
        GDK_GL_RGBA_TYPE);

    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
    gtk_window_set_title(GTK_WINDOW(window), "Alpha Demo");
    g_signal_connect(G_OBJECT(window), "delete-event", gtk_main_quit, NULL);

    gtk_widget_set_app_paintable(window, TRUE);

    g_signal_connect(G_OBJECT(window), "expose-event", G_CALLBACK(expose), NULL);
    g_signal_connect(G_OBJECT(window), "screen-changed", G_CALLBACK(screen_changed), NULL);

    screen_changed(window, NULL, NULL);

    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}
使用gcc main.c-o main`pkg config-libs-cflags gtk+-2.0 gtkglext-1.0`编译。在Ubuntu18.04上测试除了gtk之外,您还需要安装libgtkglext1-dev

编辑

我将渲染代码从简单的glClear更改为矩形

该代码是来自和的修改版本


谢谢,但是DWMenableBluhindWindow是DWM的一部分,它不属于Win32 API。此解决方案适用于Windows Vista及以上版本。@karlphilip:Pre-Vista Windows:es没有桌面合成功能,因此我不确定您是否能在那里很好地完成它。@karlphilip。很抱歉,我个人还没有得到透明的OpenGL windows与XP一起工作,但我记得在OpenGL论坛上看到过关于它的帖子。尝试查看以下搜索结果以获取更多信息:这确实很有帮助,但我想添加以下内容:对于我来说,上述方法使用默认的Win7模糊和伪光反射渲染所有背景。为了消除模糊并获得完全透明的窗口,我将bb.hRgnBlur参数设置为CreateRectRgn0,0,1,1;和bb.dwFlags到DWM_bb_ENABLE | DWM_bb_BLURREGION;。这将使一个像素模糊,并将使用glClear清除的窗口的其余部分显示为完全透明。当我尝试此操作时,我得到的标识符DWM_BLURBEHIND未定义。我需要包括一个图书馆吗?这与我的建议类似。将OpenGL场景渲染到内存FBO或类似对象,然后使用glReadPixels存储到位图对象中。然后你可以选择你的透明颜色,并使用GDI将其位图显示在屏幕上。值得一提的是,这种技术对于复杂的渲染和图形动画并不实用。为每个帧将GPU数据复制到RAM对CPU的要求很高,导致FPS较低。查看此答案上的注释:请注意,在Windows Vista和Windows 7中,您可以获得与下面我的x11argb演示相同的效果。PIXELFORMATDESCRIPTOR支持启用合成的新标志。不过,我还没有为此创建一个演示。直到四月份,当我再次有时间的时候才会发生。我有这些pragma注释pragma commentlib,opengl32.lib pragma commentlib,User32.lib pragma commentlib,Gdi32.lib在2020年64位。谢谢,但问题特别是问如何仅使用Win32 API实现此效果。OpenGL分层Windows演示基本上是实现此效果的最佳方式,pbuffer比直接渲染到DIB快得多。DIB通常使用软件渲染器,其中pbuffer被加速到WWW!难以置信的我使用:g++gl_transparent.cpp-o gl_transparent-lGL-lX11-lXext-lXrender编译了它。如果我们这些天还在做类似的事情,这可能会成为一个社区wiki。@karlphillip:在我的github存储库中,你会发现一个makefile。这个演示的一个变体,使用片段着色器添加波浪效果——只用于eyecandy。不幸的是,不可能将背景合并到着色器效果中,因为整个背景只有在所有窗口都绘制完内容后才由合成器创建。我理解。谢谢你的提醒。@datenwolf我本来是在寻求帮助,但我成功地将你的代码转换成现代OpenGL。我将在这里发布我的解决方案,以供将来参考。非常感谢教程。我也想要没有边界的。我想用opengl在屏幕上画一个橡皮画矩形,但我没有找到它的例子。在Win7上效果很好。当我使窗口大小与屏幕大小完全相等时,背景变成黑色而不是透明,就好像Aero假设窗口是全屏的,即使它实际上不是。我可以通过使窗口比屏幕高1个像素来解决这个问题,即使用window\ux=0,window\uy=-1,window\u width=screen\u width,window\u height=screen\u heig
ht+1作为传递给CreateWindowEx的值,然后像往常一样调用glViewport0、0、screen\u width、screen\u height。回答得很好!正是我需要的。所有其他答案都显示了将其绘制到屏幕外缓冲区,然后将其BitBlt到可见的绘图上下文的方法,该方法速度非常慢,不适用于任何严肃的应用程序。有趣的是,您共享的其中一个链接也是来自我的另一个答案。一定要把一切都投上去。如果你分享这个程序运行的截图,让我们知道它是什么样子的,我会投票给你这个答案。哦,很抱歉,虽然我经常使用谷歌的stackoverflow,但我丢失了密码,并且很长时间没有登录。我将来会这样做。谢谢你的另一个答案,也谢谢你的建议。我会尝试添加一个屏幕截图来改进,但是否投票还是你自己的选择@Karlphillip这个截图会给你的答案增加很多价值。
glClearColor(0.0f,0.0f,0.0f,0.0f);
#define _WIN32_WINNT 0x0500

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

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.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("WS_EX_LAYERED OpenGL");

HDC hDC;            
HGLRC m_hrc;        
int w(240);
int h(240); 

HDC pdcDIB;                 
HBITMAP hbmpDIB;            
void *bmp_cnt(NULL);        
int cxDIB(0); 
int cyDIB(0);   
BITMAPINFOHEADER BIH;       


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;
}

// DIB -> hDC
void draw(HDC pdcDest)
{
    assert(pdcDIB);

    verify(BitBlt(pdcDest, 0, 0, w, h, pdcDIB, 0, 0, SRCCOPY));
}

void CreateDIB(int cx, int cy)
{
    assert(cx > 0); 
    assert(cy > 0);

    cxDIB = cx ;
    cyDIB = cy ;

    int iSize = sizeof(BITMAPINFOHEADER);   
    memset(&BIH, 0, iSize);

    BIH.biSize = iSize;
    BIH.biWidth = cx;   
    BIH.biHeight = cy;  
    BIH.biPlanes = 1;   
    BIH.biBitCount = 24;    
    BIH.biCompression = BI_RGB;

    if(pdcDIB) 
        verify(DeleteDC(pdcDIB));

    pdcDIB = CreateCompatibleDC(NULL);
    assert(pdcDIB);

    if(hbmpDIB) 
        verify(DeleteObject(hbmpDIB));

    hbmpDIB = CreateDIBSection(
        pdcDIB,         
        (BITMAPINFO*)&BIH,  
        DIB_RGB_COLORS,     
        &bmp_cnt,       
        NULL,
        0);

    assert(hbmpDIB);
    assert(bmp_cnt);

    if(hbmpDIB)
        SelectObject(pdcDIB, hbmpDIB);
}

BOOL CreateHGLRC()
{
    DWORD dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP;

    PIXELFORMATDESCRIPTOR pfd ;
    memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR)) ;
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
    pfd.nVersion = 1;                       
    pfd.dwFlags =  dwFlags ;                
    pfd.iPixelType = PFD_TYPE_RGBA ;        
    pfd.cColorBits = 24 ;                   
    pfd.cDepthBits = 32 ;                   
    pfd.iLayerType = PFD_MAIN_PLANE ;       

   int PixelFormat = ChoosePixelFormat(pdcDIB, &pfd);
   if (PixelFormat == 0){
      assert(0);
      return FALSE ;
   }

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

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

   return TRUE;
}

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

    switch(msg) 
    {
        case WM_ERASEBKGND:
            return 0;
        break;

        case WM_CREATE:
        break;

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

        case WM_PAINT:
            hDC = BeginPaint(hWnd, &ps);
            renderSC(); // OpenGL -> DIB
            draw(hDC);  // DIB -> hDC
            EndPaint(hWnd, &ps);
        break;

        case WM_SIZE:
            w = LOWORD(lParam); h = HIWORD(lParam);         
            wglMakeCurrent(NULL, NULL);
            wglDeleteContext(m_hrc);

            CreateDIB(w, h);
            CreateHGLRC();
            verify(wglMakeCurrent(pdcDIB, m_hrc));

            initSC();
            resizeSC(w, h);
            renderSC();
        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) (COLOR_WINDOW);
    wc.lpszClassName = szAppName;

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

    HWND hWnd = CreateWindowEx(WS_EX_LAYERED, 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;
    }

    verify(SetLayeredWindowAttributes(hWnd, 0x0, 0, LWA_COLORKEY));

    MSG msg;
    while(1) 
    {
        while (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){
            if (GetMessage(&msg, NULL, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else return 0;
        }
    } 

    return (FALSE); 
}
/*------------------------------------------------------------------------
 * A demonstration of OpenGL in a  ARGB window 
 *    => support for composited window transparency
 *
 * (c) 2011 by Wolfgang 'datenwolf' Draxinger
 *     See me at comp.graphics.api.opengl and StackOverflow.com
  
 * License agreement: This source code is provided "as is". You
 * can use this source code however you want for your own personal
 * use. If you give this source code to anybody else then you must
 * leave this message in it.
 *
 * This program is based on the simplest possible 
 * Linux OpenGL program by FTB (see info below)
 
  The simplest possible Linux OpenGL program? Maybe...

  (c) 2002 by FTB. See me in comp.graphics.api.opengl

  --
  <\___/>
  / O O \
  \_____/  FTB.

------------------------------------------------------------------------*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <X11/Xutil.h>

#define USE_CHOOSE_FBCONFIG

static void fatalError(const char *why)
{
    fprintf(stderr, "%s", why);
    exit(0x666);
}

static int Xscreen;
static Atom del_atom;
static Colormap cmap;
static Display *Xdisplay;
static XVisualInfo *visual;
static XRenderPictFormat *pict_format;
static GLXFBConfig *fbconfigs, fbconfig;
static int numfbconfigs;
static GLXContext render_context;
static Window Xroot, window_handle;
static GLXWindow glX_window_handle;
static int width, height;

static int VisData[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 16,
None
};

static int isExtensionSupported(const char *extList, const char *extension)
{
 
  const char *start;
  const char *where, *terminator;
 
  /* Extension names should not have spaces. */
  where = strchr(extension, ' ');
  if ( where || *extension == '\0' )
    return 0;
 
  /* It takes a bit of care to be fool-proof about parsing the
     OpenGL extensions string. Don't be fooled by sub-strings,
     etc. */
  for ( start = extList; ; ) {
    where = strstr( start, extension );
 
    if ( !where )
      break;
 
    terminator = where + strlen( extension );
 
    if ( where == start || *(where - 1) == ' ' )
      if ( *terminator == ' ' || *terminator == '\0' )
        return 1;
 
    start = terminator;
  }
  return 0;
}

static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
{    
    return d && e && arg && (e->type == MapNotify) && (e->xmap.window == *(Window*)arg);
}

static void describe_fbconfig(GLXFBConfig fbconfig)
{
    int doublebuffer;
    int red_bits, green_bits, blue_bits, alpha_bits, depth_bits;

    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DOUBLEBUFFER, &doublebuffer);
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_RED_SIZE, &red_bits);
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_GREEN_SIZE, &green_bits);
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_BLUE_SIZE, &blue_bits);
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_ALPHA_SIZE, &alpha_bits);
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DEPTH_SIZE, &depth_bits);

    fprintf(stderr, "FBConfig selected:\n"
        "Doublebuffer: %s\n"
        "Red Bits: %d, Green Bits: %d, Blue Bits: %d, Alpha Bits: %d, Depth Bits: %d\n",
        doublebuffer == True ? "Yes" : "No", 
        red_bits, green_bits, blue_bits, alpha_bits, depth_bits);
}

static void createTheWindow()
{
    XEvent event;
    int x,y, attr_mask;
    XSizeHints hints;
    XWMHints *startup_state;
    XTextProperty textprop;
    XSetWindowAttributes attr = {0,};
    static char *title = "FTB's little OpenGL example - ARGB extension by WXD";

    Xdisplay = XOpenDisplay(NULL);
    if (!Xdisplay) {
        fatalError("Couldn't connect to X server\n");
    }
    Xscreen = DefaultScreen(Xdisplay);
    Xroot = RootWindow(Xdisplay, Xscreen);

    fbconfigs = glXChooseFBConfig(Xdisplay, Xscreen, VisData, &numfbconfigs);
    fbconfig = 0;
    for(int i = 0; i<numfbconfigs; i++) {
        visual = (XVisualInfo*) glXGetVisualFromFBConfig(Xdisplay, fbconfigs[i]);
        if(!visual)
            continue;

        pict_format = XRenderFindVisualFormat(Xdisplay, visual->visual);
        XFree(visual);
        if(!pict_format)
            continue;

        fbconfig = fbconfigs[i];
        if(pict_format->direct.alphaMask > 0) {
            break;
        }
    }

    if(!fbconfig) {
        fatalError("No matching FB config found");
    }

    describe_fbconfig(fbconfig);

    /* Create a colormap - only needed on some X clients, eg. IRIX */
    cmap = XCreateColormap(Xdisplay, Xroot, visual->visual, AllocNone);

    attr.colormap = cmap;
    attr.background_pixmap = None;
    attr.border_pixmap = None;
    attr.border_pixel = 0;
    attr.event_mask =
        StructureNotifyMask |
        EnterWindowMask |
        LeaveWindowMask |
        ExposureMask |
        ButtonPressMask |
        ButtonReleaseMask |
        OwnerGrabButtonMask |
        KeyPressMask |
        KeyReleaseMask;

    attr_mask = 
        CWBackPixmap|
        CWColormap|
        CWBorderPixel|
        CWEventMask;

    width = DisplayWidth(Xdisplay, DefaultScreen(Xdisplay))/2;
    height = DisplayHeight(Xdisplay, DefaultScreen(Xdisplay))/2;
    x=width/2, y=height/2;

    window_handle = XCreateWindow(  Xdisplay,
                    Xroot,
                    x, y, width, height,
                    0,
                    visual->depth,
                    InputOutput,
                    visual->visual,
                    attr_mask, &attr);

    if( !window_handle ) {
        fatalError("Couldn't create the window\n");
    }

#if USE_GLX_CREATE_WINDOW
    int glXattr[] = { None };
    glX_window_handle = glXCreateWindow(Xdisplay, fbconfig, window_handle, glXattr);
    if( !glX_window_handle ) {
        fatalError("Couldn't create the GLX window\n");
    }
#else
    glX_window_handle = window_handle;
#endif

    textprop.value = (unsigned char*)title;
    textprop.encoding = XA_STRING;
    textprop.format = 8;
    textprop.nitems = strlen(title);

    hints.x = x;
    hints.y = y;
    hints.width = width;
    hints.height = height;
    hints.flags = USPosition|USSize;

    startup_state = XAllocWMHints();
    startup_state->initial_state = NormalState;
    startup_state->flags = StateHint;

    XSetWMProperties(Xdisplay, window_handle,&textprop, &textprop,
            NULL, 0,
            &hints,
            startup_state,
            NULL);

    XFree(startup_state);

    XMapWindow(Xdisplay, window_handle);
    XIfEvent(Xdisplay, &event, WaitForMapNotify, (char*)&window_handle);

    if ((del_atom = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", 0)) != None) {
        XSetWMProtocols(Xdisplay, window_handle, &del_atom, 1);
    }
}

static int ctxErrorHandler( Display *dpy, XErrorEvent *ev )
{
    fputs("Error at context creation", stderr);
    return 0;
}

static void createTheRenderContext()
{
    int dummy;
    if (!glXQueryExtension(Xdisplay, &dummy, &dummy)) {
        fatalError("OpenGL not supported by X server\n");
    }

#if USE_GLX_CREATE_CONTEXT_ATTRIB
    #define GLX_CONTEXT_MAJOR_VERSION_ARB       0x2091
    #define GLX_CONTEXT_MINOR_VERSION_ARB       0x2092
    render_context = NULL;
    if( isExtensionSupported( glXQueryExtensionsString(Xdisplay, DefaultScreen(Xdisplay)), "GLX_ARB_create_context" ) ) {
        typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
        glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
        if( glXCreateContextAttribsARB ) {
            int context_attribs[] =
            {
                GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
                GLX_CONTEXT_MINOR_VERSION_ARB, 0,
                //GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
                None
            };

            int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
            
            render_context = glXCreateContextAttribsARB( Xdisplay, fbconfig, 0, True, context_attribs );

            XSync( Xdisplay, False );
            XSetErrorHandler( oldHandler );

            fputs("glXCreateContextAttribsARB failed", stderr);
        } else {
            fputs("glXCreateContextAttribsARB could not be retrieved", stderr);
        }
    } else {
            fputs("glXCreateContextAttribsARB not supported", stderr);
    }

    if(!render_context)
    {
#else
    {
#endif
        render_context = glXCreateNewContext(Xdisplay, fbconfig, GLX_RGBA_TYPE, 0, True);
        if (!render_context) {
            fatalError("Failed to create a GL context\n");
        }
    }

    if (!glXMakeContextCurrent(Xdisplay, glX_window_handle, glX_window_handle, render_context)) {
        fatalError("glXMakeCurrent failed for window\n");
    }
}

static int updateTheMessageQueue()
{
    XEvent event;
    XConfigureEvent *xc;

    while (XPending(Xdisplay))
    {
        XNextEvent(Xdisplay, &event);
        switch (event.type)
        {
        case ClientMessage:
            if (event.xclient.data.l[0] == del_atom)
            {
                return 0;
            }
        break;

        case ConfigureNotify:
            xc = &(event.xconfigure);
            width = xc->width;
            height = xc->height;
            break;
        }
    }
    return 1;
}

/*  6----7
   /|   /|
  3----2 |
  | 5--|-4
  |/   |/
  0----1

*/

GLfloat cube_vertices[][8] =  {
    /*  X     Y     Z   Nx   Ny   Nz    S    T */
    {-1.0, -1.0,  1.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 0
    { 1.0, -1.0,  1.0, 0.0, 0.0, 1.0, 1.0, 0.0}, // 1
    { 1.0,  1.0,  1.0, 0.0, 0.0, 1.0, 1.0, 1.0}, // 2
    {-1.0,  1.0,  1.0, 0.0, 0.0, 1.0, 0.0, 1.0}, // 3

    { 1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0}, // 4
    {-1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0}, // 5
    {-1.0,  1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 1.0}, // 6
    { 1.0,  1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 1.0}, // 7

    {-1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0}, // 5
    {-1.0, -1.0,  1.0, -1.0, 0.0, 0.0, 1.0, 0.0}, // 0
    {-1.0,  1.0,  1.0, -1.0, 0.0, 0.0, 1.0, 1.0}, // 3
    {-1.0,  1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0}, // 6
    
    { 1.0, -1.0,  1.0,  1.0, 0.0, 0.0, 0.0, 0.0}, // 1
    { 1.0, -1.0, -1.0,  1.0, 0.0, 0.0, 1.0, 0.0}, // 4
    { 1.0,  1.0, -1.0,  1.0, 0.0, 0.0, 1.0, 1.0}, // 7
    { 1.0,  1.0,  1.0,  1.0, 0.0, 0.0, 0.0, 1.0}, // 2
    
    {-1.0, -1.0, -1.0,  0.0, -1.0, 0.0, 0.0, 0.0}, // 5
    { 1.0, -1.0, -1.0,  0.0, -1.0, 0.0, 1.0, 0.0}, // 4
    { 1.0, -1.0,  1.0,  0.0, -1.0, 0.0, 1.0, 1.0}, // 1
    {-1.0, -1.0,  1.0,  0.0, -1.0, 0.0, 0.0, 1.0}, // 0

    {-1.0, 1.0,  1.0,  0.0,  1.0, 0.0, 0.0, 0.0}, // 3
    { 1.0, 1.0,  1.0,  0.0,  1.0, 0.0, 1.0, 0.0}, // 2
    { 1.0, 1.0, -1.0,  0.0,  1.0, 0.0, 1.0, 1.0}, // 7
    {-1.0, 1.0, -1.0,  0.0,  1.0, 0.0, 0.0, 1.0}, // 6
};

static void draw_cube(void)
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(3, GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][0]);
    glNormalPointer(GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][3]);
    glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][6]);

    glDrawArrays(GL_QUADS, 0, 24);
}

float const light0_dir[]={0,1,0,0};
float const light0_color[]={78./255., 80./255., 184./255.,1};

float const light1_dir[]={-1,1,1,0};
float const light1_color[]={255./255., 220./255., 97./255.,1};

float const light2_dir[]={0,-1,0,0};
float const light2_color[]={31./255., 75./255., 16./255.,1};

static void redrawTheWindow()
{
    float const aspect = (float)width / (float)height;

    static float a=0;
    static float b=0;
    static float c=0;

    glDrawBuffer(GL_BACK);

    glViewport(0, 0, width, height);

    // Clear with alpha = 0.0, i.e. full transparency
        glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-aspect, aspect, -1, 1, 2.5, 10);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

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

    glLightfv(GL_LIGHT0, GL_POSITION, light0_dir);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_color);

    glLightfv(GL_LIGHT1, GL_POSITION, light1_dir);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_color);

    glLightfv(GL_LIGHT2, GL_POSITION, light2_dir);
    glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_color);

    glTranslatef(0., 0., -5.);

    glRotatef(a, 1, 0, 0);
    glRotatef(b, 0, 1, 0);
    glRotatef(c, 0, 0, 1);

    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);
    glEnable(GL_LIGHTING);

    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);

    glColor4f(1., 1., 1., 0.5);

    glCullFace(GL_FRONT);
    draw_cube();
    glCullFace(GL_BACK);
    draw_cube();

    a = fmod(a+0.1, 360.);
    b = fmod(b+0.5, 360.);
    c = fmod(c+0.25, 360.);

    glXSwapBuffers(Xdisplay, glX_window_handle);
}

int main(int argc, char *argv[])
{
    createTheWindow();
    createTheRenderContext();

    while (updateTheMessageQueue()) {
        redrawTheWindow();
    }

    return 0;
}
#include <gtk/gtk.h>
#include <gdk/gdkscreen.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtkgl.h>
#include <GL/gl.h>
#include <GL/glu.h>

static gboolean supports_alpha = FALSE;

/***
 *** Configure the OpenGL framebuffer.
***/
static GdkGLConfig* configure_gl(void)
{
    GdkGLConfig* glconfig;

    /* Try double-buffered visual */
    glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGBA |
        GDK_GL_MODE_ALPHA |
        GDK_GL_MODE_DEPTH |
        GDK_GL_MODE_DOUBLE);
    if (glconfig == NULL)
    {
        printf("Cannot find the double-buffered visual.\n");
        printf("No appropriate OpenGL-capable visual found.\n");
        exit(1);
    }
    printf("Find GLConfig with alpha channel.\n");
    return glconfig;
}

static void screen_changed(GtkWidget* widget, GdkScreen* old_screen, gpointer userdata)
{
    /* To check if the display supports alpha channels, get the colormap */
    GdkScreen* screen = gtk_widget_get_screen(widget);
    GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);

    if (!colormap)
    {
        printf("Your screen does not support alpha channels!\n");
        colormap = gdk_screen_get_rgb_colormap(screen);
        supports_alpha = FALSE;
    }
    else
    {
        printf("Your screen supports alpha channels!\n");
        supports_alpha = TRUE;
    }

    gtk_widget_set_colormap(widget, colormap);
}

static gboolean expose(GtkWidget* widget, GdkEventExpose* event, gpointer userdata)
{
    GdkGLContext* glcontext = gtk_widget_get_gl_context(widget);
    GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(widget);

    if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
    {
        return FALSE;
    }

    glDrawBuffer(GL_BACK);

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glBegin(GL_QUADS);
    glColor4f(1.0f, 0.0f, 0.0f, 0.3f);
    glVertex3f(-0.5f, -0.5f, 0);
    glVertex3f(+0.5f, -0.5f, 0);
    glVertex3f(+0.5f, +0.5f, 0);
    glVertex3f(-0.5f, +0.5f, 0);
    glEnd();

    gdk_gl_drawable_swap_buffers(gldrawable);

    gdk_gl_drawable_gl_end(gldrawable);
    return TRUE;
}

int main(int argc, char** argv)
{
    gtk_init(&argc, &argv);

    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    /* Added to config GLConfig */
    GdkGLConfig* glconfig = configure_gl();
    gtk_widget_set_gl_capability(window,
        glconfig,
        NULL,
        TRUE,
        GDK_GL_RGBA_TYPE);

    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
    gtk_window_set_title(GTK_WINDOW(window), "Alpha Demo");
    g_signal_connect(G_OBJECT(window), "delete-event", gtk_main_quit, NULL);

    gtk_widget_set_app_paintable(window, TRUE);

    g_signal_connect(G_OBJECT(window), "expose-event", G_CALLBACK(expose), NULL);
    g_signal_connect(G_OBJECT(window), "screen-changed", G_CALLBACK(screen_changed), NULL);

    screen_changed(window, NULL, NULL);

    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}