OpenGL 三维物体Alpha混合

//三维透明物体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;
}

  

posted @ 2012-05-30 19:15  Andy Sun  Views(459)  Comments(0)    收藏  举报