NeHe OpenGL教程 (二十三)

來源:互聯網
上載者:User

第23課
  
  球面映射:

這一個將教會你如何把環境紋理包裹在你的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;
    }

  
 我們成功了!現在你可以使用環境映射紋理做一些非常棒的特效了。我想做一個立方體環境映射的例子,但我現在的顯卡不支援這種特效,所以只有等到以後了。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.