Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3534399
  • 博文数量: 864
  • 博客积分: 14125
  • 博客等级: 上将
  • 技术积分: 10634
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-27 16:53
个人简介

https://github.com/zytc2009/BigTeam_learning

文章分类

全部博文(864)

文章存档

2023年(1)

2021年(1)

2019年(3)

2018年(1)

2017年(10)

2015年(3)

2014年(8)

2013年(3)

2012年(69)

2011年(103)

2010年(357)

2009年(283)

2008年(22)

分类: C/C++

2010-12-06 13:32:02

球面映射:

这一个将教会你如何把环境纹理包裹在你的3D模型上,让它看起来象反射了周围的场景一样。

球体环境映射是一个创建快速金属反射效果的方法,但它并不像真实世界里那么精确!我们从18课的代码开始来创建这个教程,教你如何创建这种效果。

在我们开始之间,看一下红宝书中的介绍。它定义球体环境映射为一幅位于无限远的图像,把它映射到球面上。

在Photoshop中创建一幅球体环境映射图。

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

我们并没有添加任何全局变量,只是把纹理组的大小变为6,以保存6幅纹理。

GLuint	texture[6];								// 保存6幅纹理 
下面我们要做的就是载入这些纹理
int LoadGLTextures()								
{
int Status=FALSE;

AUX_RGBImageRec *TextureImage[2]; // 创建纹理的保存空间

memset(TextureImage,0,sizeof(void *)*2); // 清空为0

// 载入*.bmp图像
if ((TextureImage[0]=LoadBMP("Data/BG.bmp")) && // 背景图
(TextureImage[1]=LoadBMP("Data/Reflect.bmp"))) // 反射图(球形纹理图)
{
Status=TRUE;

glGenTextures(6, &texture[0]); // 创建6个纹理

for (int loop=0; loop<=1; loop++)
{
// 创建临近点过滤纹理图
glBindTexture(GL_TEXTURE_2D, texture[loop]); // 创建纹理0和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);

// 创建线形过滤纹理图
glBindTexture(GL_TEXTURE_2D, texture[loop+2]); // 创建纹理2,3
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);

// 创建线形Mipmap纹理图
glBindTexture(GL_TEXTURE_2D, texture[loop+4]); // 创建纹理4,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<=1; loop++)
{
if (TextureImage[loop]) // 如果图像存在则清除
{
if (TextureImage[loop]->data)
{
free(TextureImage[loop]->data);
}
free(TextureImage[loop]);
}
}
}

return Status;
}
我们对立方体的绘制代码做了一些小的改动,把法线的范围从[-1,1]缩放到[-0.5,0.5]。如果法向量太大的话,会产生一些块状效果,影响视觉效果。
GLvoid glDrawCube()
{
glBegin(GL_QUADS);
// 前面
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);
// 背面
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);
// 上面
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);
// 下面
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);
// 右面
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);
// 左面
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();
}
在初始化OpenGL中,我们添加一些新的函数来使用球体纹理映射。
下面的代码让OpenGL自动为我们计算使用球体映射时,顶点的纹理坐标。
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);			// 设置s方向的纹理自动生成
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); // 设置t方向的纹理自动生成
我们几乎完成了所有的工作!接下来要做的就是就是绘制渲染,我删除了一些二次几何体,因为它们的视觉效果并不好。当然我们需要OpenGL为这些几何体自动生成坐标,接着选择球体映射纹理并绘制几何体。最后把OpenGL状态设置正常模式。
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // 重置视口

glTranslatef(0.0f,0.0f,z);

glEnable(GL_TEXTURE_GEN_S); // 自动生成s方向纹理坐标
glEnable(GL_TEXTURE_GEN_T); // 自动生成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);

xrot+=xspeed;
yrot+=yspeed;
return TRUE; // 成功返回
}
最后我们使用空格来切换各个不同的几何体
				if (keys[' '] && !sp)
{
sp=TRUE;
object++;
if(object>3)
object=0;
}
阅读(510) | 评论(0) | 转发(1) |
0

上一篇:第20课

下一篇:第25课

给主人留下些什么吧!~~