NeHe OpenGL教程 第二十三课:球面映射

转自【翻译】NeHe OpenGL 教程

前言

声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改。对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢。

NeHe OpenGL第二十三课:球面映射

球面映射:

这一个将教会你如何把环境纹理包裹在你的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;

}

原文及其个版本源代码下载:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=23

时间: 2024-10-19 14:09:11

NeHe OpenGL教程 第二十三课:球面映射的相关文章

NeHe OpenGL教程 第二十二课:凹凸映射

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第二十二课:凹凸映射 凹凸映射,多重纹理扩展: 这是一课高级教程,请确信你对基本知识已经非常了解了.这一课是基于第六课的代码的,它将建立一个非常酷的立体纹理效果. 这一课由Jens Schneider所写,它基本上是由第6课改写而来

NeHe OpenGL教程 第二十八课:贝塞尔曲面

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第二十八课:贝塞尔曲面 贝塞尔曲面: 这是一课关于数学运算的,没有别的内容了.来,有信心就看看它吧. 贝塞尔曲面 作者: David Nikdel ( [email protected] ) 这篇教程旨在介绍贝塞尔曲面,希望有比我更

NeHe OpenGL教程 第二十九课:Blt函数

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第二十九课:Blt函数 Blitter 函数: 类似于DirectDraw的blit函数,过时的技术,我们有实现了它.它非常的简单,就是把一块纹理贴到另一块纹理上. 这篇文章是有Andreas Lffler所写的,它写了一份原始的教

NeHe OpenGL教程 第二十五课:变形

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第二十五课:变形 变形和从文件中加载3D物体: 在这一课中,你将学会如何从文件加载3D模型,并且平滑的从一个模型变换为另一个模型. 欢迎来到这激动人心的一课,在这一课里,我们将介绍模型的变形.需要注意的是各个模型必须要有相同的顶点,

NeHe OpenGL教程 第六课:纹理映射

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第六课:纹理映射 纹理映射: 在这一课里,我将教会你如何把纹理映射到立方体的六个面. 学习 texture map 纹理映射(贴图)有很多好处.比方说您想让一颗导弹飞过屏幕.根据前几课的知识,我们最可行的办法可能是很多个多边形来构建

NeHe OpenGL教程 第十七课:2D图像文字

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第十七课:2D图像文字 2D图像文字: 在这一课中,你将学会如何使用四边形纹理贴图把文字显示在屏幕上.你将学会如何把256个不同的文字从一个256x256的纹理图像中分别提取出来,并为每一个文字创建一个显示列表,接着创建一个输出函数

NeHe OpenGL教程 第三课:颜色渲染

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. 第三课:颜色渲染 添加颜色: 作为第二课的扩展,我将叫你如何使用颜色.你将理解两种着色模式,在左图中,三角形用的是光滑着色,四边形用的是平面着色. 上一课中我教给您三角形和四边形的绘制方法.这一课我将教您给三角形和四边形添加2种不同类型的着色方法.使用F

NeHe OpenGL教程 第十课:3D世界

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第十课:3D世界 加载3D世界,并在其中漫游: 在这一课中,你将学会如何加载3D世界,并在3D世界中漫游.这一课使用第一课的代码,当然在课程说明中我只介绍改变了代码. 这一课是由Lionel Brits (βtelgeuse)所写的

NeHe OpenGL教程 第七课:光照和键盘

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第七课:光照和键盘 光照和键盘控制: 在这一课里,我们将添加光照和键盘控制,它让程序看起来更美观. 这一课我会教您如何使用三种不同的纹理滤波方式.教您如何使用键盘来移动场景中的对象,还会教您在OpenGL场景中应用简单的光照.这一课