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