Dennis Kasprzyk napsal:
Am Samstag, 28. April 2007 15:35 schrieb Vasek Potocek:
Hello,

is there any way of utilizing OpenGL's depth test instead of the paint
order? If I understand it well, the aim here is to get it looking _like_
with depth test. I understand that shifting windows by an "infinitesimal"
offset in the z direction would lead to various problems, but isn't is
possible to persuade OpenGL somehow to use different coordinate for the
depth test than for the perspective projection? (It would require a little
bit more math than I outlined here, but should be possible.)

V.
For transparency effects you can't use a depth test, you have to paint the whole screen from back to front.

Dennis

I'm sorry, I really forgot about the problem with transparency x depth test. However, I still think this is soluble: what about using the cubeCheckFTB function for deciding which glBlendFunc to use? Normally we'd need to multiply the color drawn both by SRC_ALPHA and ONE_MINUS_DST_ALPHA, which is not possible well enough, but thanks to compiz' alpha-premultiply demand (fix me if it's not so), we could just choose glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); (as it is done now) when drawing in front of all and glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE); if drawing behind all. No other situation should arise in cube + 3D with BTF (and no other situation would be soluble at all even the original way, however).

I hacked together a little demo showing this, see the attachment and comments 
in it.

One problem I can see is this needs the support for alpha bitplanes, which is not so automatic, could we rely on it in Linux implementations?

V.
/* The base is taken from NeHe (see copyright notice below),
 * for the important part, look for the drawGLScene function.
 *
 * You can pause the animation using space and quit the program by
 * q or Escape. You can also try adjusting the individual colours in the
 * source to test various situations, but keep them alpha-premultiplied.
 */



/*
 * This code was created by Jeff Molofee '99
 * (ported to Linux/GLX by Mihael Vrbanec '00)
 *
 * If you've found this code useful, please let me know.
 *
 * Visit Jeff at http://nehe.gamedev.net/
 *
 * or for port-specific comments, questions, bugreports etc.
 * email to [EMAIL PROTECTED]
 */
 
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <GL/glx.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <X11/keysym.h>

#define Pi 3.14159265358979323846

typedef struct {
  Display *dpy;
  int screen;
  Window win;
  GLXContext ctx;
  XSetWindowAttributes attr;
  int x, y;
  unsigned int width, height;
  unsigned int depth;
} GLWindow;

/* attributes for a single buffered visual in RGBA format with at least
 * 4 bits per color and a 16 bit depth buffer */
static int attrListSgl[] = {
  GLX_RGBA,
  GLX_RED_SIZE, 4,
  GLX_GREEN_SIZE, 4,
  GLX_BLUE_SIZE, 4,
  GLX_ALPHA_SIZE, 4,
  GLX_DEPTH_SIZE, 16,
  None};

/* attributes for a double buffered visual in RGBA format with at least
 * 4 bits per color and a 16 bit depth buffer */
static int attrListDbl[] = {
  GLX_RGBA, GLX_DOUBLEBUFFER,
  GLX_RED_SIZE, 4,
  GLX_GREEN_SIZE, 4,
  GLX_BLUE_SIZE, 4,
  GLX_ALPHA_SIZE, 4,
  GLX_DEPTH_SIZE, 16,
  None };

GLWindow GLWin;

GLfloat z = -5.0;
int stop = 0;

void resizeGLScene(unsigned int width, unsigned int height) {
  if(height==0) height = 1;
  glViewport(0, 0, width, height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
  glMatrixMode(GL_MODELVIEW);
}

int initGL(GLvoid) {
  glShadeModel(GL_SMOOTH);
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  glEnable(GL_BLEND);
  glDisable(GL_DEPTH_TEST);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  /* we use resizeGLScene once to set up our initial perspective */
  resizeGLScene(GLWin.width, GLWin.height);
  glFlush();
  return True;
}

int drawGLScene(GLvoid) {
  static float t = 0, x;
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
  glTranslatef(0.0f, 0.0f, z);

  x = sin(t);
  if(x<0)       /* This is a simple check supplying cubeCheckFTB */
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  else
    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
  glTranslatef(x, 0.0, 0.0);
  glBegin(GL_QUADS);
  glColor4f(0.5, 0.0, 0.0, 0.5);
  glNormal3f(1.0, 0.0, 0.0);
  glVertex3f(0.0, 1.0, 2.0);
  glVertex3f(0.0, 1.0, -1.0);
  glVertex3f(0.0, -1.0, -1.0);
  glVertex3f(0.0, -1.0, 2.0);
  glEnd();

  x += 0.1;
  if(x<0)
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  else
    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
  glTranslatef(0.1, 0.0, 0.0);
  glBegin(GL_QUADS);
  glColor4f(0.9, 0.9, 0.9, 0.9);
  glVertex3f(0.0, 1.0, 2.0);
  glVertex3f(0.0, 1.0, -1.0);
  glVertex3f(0.0, -1.0, -1.0);
  glVertex3f(0.0, -1.0, 2.0);
  glEnd();

  x += 0.1;
  if(x<0)
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  else
    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
  glTranslatef(0.1, 0.0, 0.0);
  glBegin(GL_QUADS);
  glColor4f(0.0, 0.3, 0.0, 0.3);
  glVertex3f(0.0, 1.0, 2.0);
  glVertex3f(0.0, 1.0, -1.0);
  glVertex3f(0.0, -1.0, -1.0);
  glVertex3f(0.0, -1.0, 2.0);
  glEnd();

  x += 0.1;
  if(x<0)
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  else
    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
  glTranslatef(0.1, 0.0, 0.0);
  glBegin(GL_QUADS);
  glColor4f(0.0, 0.0, 0.5, 0.5);
  glVertex3f(0.0, 1.0, 2.0);
  glVertex3f(0.0, 1.0, -1.0);
  glVertex3f(0.0, -1.0, -1.0);
  glVertex3f(0.0, -1.0, 2.0);
  glEnd();

  glXSwapBuffers(GLWin.dpy, GLWin.win);
  if(!stop) t += 0.01;
  return True;
}

GLvoid killGLWindow(GLvoid) {
  if (GLWin.ctx) {
    if (!glXMakeCurrent(GLWin.dpy, None, NULL)) {
      printf("Could not release drawing context.\n");
    }
    glXDestroyContext(GLWin.dpy, GLWin.ctx);
    GLWin.ctx = NULL;
  }
  XCloseDisplay(GLWin.dpy);
}

Bool createGLWindow(char* title, int width, int height) {
  XVisualInfo *vi;
  Colormap cmap;
  Atom wmDelete;
  Window winDummy;
  unsigned int borderDummy;

  /* get a connection */
  GLWin.dpy = XOpenDisplay(0);
  GLWin.screen = DefaultScreen(GLWin.dpy);
  /* get an appropriate visual */
  vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl);
  if (vi == NULL)
  {
    vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl);
    printf("Only Singlebuffered Visual!\n");
  }
  /* create a GLX context */
  GLWin.ctx = glXCreateContext(GLWin.dpy, vi, 0, GL_TRUE);
  /* create a color map */
  cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), vi->visual, AllocNone);
  GLWin.attr.colormap = cmap;
  GLWin.attr.border_pixel = 0;

  /* create a window in window mode*/
  GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
  GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),
      0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
      CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr);
  /* only set window title and handle wm_delete_events if in windowed mode */
  wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True);
  XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1);
  XSetStandardProperties(GLWin.dpy, GLWin.win, title, title, None, NULL, 0, NULL);
  XMapRaised(GLWin.dpy, GLWin.win);
  /* connect the glx-context to the window */
  glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx);
  XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
      &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth);
  if (!initGL()) {
    printf("Could not initialize OpenGL.\nAborting...\n");
    return False;
  }
  return True;
}

int main(int argc, char **argv) {
  XEvent event;
  KeySym key;
  Bool done = False;
  struct timeval ltv, tv = {0, 0};
  long dt;
  
  if (!createGLWindow("", 640, 480)) done = True;
  while (!done) {
    while (XPending(GLWin.dpy) > 0) {
      XNextEvent(GLWin.dpy, &event);
      switch (event.type) {
        case Expose:
          if (event.xexpose.count != 0) break;
          drawGLScene();
          break;
        case ConfigureNotify:
          if ((event.xconfigure.width != GLWin.width) || 
              (event.xconfigure.height != GLWin.height)) {
            GLWin.width = event.xconfigure.width;
            GLWin.height = event.xconfigure.height;
            resizeGLScene(event.xconfigure.width, event.xconfigure.height);
          }
          break;
        case KeyPress:
          key = XLookupKeysym(&event.xkey, 0);
          if(key == XK_Escape || key == XK_q) done = True;
          if(key == XK_space) stop ^= 1;
          break;
        case ClientMessage:
          if (!strcmp(XGetAtomName(GLWin.dpy, event.xclient.message_type), "WM_PROTOCOLS"))
            done = True;
          break;
      }
    }
    drawGLScene();
    ltv = tv;
    gettimeofday(&tv, NULL);
    dt = (tv.tv_sec-ltv.tv_sec)*1000000+tv.tv_usec-ltv.tv_usec;
    if(dt>0 && dt<20000) usleep(20000-dt);
  }
  killGLWindow();
  return 0;
}
_______________________________________________
compiz mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/compiz

Reply via email to