X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Fatlantis.c;h=b62d50d381e0eedbb91cad20f5daa80442e3edba;hb=a94197e76a5dea5cb60542840809d6c20d0abbf3;hp=140295c1fe22d86cfe3cdb95dc334b3cd1d6f99b;hpb=ce3185de9d9705e259f2b60dd4b5509007fa17d4;p=xscreensaver diff --git a/hacks/glx/atlantis.c b/hacks/glx/atlantis.c index 140295c1..b62d50d3 100644 --- a/hacks/glx/atlantis.c +++ b/hacks/glx/atlantis.c @@ -36,6 +36,11 @@ static const char sccsid[] = "@(#)atlantis.c 1.3 98/06/18 xlockmore"; * * REVISION HISTORY: * + * Jamie Zawinski, 2-Apr-01: - The fishies were inside out! The back faces + * were being drawn, not the front faces. + * - Added a texture to simulate light from the + * surface, like in the SGI version. + * * David A. Bagley - 98/06/17 : Add whalespeed option. Global options to * initialize local variables are now: * XLock.atlantis.cycles: 100 ! SharkSpeed @@ -98,16 +103,25 @@ static const char sccsid[] = "@(#)atlantis.c 1.3 98/06/18 xlockmore"; * OpenGL(TM) is a trademark of Silicon Graphics, Inc. */ +#define DEF_TEXTURE "True" +#define DEF_GRADIENT "False" +#define DEF_WHALESPEED "250" + #ifdef STANDALONE # define PROGCLASS "Atlantis" # define HACK_INIT init_atlantis # define HACK_DRAW draw_atlantis +# define HACK_RESHAPE reshape_atlantis # define atlantis_opts xlockmore_opts -# define DEFAULTS "*delay: 1000 \n" \ +# define DEFAULTS "*delay: 25000 \n" \ "*count: 4 \n" \ + "*showFPS: False \n" \ "*cycles: 100 \n" \ "*size: 6000 \n" \ - "*whalespeed: 250 \n" + "*wireframe: False \n" \ + "*texture: " DEF_TEXTURE " \n" \ + "*gradient: " DEF_GRADIENT " \n" \ + "*whalespeed: " DEF_WHALESPEED " \n" # include "xlockmore.h" /* from the xscreensaver distribution */ #else /* !STANDALONE */ # include "xlock.h" /* from the xlockmore distribution */ @@ -120,21 +134,29 @@ static const char sccsid[] = "@(#)atlantis.c 1.3 98/06/18 xlockmore"; #include -#define DEF_WHALESPEED "250" static int whalespeed; +static int do_texture; +static int do_gradient; static XrmOptionDescRec opts[] = { - {"-whalespeed", ".atlantis.whalespeed", XrmoptionSepArg, (caddr_t) NULL} + {"-whalespeed", ".atlantis.whalespeed", XrmoptionSepArg, (caddr_t) NULL}, + {"-texture", ".atlantis.texture", XrmoptionNoArg, (caddr_t)"true"}, + {"+texture", ".atlantis.texture", XrmoptionNoArg, (caddr_t)"false"}, + {"-gradient", ".atlantis.gradient", XrmoptionNoArg, (caddr_t)"true"}, + {"+gradient", ".atlantis.gradient", XrmoptionNoArg, (caddr_t)"false"}, }; static argtype vars[] = { -{(caddr_t *) & whalespeed, "whalespeed", "WhaleSpeed", DEF_WHALESPEED, t_Int} + {(caddr_t *) & whalespeed, "whalespeed", "WhaleSpeed", DEF_WHALESPEED, t_Int}, + {(caddr_t *) &do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {(caddr_t *) &do_gradient, "gradient", "Gradient", DEF_GRADIENT, t_Bool}, }; static OptionStruct desc[] = { - {"-whalespeed num", "speed of whales and the dolphin"} + {"-whalespeed num", "speed of whales and the dolphin"}, + {"-texture num", "whether to introduce water-like distortion"} }; ModeSpecOpt atlantis_opts = @@ -151,6 +173,21 @@ ModStruct atlantis_description = static atlantisstruct *atlantis = NULL; +#include "xpm-ximage.h" + +#include "../images/sea-texture.xpm" + + +static void +parse_image_data(ModeInfo *mi) +{ + atlantisstruct *ap = &atlantis[MI_SCREEN(mi)]; + ap->texture = xpm_to_ximage (mi->dpy, + mi->xgwa.visual, + mi->xgwa.colormap, + sea_texture); +} + static void InitFishs(atlantisstruct * ap) { @@ -190,8 +227,10 @@ InitFishs(atlantisstruct * ap) } static void -Init(atlantisstruct * ap) +Init(ModeInfo *mi) { + atlantisstruct *ap = &atlantis[MI_SCREEN(mi)]; + static float ambient[] = {0.1, 0.1, 0.1, 1.0}; static float diffuse[] = @@ -210,36 +249,87 @@ Init(atlantisstruct * ap) {0.4, 0.4, 0.4, 1.0}; static float lmodel_localviewer[] = {0.0}; - float fblue = 0.0, fgreen; - - glFrontFace(GL_CW); - - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); - glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); - glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); - glLightfv(GL_LIGHT0, GL_POSITION, position); - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); - glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_localviewer); - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); + glFrontFace(GL_CCW); + + if (ap->wire) + { + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + glDisable(GL_NORMALIZE); + } + else + { + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); + glShadeModel(GL_SMOOTH); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_localviewer); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); + } + + if (ap->wire || !do_texture) + { + glDisable(GL_TEXTURE_2D); + } + else + { + GLfloat s_plane[] = { 1, 0, 0, 0 }; + GLfloat t_plane[] = { 0, 0, 1, 0 }; + GLfloat scale = 0.0005; + + if (!ap->texture) + parse_image_data (mi); + + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + ap->texture->width, ap->texture->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, + ap->texture->data); + check_gl_error("texture"); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGenfv(GL_S, GL_EYE_PLANE, s_plane); + glTexGenfv(GL_T, GL_EYE_PLANE, t_plane); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_2D); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(scale, scale, 1); + glMatrixMode(GL_MODELVIEW); + } InitFishs(ap); - /* Add a little randomness */ - fblue = ((float) (NRAND(50)) / 100.0) + 0.50; - fgreen = fblue * 0.56; - glClearColor(0.0, fgreen, fblue, 0.0); + glClearColor(0.0, 0.39, 0.7, 0.0); } -static void -Reshape(ModeInfo * mi, int width, int height) +void +reshape_atlantis(ModeInfo * mi, int width, int height) { atlantisstruct *ap = &atlantis[MI_SCREEN(mi)]; @@ -251,6 +341,106 @@ Reshape(ModeInfo * mi, int width, int height) glMatrixMode(GL_MODELVIEW); } + +/* jwz -- this doesn't really work very well. + + All I want to do is give the tank a gradient-filled background, instead + of just solid blue. The following was my guess as to how to do this, + but it kills my frame rate. I guess there's a more efficient way to do + this, but I don't see it... + + I mean, all I want to do is dump some non-projected bytes into the color + buffer, then zero out the depth buffer. That *can't* be expensive, can + it? + */ +static void +clear_tank (atlantisstruct * ap) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (do_gradient && !ap->wire) + { + static GLint gradient_list = -1; + static GLint gradient_tex = -1; + + if (gradient_list == -1) + { + unsigned char *pixels = 0; + int start = 64; + int end = start + 128; + int size = 4 * (end - start); + int i; + + pixels = (unsigned char *) malloc (size); + i = 0; + while (i < size) + { + pixels[i++] = 0; + pixels[i++] = (start + (i>>2)) * 0.56; + pixels[i++] = (start + (i>>2)); + pixels[i++] = 255; + } + + clear_gl_error(); + + glGenTextures(1, &gradient_tex); + glBindTexture(GL_TEXTURE_1D, gradient_tex); + + glTexImage1D(GL_TEXTURE_1D, 0, 4, + (end - start), 0, + GL_RGBA, GL_UNSIGNED_BYTE, pixels); + check_gl_error ("gradient texture"); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + + gradient_list = glGenLists(1); + glNewList(gradient_list, GL_COMPILE); + + glDepthMask (False); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_1D); + glBindTexture(GL_TEXTURE_1D, gradient_tex); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glRotatef(90, 0, 0, 1); + glTranslatef(-1, -1, 0); + glScalef(2, 2, 1); + + glBegin(GL_QUADS); + glTexCoord1i(1); glVertex3i(1, 0, 0); + glTexCoord1i(0); glVertex3i(0, 0, 0); + glTexCoord1i(0); glVertex3i(0, 1, 0); + glTexCoord1i(1); glVertex3i(1, 1, 0); + glEnd(); + + glPopMatrix(); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glDisable(GL_TEXTURE_1D); + + glDepthMask (True); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + if (do_texture) + glEnable(GL_TEXTURE_2D); + + glEndList(); + check_gl_error ("gradient list"); + } + + glCallList(gradient_list); + } +} + + static void Animate(atlantisstruct * ap) { @@ -273,7 +463,7 @@ AllDisplay(atlantisstruct * ap) { int i; - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + clear_tank(ap); for (i = 0; i < ap->num_sharks; i++) { glPushMatrix(); @@ -357,9 +547,9 @@ init_atlantis(ModeInfo * mi) } if ((ap->glx_context = init_GL(mi)) != NULL) { - Reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + reshape_atlantis(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); glDrawBuffer(GL_BACK); - Init(ap); + Init(mi); AllDisplay(ap); glXSwapBuffers(display, window); @@ -390,11 +580,10 @@ draw_atlantis(ModeInfo * mi) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glPushMatrix(); - - AllDisplay(ap); - Animate(ap); + AllDisplay(ap); + Animate(ap); + if (mi->fps_p) do_fps (mi); glXSwapBuffers(display, window); } @@ -439,7 +628,7 @@ change_atlantis(ModeInfo * mi) return; glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ap->glx_context)); - Init(ap); + Init(mi); } #endif /* USE_GL */