Čiastočne priehľadné okno OpenGL / Win32 - c ++, winapi, opengl

Prečítal som si každú existujúcu otázku o tejto zložitej (výklenenej) téme, ale som uviazol. Mám okno Win32 s kontextom OpenGL. Chcem, aby moje okno bolo čiastočne transparentné.

Doteraz môj výsledok je ten, že celýokno je priehľadné. Chcem, aby len čierna oblasť bola transparentná, aby som mohol nakresliť nejaké 3D objekty a budú vyzerať, ako by prišli z okna.

tu zadajte popis obrázku

Po prvé, v mojej triede okien som nastavil hbrBackground na čierne.

Windows::WindowClass windowClass;
windowClass.cbSize = sizeof(Windows::WindowClass);
windowClass.style = Windows::CS_VREDRAW | Windows::CS_HREDRAW;
windowClass.lpfnWndProc = WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = moduleHandle;
windowClass.hIcon = Windows::LoadIcon(0u, (X*)Windows::IDI_QUESTION);
windowClass.hCursor = Windows::LoadCursor(0u, (X*)Windows::IDC_ARROW);
windowClass.hbrBackground = Windows::CreateSolidBrush(0x00000000);
windowClass.lpszMenuName = nullptr;
windowClass.lpszClassName = (X*)name;
windowClass.hIconSm = Windows::LoadIcon(0u, (X*)Windows::IDI_QUESTION);

Vytvoril som okno s príznakom WS_EX_LAYERED.

windowHandle = Windows::CreateWindow(Windows::WS_EX_LAYERED, (X*)name, "", Windows::WS_POPUP, w / 4, h / 4, w / 2, h / 2, 0u, 0u, moduleHandle, 0u);

V mojom pixelovom formáte som aktivoval alfa a zloženie.

PixelFormatDescriptor format;
format.nSize = sizeof(PixelFormatDescriptor);
format.nVersion = 1;
format.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | PFD_SUPPORT_COMPOSITION;
format.iPixelType = PFD_TYPE_RGBA;
format.cColorBits = 32;
format.cRedBits = 0;
format.cRedShift = 0;
format.cGreenBits = 0;
format.cGreenShift = 0;
format.cBlueBits = 0;
format.cBlueShift = 0;
format.cAlphaBits = 8;
format.cAlphaShift = 0;
format.cAccumBits = 0;
format.cAccumRedBits = 0;
format.cAccumGreenBits = 0;
format.cAccumBlueBits = 0;
format.cAccumAlphaBits = 0;
format.cDepthBits = 24;
format.cStencilBits = 8;
format.cAuxBuffers = 0;
format.iLayerType = PFD_MAIN_PLANE;
format.bReserved = 0;
format.dwLayerMask = 0;
format.dwVisibleMask = 0;
format.dwDamageMask = 0;

Skúšal som rozmazanú oblasť "trik", ale nemá žiadny vplyv. Môj výsledok sa netýka tohto kódu.

struct DwmBlurBehind
{
U4 dwFlags;
S4 fEnable;
X* blurRegionHandle;
S4 fTransitionOnMaximized;
};

DwmBlurBehind blurBehind;
blurBehind.dwFlags = Windows::DWM_BB_ENABLE | Windows::DWM_BB_BLURREGION;
blurBehind.fEnable = true;
blurBehind.blurRegionHandle = Windows::CreateRectRgn(0, 0, -1, -1);
blurBehind.fTransitionOnMaximized = false;
Windows::DwmEnableBlurBehindWindow(windowHandle, &blurBehind);

Nakoniec som nastavil LWA_COLORKEY aAtribúty LWA_ALPHA. Toto mi dalo zobrazený efekt. Farebný kľúč sa však nezdá byť braný do úvahy (skúšal som aj nenulové hodnoty).

Windows::SetLayeredWindowAttributes(windowHandle, 0, 170, Windows::LWA_COLORKEY | Windows::LWA_ALPHA);

Nezabudol som povoliť miešanie.

GL::Enable(GL::BLEND);
GL::BlendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA);

odpovede:

1 pre odpoveď č. 1

To, čo chcete robiť, vyžaduje kompozitovanie okien, ktoré bolo okolo od Windows Vista, takže v podstate každej verzii systému Windows máte na starosti (Windows XP a staršie sú EoL).

Kľúčovými krokmi, ktoré je potrebné urobiť, je umožniť DWM kompozície vnútri okna aktivovaním "Blue Behind Window" a použitím a WM_POPUP okná; ak nepoužívate WM_POPUP v štýle správca okien nakreslí dekorácie a vaše vykresľovanie OpenGL sa bude "hover" nad tým.

        DWM_BLURBEHIND bb = {0};
bb.dwFlags = DWM_BB_ENABLE;
bb.fEnable = TRUE;
bb.hRgnBlur = NULL;
DwmEnableBlurBehindWindow(hWnd, &bb);

MARGINS margins = {-1};
impl_DwmExtendFrameIntoClientArea(hWnd, &margins);

Ďalej musíte vytvoriť kontext OpenGL pomocou novej "atribút" API namiesto použitia výberu deskriptora pixelformátu. Pomocou atribútu API môžete vybrať položku a priehľadný s alfa formát okna.

int attribs[] = {
WGL_DRAW_TO_WINDOW_ARB, TRUE,
WGL_DOUBLE_BUFFER_ARB, TRUE,
WGL_SUPPORT_OPENGL_ARB, TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_TRANSPARENT_ARB, TRUE,
WGL_COLOR_BITS_ARB, 32,
WGL_RED_BITS_ARB, 8,
WGL_GREEN_BITS_ARB, 8,
WGL_BLUE_BITS_ARB, 8,
WGL_ALPHA_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0, 0
};

INT iPF;
UINT num_formats_choosen;
if( !wglChoosePixelFormatARB(
hDC,
attribs,
NULL,
1,
&iPF,
&num_formats_choosen) ) {
fprintf(stderr, "error choosing proper pixel formatn");
return NULL;
}
if( !num_formats_choosen ) {
return NULL;
}

PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
/* now this is a kludge; we need to pass something in the PIXELFORMATDESCRIPTOR
* to SetPixelFormat; it will be ignored, mostly. OTOH we want to send something
* sane, we"re nice people after all - it doesn"t hurt if this fails. */
DescribePixelFormat(hDC, iPF, sizeof(pfd), &pfd);

if( !SetPixelFormat(hDC, iPF, &pfd) ) {
fprintf(stderr, "error setting proper pixel formatn");
ReleaseDC(hWnd, hDC);
DestroyWindow(hWnd);

return NULL;
}

Mám pre mňa úplný pracovný príklad wglarb úložisko obalov na adrese GitHub: https://github.com/datenwolf/wglarb/blob/master/test/layered.c


2 pre odpoveď č. 2

Možno vám chýba hovor UpdateLayeredWindow , IIRC, ktoré nekontaktuje aplikáciu UpdateLayeredWindow, vedie k nejakému divnému správaniu. YMMV.

Viac informácií tu


0 pre odpoveď č. 3

V súlade s SetLayeredWindowAttributes doc musíte prejsť

štruktúra COLORREF, ktorá špecifikujetransparentný farebný kľúč použitý pri zostavovaní vrstveného okna. Všetky pixely namaľované okno v tejto farbe bude transparentné. Ak chcete vygenerovať COLORREF, použite makro RGB.

Pozrite si druhý parameter svojho volania na túto funkciu.


Ponuka