=================================
=================================
=================================
OpenGL을 쓰고 항시 API를 쓰고 다시 해제해주어야 하는 API들은 는 해제 해주는것을 잊지 마세요
예로들어 wglMakeCurrent(...)로 들자면
HDC hdc = getHDC();
HGLRC hglrc = getHGLRCRES_GL();
::wglMakeCurrent(hdc, hglrc); //사용
//------------------------------------------//{랜더링 코드들..................................................................//}//------------------------------------------::wglMakeCurrent(NULL, NULL); //::wglMakeCurrent(hdc, NULL); //해제
위와같이 wglMakeCurrent(...) 랜더링 부분에 Api 사용과 해제 부분을 제대로 하지 않으면 다른
위치의 wglMakeCurrent(...) 를 사용시 문제가 생길수 있습니다.
=================================
=================================
=================================
How to make an OpenGL rendering context with transparent background?
Rendering contexts usually have a solid color on the background (black or whatever, see the image below):
I'm wondering if it's possible to setup a window, with no decorations AND with the transparent background, while allowing me to render OpenGL stuff on it.
This would give the illusion that the triangle is floating on the screen. The transparent background should allow you to see the desktop or other applications that might be behind it.
Could you please exemplify with source code?
Platform: Windows (win32 only)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
After spending some reputation on a unsuccessful bounty to get some help on this issue, I finally realized how complex was the problem I was interested in.
The few individuals that have accomplished this task don't share much. During my research I found different ways to achieve what I was looking for. One of the most interesting ones is AeroGL, and it shows snippets of code using a technique that was not mentioned so far, which is rendering the graphics to a device-independent bitmap (DIB).
To close this thread permanently, the source code below implements that technique. The code itself is a slight modification of an application presented here (big thanks to Andrei Sapronov Y.).
The end result can be seen in the image below:
The code has been tested on Windows XP (32-bits) and Windows 8.1 (32-bits). Enjoy!
#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); }
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
It's worth saying that this technique is not practical for complex rendering and graphics animations. Copying GPU data to the RAM for each frame is very demanding on the CPU, resulting in low FPS. Check the comments on this answer: stackoverflow.com/questions/4780756/… – karlphillip Feb 8 '11 at 16:57
|
|||
|
Note that in Windows Vista and Windows 7 you can achieve quite the same effect as in my x11argb demo below. The PIXELFORMATDESCRIPTOR supports a new flag to enable composition. I've yet to create a demo for this, though. Not going to happen until April, though, when I've got time for that again. – datenwolf
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
I know this is possible with Windows 7, not sure about earlier versions.
To get rid of the window border you need to remove the WS_OVERLAPPEDWINDOW
style from the window and add the WS_POPUP
style:
DWORD style = ::GetWindowLong(hWnd, GWL_STYLE); style &= ~WS_OVERLAPPEDWINDOW; style |= WS_POPUP; ::SetWindowLong(hWnd, GWL_STYLE, style);
To make the background of the OpenGL window transparent, you will need to use the DwmEnableBlurBehindWindow
function:
DWM_BLURBEHIND bb = {0}; bb.dwFlags = DWM_BB_ENABLE; bb.fEnable = true; bb.hRgnBlur = NULL; DwmEnableBlurBehindWindow(hWnd, &bb);
You will also need to specify 0 for the alpha value when calling glClearColor
.
glClearColor(0.0f,0.0f,0.0f,0.0f);
Also, when creating your OpenGL context, make sure you allocate an alpha channel.
Now your background should be fully transparent. If you keep the window decorations, then the background will use the Aero blur look and you can adjust the level of transparency using the alpha value in glClearColor
.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Thank you, but DwmEnableBlurBehindWindow() is a part of DWM, which doesn't belong to the Win32 API. This solution works for Windows Vista and above. – karlphillip Nov 1 '10 at 16:09
|
|||
|
@karlphilip: Pre-Vista Windows:es don't have desktop compositing, so I'm not sure you can do it nicely there.– Macke Nov 1 '10 at 16:15
|
||
|
@karlphilip. Sorry, I haven't personally gotten transparent OpenGL windows working with XP, but I remember seeing posts on the OpenGL forum about it. Trying looking through the following search results for more information: google.com/… – flashk Nov 1 '10 at 16:20
|
||
|
This was really helpful, but I want to add the following: For me the above method rendered all of the background with the default Win7 blur and fake light reflections. To get rid of the blur and get a completeley transparent window, I set the
bb.hRgnBlur parameter to CreateRectRgn(0, 0, 1, 1); and bb.dwFlags to DWM_BB_ENABLE | DWM_BB_BLURREGION; . This will blur exactly one pixel and show the rest of the window (where cleared with glClear) as completely transparent. – pholz |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Since all the answers given so far target Windows only, but there's surely also a demand doing this on X11 with a composited window manager, for reference I post my example code here (also to be found at https://github.com/datenwolf/codesamples/blob/master/samples/OpenGL/x11argb_opengl/x11argb_opengl.c
/*------------------------------------------------------------------------ * 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); 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; }
The main trick is getting the right FBConfig. You need to ask for a alpha channel and test the associated XRenderPictFormat
for the presence of an alpha mask.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This is an old question, but since newer versions of Windows have compositing and support, as datenwolf hints, for opengl, we can use some of that special sauce for accomplishing this. Although it is also trivial with DirectX (go figure...) Microsoft did add compositing hints to opengl contexts. Yay anti-trust fears!
So instead of an inefficient copy-to-physical-memory action, we can have the compositing engine just understand how to make use of the opengl context.
So, you have to create an opengl context with a pixelformat that specifies an alpha channel and that it should use composition (line 82). Then, you use the DwmApi.h routines to enable a blurred window (line 179) with a completely invalid region specified, which will blur nothing and leave the window transparent. (You need to specify a black+transparent brush on the window class! Oddly!) Then, you actually just use opengl as you are used to using it. In the event loop, every chance you get, you can just draw and swap buffers (line 201) and remember to enable GL_BLEND! :)
Please review/fork https://gist.github.com/3644466 or just view the following code snippet based off of the OP's own answer with this technique instead (you can just plop this in an empty project):
#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); }
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
=================================
=================================
=================================
출처: http://hyena0.tistory.com/420
mRenderer = new CubeRenderer(true);
mGLSurfaceView = new GLSurfaceView(this);
//translucent
mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);
mGLSurfaceView.setRenderer(mRenderer);
translucent 부분이 투명처리하는 부분인데, 카메라부분인 preview 객체를 생성하지 않으면 바탕화면 위에
도형이 그려지는 것을 볼 수 있어야 합니다. 확인하려면, preview 객체 생성부분을 주석처리해서 확인해 보십시오.
만약 거기서도 바탕화면이 투명처리가 안된다면, 다음을 확인해 보시기 바랍니다. (AndroidManifest.xml, 적색코드)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.XXXXX"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".XXXXX"
android:label="@string/app_name"
android:theme="@android:style/Theme.Translucent">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>
한번 해보시고 결과를 댓글로 남겨주세요.
=================================
=================================
=================================
출처: http://liveupdate.tistory.com/109
GLSurfaceView 배경 투명하게 만들기
관련소스 : APIDemos/src/com.example.android.apis.graphics/TranslucentGLSurfaceViewActivity.java
GLSurfaceView는 기본 값이 알파채널이 적용되지 않아서,
glClearColor( 0,0,0,0 ); 으로 해도 투명값이 설정되지 않는다.
EGL을 통해 SurfaceView를 핸들링하므로, 뷰 생성후 EGL, SurfaceView관련 설정만 하면 알파값을 사용할 수 있다.
GLSurfaceView myView = new GLSurfaceView(this);
// 픽셀포맷을 32비트포맷(8,8,8,8)으로 변경한다.
myView.setEGLConfigChooser( 8, 8, 8, 8, 16, 0);
// 렌더러 설정
myView.setRenderer( new MyRenderer() );
// 서비스포맷을 설정한다.
myView.getHolder().setFormat( PixelFormat.TRANSLUCENT );
이처럼 간단히 픽셀포맷만 변경하면된다.
이후 렌더러에서 glClearColor( 0, 0,0,0 ); 하면 배경은 투명으로 처리됨을 확인할 수 있다.
출처: http://liveupdate.tistory.com/109 [Live Update]
=================================
=================================
=================================
출처: http://hyena0.tistory.com/421
// The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder*)coder {
if ((self = [super initWithCoder:coder])) {
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = NO;//no - transparent
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
return nil;
}
animating = FALSE;
displayLinkSupported = FALSE;
animationFrameInterval = 1;
displayLink = nil;
animationTimer = nil;
// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
displayLinkSupported = TRUE;
[self setupView];
}
return self;
}
해당 코드는 일반적으로 제공되는 OpenGL 코드인데, eaglLayer.opaque = NO 로 설정해야 투명한 배경을
얻을 수 있습니다. 또한 도형을 그리는 부분에서는 배경화면의 색깔을 투명으로 지정해야 합니다.
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
여기서 glClear(Red, Green, Blue, alpha) 값을 보시면 모두 0 으로 설정하면 됩니다.
그런데 이렇게 하고서 투명처리가 안되어 무지 고생을 했습니다.
알고 봤더니 인터페이스 빌더에서 해당 OpenGL 을 그리는 View 의 배경색이 흰색으로 설정되어 있었습니다.
그래서 위와 같이 View 를 선택한 뒤, 배경색 팔레트에서 Opacity 값을 0 으로 설정하면
View 자체가 투명한 색을 가지게 됩니다.
그러면 아래와 같은 투명배경의 도형을 카메라와 같이 볼 수 있게 됩니다.
=================================
=================================
=================================
출처: https://stackoverflow.com/questions/34387682/win32-api-transparent-opengl-overlay-clickthrough
win32 api transparent opengl overlay Clickthrough
i try to create a transparent window with opengl rendering insite. but because it is "WS_EX_TOPMOST" it will catch all mouse input how can i tell windows to ignore my window and send all inputs to the next Window in Z-order below my window.
Stuff i already tried:
- WS_EX_LAYERED will break my opengl Rendering
- offscreen rendring in a buffer its pretty slow because i have to use BitBlt(Sometimes i will get a software Opgengl Context)
- WM_NCHITTEST returning HTNOWHEREif (!RegisterClassEx(&wc)) error();
m_OverlayWindow = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE, L"TESTA", L"hello", WS_VISIBLE | WS_POPUP, 0, 0, m_DesktopRect.right, m_DesktopRect.bottom, NULL, NULL, NULL, NULL); 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(m_OverlayWindow, &bb); g_OverlayWindow = m_OverlayWindow; EnableWindow(m_OverlayWindow, FALSE); PIXELFORMATDESCRIPTOR pfd1 = { sizeof(PIXELFORMATDESCRIPTOR), 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_SUPPORT_COMPOSITION | PFD_DOUBLEBUFFER, // Format Must Support Composition PFD_TYPE_RGBA, // Request An RGBA Format 32, // Select Our Color Depth 0, 0, 0, 0, 0, 0,................... m_hDC = GetDC(m_OverlayWindow); int nPixelFormat = ChoosePixelFormat(m_hDC, &pfd1); SetPixelFormat(m_hDC, nPixelFormat, &pfd1); m_OpenGlContext = wglCreateContext(m_hDC); wglMakeCurrent(m_hDC, m_OpenGlContext); const GLubyte *GLVersionString = glGetString(GL_VERSION); glEnable(GL_ALPHA_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor(0, 0, 0, 0);
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 = NULL; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = NULL;//LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)CreateSolidBrush(0x00000000); wc.lpszClassName = L"TESTA";
=================================
=================================
=================================
출처: https://www.codeproject.com/Articles/9064/Yet-Another-Transparent-Static-Control
Introduction
There are many ways to develop a transparent static control. I like two approaches in particular, because they are simple and they get the job done. When you think about placing a static control with a transparent background on your window, the one important thing you have to consider is, whether the background is static or dynamic. The problem of having a static control changes depending on what is displayed in the background.
Method 1
If the background is static, then the best approach is to make a copy of the area on the parent window behind the static control before it is drawn for the first time, and then simply copy the image back to the parent every time the static control needs to be redrawn. The advantage of this approach is its flicker free display every time the static control is changed.
LRESULT CTransparentStatic2::OnSetText(WPARAM wParam,LPARAM lParam) { LRESULT Result = Default(); Invalidate(); UpdateWindow(); return Result; } HBRUSH CTransparentStatic2::CtlColor(CDC* pDC, UINT /*nCtlColor*/) { pDC->SetBkMode(TRANSPARENT); return (HBRUSH)GetStockObject(NULL_BRUSH); } BOOL CTransparentStatic2::OnEraseBkgnd(CDC* pDC) { if (m_Bmp.GetSafeHandle() == NULL) { CRect Rect; GetWindowRect(&Rect); CWnd *pParent = GetParent(); ASSERT(pParent); pParent->ScreenToClient(&Rect); //convert our corrdinates to our parents //copy what's on the parents at this point CDC *pDC = pParent->GetDC(); CDC MemDC; MemDC.CreateCompatibleDC(pDC); m_Bmp.CreateCompatibleBitmap(pDC,Rect.Width(),Rect.Height()); CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp); MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),pDC,Rect.left,Rect.top,SRCCOPY); MemDC.SelectObject(pOldBmp); pParent->ReleaseDC(pDC); } else //copy what we copied off the parent the first time back onto the parent { CRect Rect; GetClientRect(Rect); CDC MemDC; MemDC.CreateCompatibleDC(pDC); CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp); pDC->BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY); MemDC.SelectObject(pOldBmp); } return TRUE; }
Method 2
The other approach comes in handy when the parent window's background is dynamic. If the parent window's background is constantly changing then the above approach will not look too nice. So instead of all the copying, what the static control should do is invalidate the area of the parent where the control resides every time its text is changed. This method is much simpler than the one before, but it could flicker if the text is changed at a rapid rate.
LRESULT CTransparentStatic::OnSetText(WPARAM wParam,LPARAM lParam) { LRESULT Result = Default(); CRect Rect; GetWindowRect(&Rect); GetParent()->ScreenToClient(&Rect); GetParent()->InvalidateRect(&Rect); GetParent()->UpdateWindow(); return Result; } HBRUSH CTransparentStatic::CtlColor(CDC* pDC, UINT /*nCtlColor*/) { pDC->SetBkMode(TRANSPARENT); return (HBRUSH)GetStockObject(NULL_BRUSH); }
Keep an eye out for a Transparent Edit control and Transparent Listbox.
=================================
=================================
=================================
'프로그래밍 관련 > 3D,2D DRAW 관련' 카테고리의 다른 글
OpenGL 블렌딩 (0) | 2017.08.18 |
---|---|
OpenGL FBO (FrameBuffer Object) 사용하기 (0) | 2017.08.18 |
3D구현 - 2D 물체 겹침 표현하기 관련 (0) | 2017.07.12 |
OpenGL 스텐실 테스트, 그림판 지우기 Painter Eraser 구현 관련 (0) | 2017.07.12 |
OpenGL 을 window DC 에 따로 렌더링 하기 다른부분에 랜더링 관련 (0) | 2017.06.20 |