📄 dissolve.c
字号:
/* dissolve.c - by Tom McReynolds, SGI *//* An Example of dissolve, using stencil *//* Drag with left mouse button to dissolve to the 3D background, Drag with middle mouse button to dissolve to checkerboard, and use right button for menu to clear stencil. */#include "glut.h"#include <stdlib.h>#include <string.h>#include <math.h>#include <stdio.h>#ifdef WIN32#define random rand#endifint winWidth = 512;int winHeight = 512;/* Create a single component texture map */GLfloat *make_texture(int maxs, int maxt){ int s, t; static GLfloat *texture; texture = (GLfloat *) malloc(maxs * maxt * sizeof(GLfloat)); for (t = 0; t < maxt; t++) { for (s = 0; s < maxs; s++) { texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1); } } return texture;}enum { SPHERE = 1, CONE};GLfloat angle = 0.f; /* angle of rotating object in layer 0 */enum { X, Y};GLboolean eraser = GL_FALSE;GLint layer = 1;GLint eraserpos[2] ={512 / 8, 512 / 12};/* draw eraser and erase what's underneath */GLubyte *eraserpix = 0;int erasersize = 0;voidmakeEraser(void){ int i, skip; erasersize = 4 * winWidth / 4 * winHeight / 6; eraserpix = (GLubyte *) realloc(eraserpix, erasersize * sizeof(GLubyte)); /* make it white */ (void) memset(eraserpix, 255, erasersize * sizeof(GLubyte)); skip = (int) (random() % 8); for (i = 0; i < erasersize; i++) { if (!skip) { eraserpix[i] = 0; eraserpix[i + 1] = 0; eraserpix[i + 2] = 0; eraserpix[i + 3] = 0; skip = (int) (random() % 8); } else skip--; }}/* ARGSUSED2 *//* left button, first layer, middle button, second layer */voidmouse(int button, int state, int x, int y){ if (state == GLUT_DOWN) { eraser = GL_TRUE; if (button == GLUT_LEFT_BUTTON) layer = 1; else /* GLUT_MIDDLE: GLUT_RIGHT is for menu */ layer = 0; } else { /* GLUT_UP */ eraser = GL_FALSE; } glutPostRedisplay();}enum { CLEAR}; /* menu choices */GLboolean clearstencil = GL_TRUE;voidmenu(int choice){ switch (choice) { case CLEAR: clearstencil = GL_TRUE; break; } glutPostRedisplay();}/* used to get current width and height of viewport */voidreshape(int wid, int ht){ glViewport(0, 0, wid, ht); winWidth = wid; winHeight = ht; clearstencil = GL_TRUE; makeEraser(); glutPostRedisplay();}voiddraweraser(void){ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, winWidth, 0, winHeight); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* replace with this layer */ glStencilFunc(GL_ALWAYS, layer, 0); glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_NOTEQUAL, 0); glRasterPos2i(eraserpos[X], eraserpos[Y]); glBitmap(0, 0, 0.f, 0.f, -winWidth / 8.f, -winHeight / 12.f, 0); glDrawPixels(winWidth / 4, winHeight / 6, GL_RGBA, GL_UNSIGNED_BYTE, eraserpix); glDisable(GL_ALPHA_TEST);}voiddrawlayer2(void){ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, winWidth, 0, winHeight); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2i(0, 0); glVertex2i(0, 0); glTexCoord2i(1, 0); glVertex2i(winWidth, 0); glTexCoord2i(1, 1); glVertex2i(winWidth, winHeight); glTexCoord2i(0, 1); glVertex2i(0, winHeight); glEnd(); glDisable(GL_TEXTURE_2D); if (glGetError()) /* to catch programming errors; should never happen */ printf("Oops! I screwed up my OpenGL calls somewhere\n");}voiddrawlayer1(void){ /* material properties for objects in scene */ static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f}; static GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f}; /* draw a perspective scene */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-100., 100., -100., 100., 320., 640.); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* turn on features */ glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); /* place light 0 in the right place */ glLightfv(GL_LIGHT0, GL_POSITION, lightpos); /* remove back faces to speed things up */ glCullFace(GL_BACK); /* Note: wall verticies are ordered so they are all front facing this lets me do back face culling to speed things up. */ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat); /* floor */ /* make the floor textured */ glEnable(GL_TEXTURE_2D); /* Since we want to turn texturing on for floor only, we have to make floor a separate glBegin()/glEnd() sequence. You can't turn texturing on and off between begin and end calls */ glBegin(GL_QUADS); glNormal3f(0.f, 1.f, 0.f); glTexCoord2i(0, 0); glVertex3f(-100.f, -100.f, -320.f); glTexCoord2i(1, 0); glVertex3f(100.f, -100.f, -320.f); glTexCoord2i(1, 1); glVertex3f(100.f, -100.f, -520.f); glTexCoord2i(0, 1); glVertex3f(-100.f, -100.f, -520.f); glEnd(); glDisable(GL_TEXTURE_2D); /* walls */ glBegin(GL_QUADS); /* left wall */ glNormal3f(1.f, 0.f, 0.f); glVertex3f(-100.f, -100.f, -320.f); glVertex3f(-100.f, -100.f, -520.f); glVertex3f(-100.f, 100.f, -520.f); glVertex3f(-100.f, 100.f, -320.f); /* right wall */ glNormal3f(-1.f, 0.f, 0.f); glVertex3f(100.f, -100.f, -320.f); glVertex3f(100.f, 100.f, -320.f); glVertex3f(100.f, 100.f, -520.f); glVertex3f(100.f, -100.f, -520.f); /* ceiling */ glNormal3f(0.f, -1.f, 0.f); glVertex3f(-100.f, 100.f, -320.f); glVertex3f(-100.f, 100.f, -520.f); glVertex3f(100.f, 100.f, -520.f); glVertex3f(100.f, 100.f, -320.f); /* back wall */ glNormal3f(0.f, 0.f, 1.f); glVertex3f(-100.f, -100.f, -520.f); glVertex3f(100.f, -100.f, -520.f); glVertex3f(100.f, 100.f, -520.f); glVertex3f(-100.f, 100.f, -520.f); glEnd(); glPushMatrix(); glTranslatef(-80.f, -80.f, -420.f); glCallList(SPHERE); glPopMatrix(); glPushMatrix(); glTranslatef(-20.f, -100.f, -500.f); glCallList(CONE); glPopMatrix(); if (glGetError()) /* to catch programming errors; should never happen */ printf("Oops! I screwed up my OpenGL calls somewhere\n");}voiddrawlayer0(void){ static GLfloat lightpos[] = {50.f, 50.f, 0.f, 1.f}; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-50.f, 50.f, -50.f, 50.f, 0.f, 100.f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.f, 0.f, -50.f); glRotatef(angle, 0.f, 1.f, 0.f); glRotatef(90.f, 0.f, 0.f, 1.f); glTranslatef(0.f, -25.f, 0.f); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, lightpos); glCullFace(GL_BACK); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glCallList(CONE);}voidredraw(void){ if (glutLayerGet(GLUT_NORMAL_DAMAGED) || clearstencil == GL_TRUE) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); clearstencil = GL_FALSE; } else glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 2, ~0); drawlayer2(); glStencilFunc(GL_EQUAL, 1, ~0); drawlayer1(); glStencilFunc(GL_EQUAL, 0, ~0); drawlayer0(); if (eraser) draweraser(); glutSwapBuffers();}voididle(void){ angle += 1.f; glutPostRedisplay();}voidpassive(int x, int y){ eraserpos[X] = x; eraserpos[Y] = winHeight - y;}voidmotion(int x, int y){ eraserpos[X] = x; eraserpos[Y] = winHeight - y; glutPostRedisplay();}/* ARGSUSED1 */void key(unsigned char key, int x, int y){ switch (key) { case '\033': exit(0); }}void visible(int vis){ if (vis == GLUT_VISIBLE) glutIdleFunc(idle); else glutIdleFunc(NULL);}const int TEXDIM = 256;GLfloat *tex = 0;main(int argc, char *argv[]){ static GLfloat sphere_mat[] = {1.f, .5f, 0.f, 1.f}; static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f}; GLUquadricObj *sphere, *cone, *base; glutInit(&argc, argv); glutInitWindowSize(winWidth, winHeight); glutInitDisplayMode(GLUT_DOUBLE | GLUT_STENCIL | GLUT_DEPTH); (void) glutCreateWindow("dissolve"); glutDisplayFunc(redraw); glutMouseFunc(mouse); glutMotionFunc(motion); glutPassiveMotionFunc(passive); glutKeyboardFunc(key); glutVisibilityFunc(visible); glutReshapeFunc(reshape); glutCreateMenu(menu); glutAddMenuEntry("Clear Stencil", CLEAR); glutAttachMenu(GLUT_RIGHT_BUTTON); glNewList(SPHERE, GL_COMPILE); /* make display lists for sphere and cone; for efficiency */ sphere = gluNewQuadric(); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat); gluSphere(sphere, 20.f, 20, 20); gluDeleteQuadric(sphere); glEndList(); glNewList(CONE, GL_COMPILE); cone = gluNewQuadric(); base = gluNewQuadric(); glRotatef(-90.f, 1.f, 0.f, 0.f); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat); gluQuadricOrientation(base, GLU_INSIDE); gluDisk(base, 0., 20., 20, 1); gluCylinder(cone, 20., 0., 60., 20, 20); gluDeleteQuadric(cone); gluDeleteQuadric(base); glEndList(); makeEraser(); /* load pattern for current 2d texture */ tex = make_texture(TEXDIM, TEXDIM); glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex); free(tex); glClearStencil(2); glEnable(GL_STENCIL_TEST); /* used all the time */ glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glutMainLoop(); return 0; /* ANSI C requires main to return int. */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -