有没有办法用 X11 获得透明的 OpenGL ES 背景?

发布于 2024-11-30 02:45:45 字数 102 浏览 1 评论 0原文

我可以找到适用于 iPhone/Windows 的问题/答案,但找不到适用于 X11 的问题/答案。
另外,是否有具有丰富 OpenGL 经验的人可以解释任何窗口系统涉及的一般概念?

I can find questions/answers for iPhone/Windows but none for X11.

Also if there is anyone with a ton of OpenGL experience who can explain the general concepts involved for any windowing system?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

生生漫 2024-12-07 02:45:45

是的,这是可能的。我修改了 fungus 编写的示例程序来创建 RGBA OpenGL 窗口。如果启用了合成器,结果将类似于我在此处发布的视频:http://www.youtube .com/watch?v=iHZfH1Qhonk

/*------------------------------------------------------------------------
  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

------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glx.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>

typedef struct
{
    Visual *visual;
    VisualID visualid;
    int screen;
    unsigned int depth;
    int klass;
    unsigned long red_mask;
    unsigned long green_mask;
    unsigned long blue_mask;
    int colormap_size;
    int bits_per_rgb;
} XVisualInfo_CPP;

/*------------------------------------------------------------------------
  Something went horribly wrong
------------------------------------------------------------------------*/\
static void fatalError(const char *why)
{
    fprintf(stderr, "%s", why);
    exit(0x666);
}

/*------------------------------------------------------------------------
  Global vars
------------------------------------------------------------------------*/
static int Xscreen;
static Atom del_atom;
static Colormap cmap;
static Display *Xdisplay;
static XVisualInfo_CPP *visual;
static XRenderPictFormat *pictFormat;
static GLXFBConfig *fbconfigs, fbconfig;
static int numfbconfigs;
static GLXContext RenderContext;
static Window Xroot, WindowHandle, GLXWindowHandle;
static int width, height;   /* Size of the window */

int const tex_width=512;
int const tex_height=512;
static GLuint texture;

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
};
/*------------------------------------------------------------------------
  Create a window
------------------------------------------------------------------------*/
static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
{
    return (e->type == MapNotify) && (e->xmap.window == *(Window*)arg);
}

static void createTheWindow()
{
    XEvent event;
    int x,y, attr_mask;
    XSizeHints hints;
    XWMHints *StartupState;
    XTextProperty textprop;
    XSetWindowAttributes attr;
    static char *title = "FTB's little OpenGL example";

    /* 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 */

    /* Create the window */
    width = DisplayWidth(Xdisplay, DefaultScreen(Xdisplay))/2;
    height = DisplayHeight(Xdisplay, DefaultScreen(Xdisplay))/2;
    x=width/2, y=height/2;

    /* Create the window */
    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 */
    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);
    }
}
/*------------------------------------------------------------------------
  Create the OpenGL rendering context
------------------------------------------------------------------------*/
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");
    }

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
/*------------------------------------------------------------------------
  Window messages
------------------------------------------------------------------------*/
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;
}


/*------------------------------------------------------------------------
  Redraw the window
------------------------------------------------------------------------*/
float const light_dir[]={1,1,1,0};
float const light_color[]={1,0.95,0.9,1};

static void redrawTheWindow()
{
    int size;
    static float a=0;
    static float b=0;
    static float c=0;

    glViewport(0,0,width,height);

    /* Clear the screen */
    // glClearColor(0.750,0.750,1.0,0.5);
    glClearColor(0.0,0.0,0.0,0.);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, (float)width/(float)height, 1, 10);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();


    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    glLightfv(GL_LIGHT0, GL_POSITION, light_dir);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_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_LIGHTING);
    glutSolidTeapot(1);

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

    /* Swapbuffers */
    glXSwapBuffers(Xdisplay, GLXWindowHandle);
}

/*------------------------------------------------------------------------
  Program entry point
------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
    /* instead of a triangle I wanted a teapot. GLUT has it. 
       GLUT is NOT used for window creation, but just the teapot
       primitive. Nevertheless it must be initialized */
    glutInit(&argc, argv);

    createTheWindow();
    createTheRenderContext();

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

    return 0;
}

Yes it is possible. I modified a example program written by fungus to create a RGBA OpenGL window. If a compositor is enabled the results look like in the video I posted here: http://www.youtube.com/watch?v=iHZfH1Qhonk

/*------------------------------------------------------------------------
  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

------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glx.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>

typedef struct
{
    Visual *visual;
    VisualID visualid;
    int screen;
    unsigned int depth;
    int klass;
    unsigned long red_mask;
    unsigned long green_mask;
    unsigned long blue_mask;
    int colormap_size;
    int bits_per_rgb;
} XVisualInfo_CPP;

/*------------------------------------------------------------------------
  Something went horribly wrong
------------------------------------------------------------------------*/\
static void fatalError(const char *why)
{
    fprintf(stderr, "%s", why);
    exit(0x666);
}

/*------------------------------------------------------------------------
  Global vars
------------------------------------------------------------------------*/
static int Xscreen;
static Atom del_atom;
static Colormap cmap;
static Display *Xdisplay;
static XVisualInfo_CPP *visual;
static XRenderPictFormat *pictFormat;
static GLXFBConfig *fbconfigs, fbconfig;
static int numfbconfigs;
static GLXContext RenderContext;
static Window Xroot, WindowHandle, GLXWindowHandle;
static int width, height;   /* Size of the window */

int const tex_width=512;
int const tex_height=512;
static GLuint texture;

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
};
/*------------------------------------------------------------------------
  Create a window
------------------------------------------------------------------------*/
static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
{
    return (e->type == MapNotify) && (e->xmap.window == *(Window*)arg);
}

static void createTheWindow()
{
    XEvent event;
    int x,y, attr_mask;
    XSizeHints hints;
    XWMHints *StartupState;
    XTextProperty textprop;
    XSetWindowAttributes attr;
    static char *title = "FTB's little OpenGL example";

    /* 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 */

    /* Create the window */
    width = DisplayWidth(Xdisplay, DefaultScreen(Xdisplay))/2;
    height = DisplayHeight(Xdisplay, DefaultScreen(Xdisplay))/2;
    x=width/2, y=height/2;

    /* Create the window */
    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 */
    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);
    }
}
/*------------------------------------------------------------------------
  Create the OpenGL rendering context
------------------------------------------------------------------------*/
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");
    }

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
/*------------------------------------------------------------------------
  Window messages
------------------------------------------------------------------------*/
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;
}


/*------------------------------------------------------------------------
  Redraw the window
------------------------------------------------------------------------*/
float const light_dir[]={1,1,1,0};
float const light_color[]={1,0.95,0.9,1};

static void redrawTheWindow()
{
    int size;
    static float a=0;
    static float b=0;
    static float c=0;

    glViewport(0,0,width,height);

    /* Clear the screen */
    // glClearColor(0.750,0.750,1.0,0.5);
    glClearColor(0.0,0.0,0.0,0.);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, (float)width/(float)height, 1, 10);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();


    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    glLightfv(GL_LIGHT0, GL_POSITION, light_dir);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_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_LIGHTING);
    glutSolidTeapot(1);

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

    /* Swapbuffers */
    glXSwapBuffers(Xdisplay, GLXWindowHandle);
}

/*------------------------------------------------------------------------
  Program entry point
------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
    /* instead of a triangle I wanted a teapot. GLUT has it. 
       GLUT is NOT used for window creation, but just the teapot
       primitive. Nevertheless it must be initialized */
    glutInit(&argc, argv);

    createTheWindow();
    createTheRenderContext();

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

    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文