📄 underwater.c
字号:
void reshape(int w, int h){ glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0, /* field of view in degree */ (GLfloat) w/(GLfloat) h, /* aspect ratio */ 20.0, /* Z near */ 100.0); /* Z far */ glMatrixMode(GL_MODELVIEW);}voididle(void){ /* Advance the caustic pattern. */ currentCaustic = (currentCaustic + causticIncrement) % NUM_PATTERNS; glutPostRedisplay();}voidupdateIdleFunc(void){ /* Must be both displaying the caustic patterns and have the caustics in rippling motion to need an idle callback. */ if (showCaustics && causticMotion) { glutIdleFunc(idle); } else { glutIdleFunc(NULL); }}void visible(int vis){ /* Stop the animation when the window is not visible. */ if (vis == GLUT_VISIBLE) updateIdleFunc(); else glutIdleFunc(NULL);}/* ARGSUSED2 */static voidmouse(int button, int state, int x, int y){ /* Rotate the scene with the left mouse button. */ if (button == GLUT_LEFT_BUTTON) { if (state == GLUT_DOWN) { moving = 1; startx = x; starty = y; } if (state == GLUT_UP) { moving = 0; } } /* Rotate the light position with the middle mouse button. */ if (button == GLUT_MIDDLE_BUTTON) { if (state == GLUT_DOWN) { lightMoving = 1; lightStartX = x; lightStartY = y; } if (state == GLUT_UP) { lightMoving = 0; } }}/* ARGSUSED1 */static voidmotion(int x, int y){ if (moving) { angle = angle + (x - startx); angle2 = angle2 + (y - starty); startx = x; starty = y; glutPostRedisplay(); } if (lightMoving) { lightAngle += (x - lightStartX)/40.0; lightHeight += (lightStartY - y)/20.0; lightStartX = x; lightStartY = y; glutPostRedisplay(); }}/* ARGSUSED1 */static voidkeyboard(unsigned char c, int x, int y){ switch (c) { case 27: /* Escape quits. */ exit(0); break; case 'R': /* Simplistic benchmarking. */ case 'r': reportSpeed = !reportSpeed; break; case ' ': /* Spacebar toggles caustic rippling motion. */ causticMotion = !causticMotion; updateIdleFunc(); break; }}voidmenuSelect(int value){ switch (value) { case M_POSITIONAL: directionalLight = 0; break; case M_DIRECTIONAL: directionalLight = 1; break; case M_GREENISH_LIGHT: lightDiffuseColor[0] = 1.0; lightDiffuseColor[1] = 1.5; /* XXX Green = 1.5 */ lightDiffuseColor[2] = 1.0; glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuseColor); break; case M_WHITE_LIGHT: lightDiffuseColor[0] = 1.5; /* XXX Red = 1.5 */ lightDiffuseColor[1] = 1.5; /* XXX Green = 1.5 */ lightDiffuseColor[2] = 1.5; /* XXX Blue = 1.5 */ glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuseColor); break; case M_WITH_CAUSTICS: showCaustics = 1; updateIdleFunc(); break; case M_NO_CAUSTICS: showCaustics = 0; updateIdleFunc(); break; case M_SWITCH_MODEL: object = (object + 1) % 3; break; case M_INCREASE_RIPPLE_SIZE: causticScale /= 1.5; break; case M_DECREASE_RIPPLE_SIZE: causticScale *= 1.5; break; } glutPostRedisplay();}intmain(int argc, char **argv){ int width, height; int i; GLubyte *imageData; glutInit(&argc, argv); for (i=1; i<argc; i++) { if (!strcmp("-lesstex", argv[i])) { /* Only use 16 caustic textures. Saves texture memory and works better on slow machines. */ causticIncrement = 2; } else if (!strcmp("-evenlesstex", argv[i])) { /* Only use 8 caustic textures. Saves even more texture memory for slow machines. Temporal rippling suffers. */ causticIncrement = 4; } else if (!strcmp("-nomipmap", argv[i])) { /* Don't use linear mipmap linear texture filtering; instead use linear filtering. */ useMipmaps = 0; } else if (!strcmp("-fullscreen", argv[i])) { fullscreen = 1; } else { fprintf(stderr, "usage: caustics [-lesstex]\n"); fprintf(stderr, " -lesstex uses half the caustic textures.\n"); fprintf(stderr, " -evenlesstex uses one fourth of the caustic textures.\n"); exit(1); } } glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); if (fullscreen) { glutGameModeString("800x600:16@60"); glutEnterGameMode(); } else { glutCreateWindow("underwater"); } /* Check that renderer has the GL_EXT_texture_object extension or supports OpenGL 1.1 */#ifdef TEXTURE_OBJECT { char *version = (char *) glGetString(GL_VERSION); if (glutExtensionSupported("GL_EXT_texture_object") || strncmp(version, "1.1", 3) == 0) { HaveTexObj = GL_TRUE; } }#endif glEnable(GL_TEXTURE_2D);#ifdef TEXTURE_OBJECT /* Replace texture environment not in OpenGL 1.0. */ if (HaveTexObj) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);#endif /* Load the caustic ripple textures. */ printf("loading caustics:"); for (i=0; i<NUM_PATTERNS; i += causticIncrement) { char filename[80]; sprintf(filename, "caust%02d.bw", i); printf(" %d", i); fflush(stdout); imageData = read_alpha_texture(filename, &width, &height); if (imageData == NULL) { fprintf(stderr, "\n%s: could not load image file\n", filename); exit(1); } if (HaveTexObj) glBindTexture(GL_TEXTURE_2D, i+1); else glNewList(i+101, GL_COMPILE); if (useMipmaps) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imageData); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, height, width, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, imageData); } free(imageData); if (!HaveTexObj) glEndList(); } printf(".\n"); /* Load an RGB file for the floor texture. */ printf("loading RGB textures: floor"); fflush(stdout); imageData = read_rgb_texture(FLOOR_FILE, &width, &height); if (imageData == NULL) { fprintf(stderr, "%s: could not load image file\n", FLOOR_FILE); exit(1); } printf(".\n"); if (HaveTexObj) glBindTexture(GL_TEXTURE_2D, 100); else glNewList(100, GL_COMPILE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (useMipmaps) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, imageData); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData); } free(imageData); if (!HaveTexObj) glEndList(); glMatrixMode(GL_MODELVIEW); gluLookAt(0.0, 8.0, 60.0, /* eye is at (0,8,60) */ 0.0, 8.0, 0.0, /* center is at (0,8,0) */ 0.0, 1.0, 0.); /* up is in postivie Y direction */ /* Setup initial OpenGL rendering state. */ glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuseColor); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); /* Register assorted GLUT callback routines. */ glutDisplayFunc(display); glutReshapeFunc(reshape); glutVisibilityFunc(visible); glutMouseFunc(mouse); glutMotionFunc(motion); glutKeyboardFunc(keyboard); /* Create a pop-up menu. */ if (!fullscreen) { glutCreateMenu(menuSelect); glutAddMenuEntry("Positional light", M_POSITIONAL); glutAddMenuEntry("Directional light", M_DIRECTIONAL); glutAddMenuEntry("Greenish light", M_GREENISH_LIGHT); glutAddMenuEntry("White light", M_WHITE_LIGHT); glutAddMenuEntry("With caustics", M_WITH_CAUSTICS); glutAddMenuEntry("No caustics", M_NO_CAUSTICS); glutAddMenuEntry("Switch model", M_SWITCH_MODEL); glutAddMenuEntry("Increase ripple size", M_INCREASE_RIPPLE_SIZE); glutAddMenuEntry("Decrease ripple size", M_DECREASE_RIPPLE_SIZE); glutAttachMenu(GLUT_RIGHT_BUTTON); } /* For rendering the MODEL_DINO object. */ dinoDisplayList = makeDinosaur(); /* Enter GLUT's main loop; callback dispatching begins. */ glutMainLoop(); return 0; /* ANSI C requires main to return int. */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -