//三维透明物体Alpha混合 红宝书P160
#include<GL\freeglut.h>
#define MAXZ 8.0//Z的最大深度
#define MINZ -8.0//Z的最小深度
#define ZINC 0.04//Z每次的深度改变值
static float solidZ = MAXZ;//实体球的深度
static float transparentZ = MINZ;//透明立方体的深度
static GLuint sphereList,cubeList;//绘制球和立方体的列表
static void init(void)
{
GLfloat mat_specular[] = {1.0,1.0,1.0,0.15};
GLfloat mat_shininess[] = {100.0};
GLfloat position[] = {0.5,0.5,1.0,0.0};
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
sphereList = glGenLists(1);
glNewList(sphereList,GL_COMPILE);
glutSolidSphere(0.4,16,16);
glEndList();
cubeList = glGenLists(1);
glNewList(cubeList,GL_COMPILE);
glutSolidCube(0.6);
glEndList();
}
void display(void)
{
GLfloat mat_solid[] = {0.75,0.75,0.0,1.0};
GLfloat mat_zero[] = {0.0,0.0,0.0,1.0};
GLfloat mat_transparent[]={0.0,0.8,0.8,0.6};
GLfloat mat_emission[] = {0.0,0.3,0.3,0.6};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(-0.15,-0.15,solidZ);
glMaterialfv(GL_FRONT,GL_EMISSION,mat_zero);
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_solid);
glCallList(sphereList);//调用显示列表绘制球体
glPopMatrix();
glPushMatrix();
glTranslatef(0.15,0.15,transparentZ);
glRotatef(15.0,1.0,1.0,0.0);
glRotatef(30.0,0.0,1.0,0.0);
glMaterialfv(GL_FRONT,GL_EMISSION,mat_emission);
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_transparent);
glEnable(GL_BLEND);//启用混合
glDepthMask(GL_FALSE);//深度缓冲区设置为只读
glBlendFunc(GL_SRC_ALPHA,GL_ONE);//设置混合方式为Alpha混合
glCallList(cubeList);//调用显示列表绘制立方体
glDepthMask(GL_TRUE);//将深度缓冲区设置为正常的读写
glDisable(GL_BLEND);//禁用混合
glPopMatrix();
glutSwapBuffers();//交换缓存,显示更改后的效果
}
void reshape(int w,int h)
{
glViewport(0,0,(GLint)w,(GLint)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w <= h)
glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w,1.5*(GLfloat)h/(GLfloat)w,-10.0,10.0);
else
glOrtho(-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h,-1.5,1.5,-10.0,10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void animate(void)
{
if(solidZ <= MINZ || transparentZ >= MAXZ)
glutIdleFunc(NULL);
else
{
solidZ -= ZINC;
transparentZ += ZINC;
glutPostRedisplay();//更改物体深度后,重绘整个场景
}
}
void keyboard(unsigned char key,int x,int y)
{
switch(key)
{
case 'a':case 'A':
solidZ = MAXZ;
transparentZ = MINZ;
glutIdleFunc(animate);//回调animate方法
break;
case 'r':case 'R':
solidZ = MAXZ;
transparentZ = MINZ;
glutPostRedisplay();//重置为初始状态
break;
case 27:
exit(0);
break;
}
}
int main(int argc,char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500,500);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}