OpenGL学习三十三:球面映射

(此节内容对应NEHE教程第23课)

 

把环境纹理包裹在你的3D模型上,让它看起来象反射了周围的场景一样。
球体环境映射是一个创建快速金属反射效果的方法

首先,你需要一幅球体环境映射图,用来把它映射到球体上。在Photoshop中打开一幅图并选择所有的像素,创建它的一个复制。
接着,我们把图像变为2的幂次方大小,一般为128x128或256x256。
最后使用扭曲(distort)滤镜,并应用球体效果。然后把它保存为Reflect.bmp文件。
如右图上面的为背景的图片,下面为经过球面滤镜处理过的,用于进行球面贴图的纹理

对于球面映射往往我们希望背景图片是不变的,前面球面是可以转动的,因此适当的PUSH 与POP 视图模型 可以带到效果

 

OpenGL学习三十三:球面映射OpenGL学习三十三:球面映射OpenGL学习三十三:球面映射

            原始图片                                处理后图片                                     合成后效果

 

#include "header.h"

int		part1;				
int		part2;				
int		p1=0;				
int		p2=1;				

GLfloat	xrot;				
GLfloat	yrot;				
GLfloat xspeed;				
GLfloat yspeed;				
GLfloat	z=-10.0f;			

GLUquadricObj *quadratic;	

GLfloat LightAmbient[]=		{ 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[]=		{ 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]=	{ 0.0f, 0.0f, 2.0f, 1.0f };

GLuint	filter;			
GLuint	texture[6];			
GLuint  object=1;			



AUX_RGBImageRec *LoadBMP(char *Filename)				
{
	FILE *File=NULL;									
	if (!Filename)										
	{
		return NULL;								
	}

	File=fopen(Filename,"r");							

	if (File)											
	{
		fclose(File);								
		return auxDIBImageLoad(Filename);				
	}

	return NULL;										
}
int loop=0;
int LoadGLTextures()									
{
	int Status=FALSE;									

	AUX_RGBImageRec *TextureImage[2];					

	memset(TextureImage,0,sizeof(void *)*2);           	


	if ((TextureImage[0]=LoadBMP("Data/BG.bmp")) &&
		(TextureImage[1]=LoadBMP("Data/Reflect.bmp")))
	{
		Status=TRUE;									

		glGenTextures(6, &texture[0]);					

		for ( loop=0; loop<2; loop++)
		{
		// Create Nearest Filtered Texture
			glBindTexture(GL_TEXTURE_2D, texture[loop]);	// Gen Tex 0 and 1
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
			glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data);

			// Create Linear Filtered Texture
			glBindTexture(GL_TEXTURE_2D, texture[loop+2]);	// Gen Tex 2 and 3 4
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
			glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data);

			// Create MipMapped Texture
			glBindTexture(GL_TEXTURE_2D, texture[loop+4]);	// Gen Tex 4 and 5
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
			gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data);
		}
		for (loop=0; loop<2; loop++)
		{
	        if (TextureImage[loop])						
		    {
			        if (TextureImage[loop]->data)			
				    {
					        free(TextureImage[loop]->data);	
					}
					free(TextureImage[loop]);				
			}
		}
	}

	return Status;										
}
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)		
{
	if (height==0)										
	{
		height=1;										
	}

	glViewport(0,0,width,height);						

	glMatrixMode(GL_PROJECTION);						
	glLoadIdentity();									

	// Calculate The Aspect Ratio Of The Window
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

	glMatrixMode(GL_MODELVIEW);							
	glLoadIdentity();									
}

int InitGL(void)										
{
	if (!LoadGLTextures())								
	{
		return FALSE;									
	}

	glEnable(GL_TEXTURE_2D);							
	glShadeModel(GL_SMOOTH);						
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				
	glClearDepth(1.0f);									
	glEnable(GL_DEPTH_TEST);							
	glDepthFunc(GL_LEQUAL);								
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	

	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);		
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);		
	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);	
	glEnable(GL_LIGHT1);								

	quadratic=gluNewQuadric();							
	gluQuadricNormals(quadratic, GLU_SMOOTH);			
	gluQuadricTexture(quadratic, GL_TRUE);				

	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); 
	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); 

	return TRUE;										
}

void glDrawCube()
{
		glBegin(GL_QUADS);
		// Front Face
		glNormal3f( 0.0f, 0.0f, 0.5f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		// Back Face
		glNormal3f( 0.0f, 0.0f,-0.5f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		// Top Face
		glNormal3f( 0.0f, 0.5f, 0.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		// Bottom Face
		glNormal3f( 0.0f,-0.5f, 0.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		// Right Face
		glNormal3f( 0.5f, 0.0f, 0.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		// Left Face
		glNormal3f(-0.5f, 0.0f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
	glEnd();
}

void DrawGLScene(void)									
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
	glLoadIdentity();									

	glTranslatef(0.0f,0.0f,z);

	glEnable(GL_TEXTURE_GEN_S);						
	glEnable(GL_TEXTURE_GEN_T);						

	glBindTexture(GL_TEXTURE_2D, texture[filter+(filter+1)]);
	glPushMatrix();
	glRotatef(xrot,1.0f,0.0f,0.0f);
	glRotatef(yrot,0.0f,1.0f,0.0f);
	switch(object)
	{
	case 0:
		glDrawCube();
		break;
	case 1:
		glTranslatef(0.0f,0.0f,-1.5f);					
		gluCylinder(quadratic,1.0f,1.0f,3.0f,32,32);	
		break;
	case 2:
		gluSphere(quadratic,1.3f,32,32);				
		break;
	case 3:
		glTranslatef(0.0f,0.0f,-1.5f);					
		gluCylinder(quadratic,1.0f,0.0f,3.0f,32,32);	
		break;
	};

	glPopMatrix();
	glDisable(GL_TEXTURE_GEN_S);
	glDisable(GL_TEXTURE_GEN_T);

	glBindTexture(GL_TEXTURE_2D, texture[filter*2]);	
	glPushMatrix();
		glTranslatef(0.0f, 0.0f, -24.0f);
		glBegin(GL_QUADS);
			glNormal3f( 0.0f, 0.0f, 1.0f);
			glTexCoord2f(0.0f, 0.0f); glVertex3f(-13.3f, -10.0f,  10.0f);
			glTexCoord2f(1.0f, 0.0f); glVertex3f( 13.3f, -10.0f,  10.0f);
			glTexCoord2f(1.0f, 1.0f); glVertex3f( 13.3f,  10.0f,  10.0f);
			glTexCoord2f(0.0f, 1.0f); glVertex3f(-13.3f,  10.0f,  10.0f);
		glEnd();
	glPopMatrix();

	xrot+=xspeed;
	yrot+=yspeed;
	glFlush();
}


void rotate()
{
	glutPostRedisplay();
}
void keyboard(unsigned char key,int x,int y)
{
	switch (key)
	{
	case 'L':
		glEnable(GL_LIGHTING);
		glutPostRedisplay();
		break;
	case 'l':
		glDisable(GL_LIGHTING);
		glutPostRedisplay();
		break;
	case ' ':
		object++;
		if(object>5)
			object=0;
		glutPostRedisplay();
		break;
	case 'F':
		filter+=1;
		if (filter>2)
		{
			filter=0;
		}	
		glutPostRedisplay();
		break;
	case 'W':
		yspeed+=0.01f;	
		glutIdleFunc(rotate);
		break;
	case 'S':
		yspeed-=0.01f;	
		glutIdleFunc(rotate);
		break;
	case 'A':
		xspeed+=0.01f;	
		glutIdleFunc(rotate);
		break;
	case 'D':
		xspeed-=0.01f;	
		glutIdleFunc(rotate);
		break;
	case 'Z':
		z-=0.01f;	
		glutIdleFunc(rotate);
		break;
	case 'X':
		z+=0.01f;	
		glutIdleFunc(rotate);
		break;
	case 'R':
		glutIdleFunc(NULL);
		break;
	}

}


int main(int argc,char **argv)
{
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
	glutInitWindowSize(800,600);
	glutInitWindowPosition(100,100);
	glutCreateWindow("球面映射");
	InitGL();
	glutDisplayFunc(DrawGLScene);
	glutKeyboardFunc(keyboard);
	glutReshapeFunc(ReSizeGLScene);
	glutMainLoop();
}

 

你可能感兴趣的:(OpenGL)