/* comp.c - by David Blythe, SGI */ /* Porter/Duff compositing operations using OpenGL alpha blending. */ /* NOTE: This program uses OpenGL blending functions that need the frame buffer to retain a destination alpha component. Examples of such hardware: O2, IMPACT, RealityEngine, and InfiniteReality. */ #include #include #include #include #include "texture.h" static int w = 640, h = 640; void myReshape(int nw, int nh) { w = nw, h = nh; glClearColor(0, 0, 0, 0); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } static unsigned *a_data = 0, *b_data = 0; static int a_width, a_height, b_width, b_height; void init_tris(void) { if (a_data) free(a_data); if (b_data) free(b_data); a_data = (unsigned *) malloc(w * h); b_data = (unsigned *) malloc(w * h); glViewport(0, 0, w / 2, h / 2); glClear(GL_COLOR_BUFFER_BIT); glColor4f(1, 0, 0, 1); glBegin(GL_TRIANGLES); glVertex2f(-1, -1); glVertex2f(-1, 1); glVertex2f(.5, 1); glEnd(); glReadPixels(0, 0, w / 2, h / 2, GL_RGBA, GL_UNSIGNED_BYTE, a_data); glClear(GL_COLOR_BUFFER_BIT); glColor4f(0, 1, 0, 1); glBegin(GL_TRIANGLES); glVertex2f(1, -1); glVertex2f(1, 1); glVertex2f(-.5, 1); glEnd(); glReadPixels(0, 0, w / 2, h / 2, GL_RGBA, GL_UNSIGNED_BYTE, b_data); a_width = b_width = w / 2, a_height = b_height = h / 2; } void init_images(void) { int comp; a_data = read_texture("a.rgb", &a_width, &a_height, &comp); printf("%dx%dx%d\n", a_width, a_height, comp); b_data = read_texture("b.rgb", &b_width, &b_height, &comp); printf("%dx%dx%d\n", b_width, b_height, comp); } void display(void) { int i; glDrawBuffer(GL_FRONT_AND_BACK); glClear(GL_COLOR_BUFFER_BIT); glDrawBuffer(GL_BACK); glBlendFunc(GL_SRC_ALPHA, GL_ZERO); /* image A */ glViewport(0, 0, w / 2, h / 2); glRasterPos2f(-1, -1); glDrawPixels(a_width, a_height, GL_RGBA, GL_UNSIGNED_BYTE, a_data); glEnable(GL_BLEND); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glCopyPixels(0, 0, w / 2, h / 2, GL_COLOR); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_BLEND); /* image B */ glViewport(w / 2, 0, w / 2, h / 2); glRasterPos2f(-1, -1); glDrawPixels(b_width, b_height, GL_RGBA, GL_UNSIGNED_BYTE, b_data); glEnable(GL_BLEND); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glCopyPixels(w / 2, 0, w / 2, h / 2, GL_COLOR); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glReadBuffer(GL_BACK); glDrawBuffer(GL_FRONT); for (i = 0; i < 4; i++) { glDisable(GL_BLEND); switch (i) { case 0: /* a over b */ glViewport(0, 0, w / 2, h / 2); glRasterPos2f(-1, -1); glCopyPixels(0, 0, w / 2, h / 2, GL_COLOR); glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE); glCopyPixels(w / 2, 0, w / 2, h / 2, GL_COLOR); break; case 1: /* a under b */ glViewport(w / 2, 0, w / 2, h / 2); glRasterPos2f(-1, -1); glCopyPixels(0, 0, w / 2, h / 2, GL_COLOR); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glCopyPixels(w / 2, 0, w / 2, h / 2, GL_COLOR); break; case 2: /* b in a */ glViewport(0, h / 2, w / 2, h / 2); glRasterPos2f(-1, -1); glCopyPixels(0, 0, w / 2, h / 2, GL_COLOR); glEnable(GL_BLEND); glBlendFunc(GL_DST_ALPHA, GL_ZERO); glCopyPixels(w / 2, 0, w / 2, h / 2, GL_COLOR); break; case 3: /* b out of a */ glViewport(w / 2, h / 2, w / 2, h / 2); glRasterPos2f(-1, -1); glCopyPixels(0, 0, w / 2, h / 2, GL_COLOR); glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO); glCopyPixels(w / 2, 0, w / 2, h / 2, GL_COLOR); break; } } glViewport(0, 0, w, h); glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE); glColor4f(1., 1., 1., 0.); glRectf(-1, -1, 1, 1); glFlush(); } /* ARGSUSED1 */ void key(unsigned char key, int x, int y) { if (key == '\033') exit(0); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitWindowSize(w, h); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA); if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE)) { printf("comp: requires a frame buffer with destination alpha\n"); exit(1); } glutCreateWindow("comp"); if (argc > 1) init_images(); else init_tris(); glutDisplayFunc(display); glutReshapeFunc(myReshape); glutKeyboardFunc(key); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }