转自【翻译】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

 
 

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

  1. NeHe OpenGL教程 第二十课:蒙板

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  2. NeHe OpenGL教程 第十三课:图像字体

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  3. NeHe OpenGL教程 第二十七课:影子

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. NeHe OpenGL教程 第二十一课:线的游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

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

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

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

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. NeHe OpenGL教程 第二十六课:反射

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

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

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

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

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

随机推荐

  1. HDU 2083 简易版之最短距离 --- 水题

    HDU 2083 简易版之最短距离 /* HDU 2083 简易版之最短距离 */ #include <cstdio> #include <algorithm> using n ...

  2. 后台向前台传递entity的list然后构筑combobox的方法(easyui)

    遇问题,莫着急,深呼吸. 后台写法:JsonUtil.toJson(new ArrayList<Entity>());此处jsonUtil是已封装的方法,即将entity的list转为js ...

  3. 磁盘检验[转自vbird]

    磁盘检验 由于系统在运行时谁也说不准啥时硬件或者是电源会有问题,所以『死机』可能是难免的情况(不管是硬件还是软件). 现在我们知道文件系统运行时会有硬盘与内存数据异步的状况发生,因此莫名其妙的死机非常 ...

  4. Android sdk 镜像服务器资源

    大连东软信息学院镜像服务器地址:- http://mirrors.neusoft.edu.cn 端口:80北京化工大学镜像服务器地址:- IPv4: http://ubuntu.buct.edu.cn ...

  5. C#联调C++项目

    很多人在编写C#代码时,经常要调用C++代码,有时我们通常用打日志来查看运行状况,这当然可以,不过这样挺不方便,一遍遍的跑代码,一遍遍的看日志,感觉如果可以直接把断点打入C++的代码就好了,其实是可以 ...

  6. 从开发的角度比较 ASP.NET Web 服务与 WCF

    Windows Communication Foundation (WCF) 具有一个 ASP.NET 兼容模式选项,用户使用此选项可以对 WCF 应用程序进行编程和配置,使其像 ASP.NET We ...

  7. 检测php网站是否已经被攻破

    from :http://www.gregfreeman.org/2013/how-to-tell-if-your-php-site-has-been-compromised/ http://drop ...

  8. 未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。

    64位系统 IIS7.0配置.net网站时报错:未能加载文件或程序集"XXX"或它的某一个依赖项.试图加载格式不正确的程序. 背景: 在64位的操作系统中, IIS7.0配置.ne ...

  9. Java_数组

    一.java数组 1.数组定义:数组就是形象于一个容器(容器即可理解为:装东西的容器) 2.数组特征:数据是连续的,分配大小固定,数组中数据类型完全一致 创建规则:int[] arr = new in ...

  10. jQuery Mobile_页面事件

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...