Сделать прозрачность не показывать то, что находится за окном в OpenGL с переполнением стека

Я делаю двухмерное изображение в opengl с C ++, и сталкиваюсь с интересной проблемой. Всякий раз, когда я пытаюсь нарисовать частично прозрачный многоугольник на моем изображении, оно делает само окно частично прозрачным там, где находится многоугольник. Например, я могу видеть все, что находится за моим окном (например, мой код), когда я запускаю программу (что мне не нужно). Я также могу видеть изображение позади многоугольника (который я хочу). Можно ли как-нибудь отключить поведение «прозрачного окна»? Я включил то, что я чувствую, чтобы быть соответствующими частями кода ниже:

glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // I have tried 1.0f for the alpha value too
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
glDisable(GL_POINT_SMOOTH);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

// other code to draw my opaque "background" object

// Draw my partially transparent quad (note: this is where the window itself becomes partially transparent)
glBegin(GL_QUADS); // Begin drawing quads
glColor4f(1.0,1.0,1.0,0.5); // Make a white quad with .5 alpha
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, .05);
glVertex2f(0.5, -0.5);
glVertex2f(-0.5, -0.5);
glEnd();

Другая важная информация:

  • Я использую CentOS 6
  • Я довольно новичок в opengl и работаю над кодом после предыдущего разработчика, так что я мог упустить что-то тривиальное
  • Это использует систему X Windows

Вот код отладки X Window, отлаженный далее, проблема скорее здесь, чем код opengl выше.

/*  The simplest possible Linux OpenGL program? Maybe...
Modification for creating a RGBA window (transparency with compositors)
by Wolfgang 'datenwolf' Draxinger

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

(c) 2011 Wolfgang Draxinger. See me in comp.graphics.api.opengl and on StackOverflow

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.

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

--
datenwolf

------------------------------------------------------------------------*/
static void createTheWindow() {
XEvent event;
int x, y, attr_mask;
XSizeHints hints;
XWMHints *StartupState;
XTextProperty textprop;
XSetWindowAttributes attr;
static char *title = "Fix me";

/* Connect to the X server */
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);
for (int i = 0; i < numfbconfigs; i++)
{
visual = (XVisualInfo_CPP*) glXGetVisualFromFBConfig(Xdisplay,
fbconfigs[i]);
if (!visual)
continue;

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

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

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

/* Prepare the attributes for our window */
attr.colormap = cmap;

attr.border_pixel = 0;
attr.event_mask = StructureNotifyMask | EnterWindowMask | LeaveWindowMask
| ExposureMask | ButtonPressMask | ButtonReleaseMask
| OwnerGrabButtonMask | KeyPressMask | KeyReleaseMask;

attr.background_pixmap = None;

attr_mask = CWBackPixmap | CWColormap | CWBorderPixel | CWEventMask; /* What's in the attr data */

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

/* Create the window */
attr.do_not_propagate_mask = NoEventMask;
WindowHandle = XCreateWindow(Xdisplay, /* Screen */
Xroot, /* Parent */
x, y, width, height,/* Position */
1,/* Border */
visual->depth,/* Color depth*/
InputOutput,/* klass */
visual->visual,/* Visual */
attr_mask, &attr);/* Attributes*/

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

/* Configure it...  (ok, ok, this next bit isn't "minimal") */
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;

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

XSetWMProperties(Xdisplay, WindowHandle, &textprop, &textprop,/* Window title/icon title*/
NULL, 0,/* Argv[], argc for program*/
&hints, /* Start position/size*/
StartupState,/* Iconised/not flag   */
NULL);

XFree(StartupState);

/* Open it, wait for it to appear */
int event_base, error_base = 0;

XMapWindow(Xdisplay, WindowHandle);
//   }

XIfEvent(Xdisplay, &event, WaitForMapNotify, (char*) &WindowHandle);

/* Set the kill atom so we get a message when the user tries to close the window */
if ((del_atom = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", 0)) != None)
{
XSetWMProtocols(Xdisplay, WindowHandle, &del_atom, 1);
}

}

Вот настройки для VisData:

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

Вот где создается контекст рендеринга:

static void createTheRenderContext() {
/* See if we can do OpenGL on this visual */
int dummy;
if (!glXQueryExtension(Xdisplay, &dummy, &dummy))
{
fatalError("OpenGL not supported by X server\n");
}

/* Create the OpenGL rendering context */
RenderContext = glXCreateNewContext(Xdisplay, fbconfig, GLX_RGBA_TYPE, 0,
True);
if (!RenderContext)
{
fatalError("Failed to create a GL context\n");
}

GLXWindowHandle = glXCreateWindow(Xdisplay, fbconfig, WindowHandle, NULL);

/* Make it current */
if (!glXMakeContextCurrent(Xdisplay, GLXWindowHandle, GLXWindowHandle,
RenderContext))
{
fatalError("glXMakeCurrent failed for window\n");
}
}

0

Решение

То, что предлагает фанат с трещоткой (эффект Aero Glass в Windows), не происходит случайно, потому что для этого нужно вручную включить прозрачность DWM.

Однако в X11 / GLX вполне возможно получить визуальный режим с альфа-каналом по умолчанию. Если вы хотите получить действительно окно с альфа-каналом или без него, код становится немного более сложным, чем большинство инструментов.

Код, который вы используете, выглядит поразительно знакомым. Чтобы быть конкретным, это, кажется, происходит из примера кода, который я написал о том, как создать прозрачный окно (вы видите, куда это идет), а именно этот код:

https://github.com/datenwolf/codesamples/blob/master/samples/OpenGL/x11argb_opengl/x11argb_opengl.c

Последовательность ключей такая:

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

Что он делает, он выбирает X11 Visual, который соответствует одному из ранее выбранных FBConfigs, который также содержит альфа-маску.

Если бы мне пришлось сделать ставку, я подозреваю, что VisData массив, который вы передали glXChooseFBConfig не указывает альфа-канал. Так что получается, что вы можете получить окно с альфа-маской X11, но без альфа-канала, доступного для OpenGL.

Так как я никогда не предполагал, что этот код будет использоваться для окон, у которых нет альфа-канала, этот код делает только то, что первоначально предполагалось, если VisData действительно выбирает для альфа-канала.

Теперь у вас есть два варианта:

  • провести дополнительный тест if(pict_format->direct.alphaMask == 0 && no_alpha_in(VisData)) break;

  • выберите альфа-канал в VisData и очистите альфа-канал до 1.0 с помощью OpenGL glClearColor(…,…,…,1.0f);

3

Другие решения

Это не проблема opengl, а окно, которое вы создаете. Я подозреваю, что вы используете оконный менеджер с поддержкой эффектов прозрачности. В любом случае, вероятно, происходит то, что при рендеринге прозрачного поли холст окна заканчивается некоторой альфой, и ваш оконный менеджер предполагает, что вы хотите, чтобы фон был прозрачным. Отключите все расширенные эффекты вашего оконного менеджера, чтобы проверить.

Я не знаком с кодом создания окна с использованием xlib, но, вероятно, это связано с тем типом окна, которое вы создаете.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector