• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

              C++博客 :: 首頁 :: 聯系 ::  :: 管理
              163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(48)

            我參與的團隊

            搜索

            •  

            積分與排名

            • 積分 - 400070
            • 排名 - 59

            最新評論

            閱讀排行榜

            評論排行榜

             這一課我會教您如何使用三種不同的紋理濾波方式。教您如何使用鍵盤來移動場景中的對象,還會教您在OpenGL場 景中應用簡單的光照。這一課包含了很多內容,如果您對前面的課程有疑問的話,先回頭復習一下。進入后面的代碼之前,很好的理解基礎知識十分重要。我們還是 在第一課的代碼上加以修改。跟以前不一樣的是,只要有任何大的改動,我都會寫出整段代碼。程序開始,我們先加上幾個新的變量。

              #include <windows.h>                    // Windows的頭文件
              #include <stdio.h>                     // 標準輸入/輸出庫的頭文件 (新增)
              #include <gl\\gl.h>                     // OpenGL32庫的頭文件
              #include <gl\\glu.h>                    // GLu32庫的頭文件
              #include <gl\\glaux.h>                   // GLaux庫的頭文件

              HGLRC hRC=NULL;                      // 永久著色描述表
              HDC hDC=NULL;                       // 私有GDI設備描述表
              HWND hWnd=NULL;                      // 保存我們的窗口句柄
              HINSTANCE hInstance;                    // 保存程序的實例

              bool keys[256];                      // 用于鍵盤例程的數組
              bool active=TRUE;                     // 窗口的活動標志,缺省為TRUE
              bool fullscreen=TRUE;                   // 全屏標志缺省設定成全屏模式

               下面幾行是新的。我們增加三個布爾變量。light變量跟蹤光照是否打開。變量lpfp用來存儲‘L’和‘F’鍵是否按下的狀態。后面我會解釋這些變量的重要性。現在,先放在一邊吧。

              BOOL light;                   ?    ?// 光源的開/關
              BOOL lp;                          // L鍵按下了么?
              BOOL fp;                          // F鍵按下了么?

               現在設置5個變量來控制繞x軸和y軸旋轉角度的步長,以及繞x軸和y軸的旋轉速度。另外還創建了一個z變量來控制進入屏幕深處的距離。

              GLfloat xrot;                       // X 旋轉
              GLfloat yrot;                       // Y 旋轉
              GLfloat xspeed;                      // X 旋轉速度
              GLfloat yspeed;                      // Y 旋轉速度

              GLfloat z=-5.0f;                      // 深入屏幕的距離

            接著設置用來創建光源的數組。我們將使用兩種不同的光。第一種稱為環境光。環境光來自于四面八方。所有場景中的對象都處于環境光的照射中。第二種類型的光 源叫做漫射光。漫射光由特定的光源產生,并在您的場景中的對象表面上產生反射。處于漫射光直接照射下的任何對象表面都變得很亮,而幾乎未被照射到的區域就 顯得要暗一些。這樣在我們所創建的木板箱的棱邊上就會產生的很不錯的陰影效果。
               創建光源的過程和顏色的創建完全一致。前三個參數分別是RGB三色分量,最后一個是alpha通道參數。
               因此,下面的代碼我們得到的是半亮(0.5f)的白色環境光。如果沒有環境光,未被漫射光照到的地方會變得十分黑暗。

              GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };    // 環境光參數 (新增)

               下一行代碼我們生成最亮的漫射光。所有的參數值都取成最大值1.0f。它將照在我們木板箱的前面,看起來挺好。

              GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };    // 漫射光參數 (新增)

            最后我們保存光源的位置。前三個參數和glTranslate中的一樣。依次分別是XYZ軸上的位移。由于我們想要光線直接照射在木箱的正面,所以XY軸 上的位移都是0.0f。第三個值是Z軸上的位移。為了保證光線總在木箱的前面,所以我們將光源的位置朝著觀察者(就是您哪。)挪出屏幕。我們通常將屏幕也 就是顯示器的屏幕玻璃所處的位置稱作Z軸的0.0f點。所以Z軸上的位移最后定為2.0f。假如您能夠看見光源的話,它就浮在您顯示器的前方。當然,如果 木箱不在顯示器的屏幕玻璃后面的話,您也無法看見箱子。最后一個參數取為1.0f。這將告訴OpenGL這里指定的坐標就是光源的位置,以后的教程中我會多加解釋。

              GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };    // 光源位置 ( 新增 )

              filter變 量跟蹤顯示時所采用的紋理類型。第一種紋理(texture 0)使用gl_nearest(不光滑)濾波方式構建。第二種紋理(texture 1)使用gl_linear(線性濾波)方式,離屏幕越近的圖像看起來就越光滑。第三種紋理 (texture 2)使用mipmapped濾波方式,這將創建一個外觀十分優秀的紋理。根據我們的使用類型,filter變量的值分別等于0,1或2。下面我們從第一種紋理開始。
               GLuint texture[3]為三種不同紋理分配儲存空間。它們分別位于在texture[0]、texture[1]、texture[2]中。

              GLuint filter;                       // 濾波類型
              GLuint texture[3];                     // 3種紋理的儲存空間
              LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);   // WndProc定義

               現在載入一個位圖,并用它創建三種不同的紋理。這一課使用glaux輔助庫來載入位圖,因此在編譯時您應該確認是否包含了glaux庫。我知道Delphi和VC++都包含了glaux庫,但別的語言不能保證都有。(譯者glaux是OpenGL輔助庫,根據OpenGL的跨平臺特性,所有平臺上的代碼都應通用。但輔助庫不是正式的OpenGL標準庫,沒有出現在所有的平臺上。但正好在Win32平臺上可用。呵呵,BCB當然也沒問題了。)這里我只對新增的代碼做注解。如果您對某行代碼有疑問的話,請查看教程六。那一課很詳細的解釋了載入、創建紋理的內容。
               在上一段代碼后面及ReSizeGLScene()之前的位置,我們增加了下面的代碼。這和第六課中載入位圖的代碼幾乎相同。

              AUX_RGBImageRec *LoadBMP(char *Filename)          // 載入位圖
              {
                   FILE *File=NULL;
                              // 文件句柄
                  if (!Filename)                   // 確認文件名已初始化
                  {
                       return NULL;
                            // 沒有返回 NULL
                  }
                   File=fopen(Filename,"r");
                         // 檢查文件是否存在
                  if (File)                     // 存在么?
                  {
                       fclose(File); 
                          // 關閉文件句柄
                      return auxDIBImageLoad(Filename);     // 載入位圖并返回一個指針
                  }
                  return NULL;                    // 載入失敗返回 NULL
              }

               這段代碼調用前面的代碼載入位圖,并將其轉換成3個紋理。Status變量跟蹤紋理是否已載入并被創建了。

              int LoadGLTextures()                    // 載入位圖并轉換成紋理
              {
                   int Status=FALSE;
                              // Status 指示器
                  AUX_RGBImageRec *TextureImage[1];         // 創建紋理的存儲空間
                  memset(TextureImage,0,sizeof(void *)*1);      // 將指針設為 NULL

            現在載入位圖并轉換成紋理。TextureImage[0]=LoadBMP("Data/Crate.bmp")調用我們的LoadBMP()函數。 Data目錄下的“Crate.bmp”將被載入。如果一切正常,圖像數據將存放在TextureImage[0]。Status變量被設為TRUE,我 們將開始創建紋理。

                  // 載入位圖,檢查有錯,或位圖不存在的話退出。
                  if (TextureImage[0]=LoadBMP("Data/Crate.bmp"))
                   {
                       Status=TRUE;
                            // Status 設為 TRUE

               現在我們已經將圖像數據載入TextureImage[0]。我們將用它來創建3個紋理。下面的行告訴OpenGL我們要創建三個紋理,它們將存放在texture[0]、texture[1]、texture[2] 中。

                      glGenTextures(3, &texture[0]);       // 創建紋理

            第六課中我們使用了線性濾波的紋理貼圖。這需要機器有相當高的處理能力,但它們看起來很不錯。這一課中,我們接著要創建的第一種紋理使用 GL_NEAREST方式。從原理上講,這種方式沒有真正進行濾波。它只占用很小的處理能力,看起來也很差。唯一的好處是這樣我們的工程在很快和很慢的機 器上都可以正常運行。
            您會注意到我們在MIN和MAG時都采用了GL_NEAREST,你可以混合使用GL_NEAREST和GL_LINEAR。紋理看起來效果會好些,但我 們更關心速度,所以全采用低質量貼圖。MIN_FILTER在圖像繪制時小于貼圖的原始尺寸時采用。MAG_FILTER在圖像繪制時大于貼圖的原始尺寸 時采用。

                      // 創建 Nearest 濾波貼圖
                      glBindTexture(GL_TEXTURE_2D, texture[0]);
                       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[0]->sizeX, TextureImage[0]->sizeY,
                           0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);

               下個紋理與第六課的相同,線性濾波。唯一的不同是這次放在了texture[1]中。因為這是第二個紋理。如果放在texture[0]中的話,他將覆蓋前面創建的GL_NEAREST紋理。

                      // 創建線性濾波紋理
                      glBindTexture(GL_TEXTURE_2D, texture[1]);
                        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[0]->sizeX, TextureImage[0]->sizeY,
                           0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);

            下面是創建紋理的新方法:Mip-mapping(紋理細化)。您可能會注意到當圖像在屏幕上變得很小的時候,很多細節將會丟失。剛才還很不錯的圖案變得 很難看。當您告訴OpenGL創建一個mipmapped的紋理后,OpenGL將嘗試創建不同尺寸的高質量紋理。當您向屏幕繪制一個mipmapped 紋理的時候,OpenGL將選擇它已經創建的外觀最佳的紋理(帶有更多細節)來繪制,而不僅僅是縮放原先的圖像(這將導致細節丟失)。
            我曾經說過有辦法可以繞過OpenGL對紋理寬度和高度所加的限制 — 64、128、256,等等。辦法就是 gluBuild2DMipmaps。據我的發現,您可以使用任意的位圖來創建紋理。OpenGL將自動將它縮放到正常的大小。因為是第三個紋理,我們將 它存到texture[2]。這樣本課中的三個紋理全都創建好了。

                      // 創建 MipMapped 紋理
                      glBindTexture(GL_TEXTURE_2D, texture[2]);
                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
            // (新增)

            下面一行生成mipmapped紋理。我們使用三種顏色(紅,綠,藍)來生成一個2D紋理。TextureImage[0]->sizeX 是位圖寬度,extureImage[0]->sizeY是位圖高度,GL_RGB意味著我們依次使用RGB色彩。 GL_UNSIGNED_BYTE意味著紋理數據的單位是字節。TextureImage[0]->data指向我們創建紋理所用的位圖。

                      gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
                           TextureImage[0]->sizeX, TextureImage[0]->sizeY,
                           GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
              // ( 新增 )
                  }

               現在釋放用來存放位圖數據的內存。我們先查看位圖數據是否存放在TextureImage[0]中,如果有,刪掉。然后釋放位圖結構以確保內存被釋放。

                  if (TextureImage[0])                // 紋理是否存在
                  {
                       if (TextureImage[0]->data)
                     // 紋理圖像是否存在
                      {
                           free(TextureImage[0]->data);
                // 釋放紋理圖像占用的內存
                      }
                       free(TextureImage[0]);
                       // 釋放圖像結構
                  }

               最后我們返回status變量。如果一切OK,status變量的值為TRUE。否則為FALSE。

                  return Status;                  // 返回 Status 變量
              }

               接著應該載入紋理并初始化OpenGL設置了。InitGL函數的第一行使用上面的代碼載入紋理。創建紋理之后,我們調用glEnable(GL_TEXTURE_2D)啟用2D紋理映射。陰影模式設為平滑陰影(smooth shading)。背景色設為黑色,我們啟用深度測試,然后我們啟用優化透視計算。

              int InitGL(GLvoid)                    // 此處開始對OpenGL進行所有設置
              {
                   if (!LoadGLTextures())
                          // 跳轉到紋理載入例程
                  {
                       return FALSE;
                           // 如果不能載入紋理返回 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);// 高度優化的透視投影計算

               現在開始設置光源。下面下面一行設置環境光的發光量,光源light1開始發光。這一課的開始處我們我們將環境光的發光量存放在LightAmbient數組中。現在我們就使用此數組(半亮度環境光)。

                  glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);  // 設置環境光

               接下來我們設置漫射光的發光量。它存放在LightDiffuse數組中(全亮度白光)。

                  glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);  // 設置漫射光

               然后設置光源的位置。位置存放在 LightPosition 數組中(正好位于木箱前面的中心,X-0.0f,Y-0.0f,Z方向移向觀察者2個單位[位于屏幕外面])。

                  glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // 光源位置

               最后,我們啟用一號光源。我們還沒有啟用GL_LIGHTING,所以您看不見任何光線。記住:只對光源進行設置、定位、甚至啟用,光源都不會工作。除非我們啟用GL_LIGHTING。

                  glEnable(GL_LIGHT1);               // 啟用一號光源
                  return TRUE;                   // 初始化 OK
              }

               下一段代碼繪制貼圖立方體。我只對新增的代碼進行注解。如果您對沒有注解的代碼有疑問,回頭看看第六課。

              int DrawGLScene(GLvoid)                  // 從這里開始進行所有的繪制
              {
                   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            // 清除屏幕和深度緩存
                  glLoadIdentity();                 // 重置當前的模型觀察矩陣

               下三行代碼放置并旋轉貼圖立方體。glTranslatef(0.0f,0.0f,z)將立方體沿著Z軸移動Z單位。glRotatef(xrot,1.0f,0.0f,0.0f)將立方體繞X軸旋轉xrot。glRotatef(yrot,0.0f,1.0f,0.0f)將立方體繞Y軸旋轉yrot

                  glTranslatef(0.0f,0.0f,z);            // 移入/移出屏幕 z 個單位

                  glRotatef(xrot,1.0f,0.0f,0.0f);          // 繞X軸旋轉
                  glRotatef(yrot,0.0f,1.0f,0.0f);          // 繞Y軸旋轉

            下一行與我們在第六課中的類似。有所不同的是,這次我們綁定的紋理是texture[filter],而不是上一課中的texture[0]。任何時候, 我們按下F鍵,filter的值就會增加。如果這個數值大于2,變量filter 將被重置為0。程序初始時,變量filter的值也將設為0。使用變量filter我們就可以選擇三種紋理中的任意一種。

                  glBindTexture(GL_TEXTURE_2D, texture[filter]);  // 選擇由filter決定的紋理
                  glBegin(GL_QUADS);                // 開始繪制四邊形

            glNormal3f是這一課的新東西。Normal就是法線的意思,所謂法線是指經過面(多邊形)上的一點且垂直于這個面(多邊形)的直線。使用光源的 時候必須指定一條法線。法線告訴OpenGL這個多邊形的朝向,并指明多邊形的正面和背面。如果沒有指定法線,什么怪事情都可能發生:不該照亮的面被照亮 了,多邊形的背面也被照亮....。對了,法線應該指向多邊形的外側。
            看著木箱的前面您會注意到法線與Z軸正向同向。這意味著法線正指向觀察者-您自己。這正是我們所希望的。對于木箱的背面,也正如我們所要的,法線背對著觀 察者。如果立方體沿著X或Y軸轉個180度的話,前側面的法線仍然朝著觀察者,背面的法線也還是背對著觀察者。換句話說,不管是哪個面,只要它朝著觀察者 這個面的法線就指向觀察者。由于光源緊鄰觀察者,任何時候法線對著觀察者時,這個面就會被照亮。并且法線越朝著光源,就顯得越亮一些。如果您把觀察點放到 立方體內部,你就會法線里面一片漆黑。因為法線是向外指的。如果立方體內部沒有光源的話,當然是一片漆黑。

                      // 前側面
                      glNormal3f( 0.0f, 0.0f, 1.0f);      // 法線指向觀察者
                      glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);// Point 1 (Front)
                      glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);// Point 2 (Front)
                      glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Point 3 (Front)
                      glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Point 4 (Front)

                      // 后側面
                      glNormal3f( 0.0f, 0.0f,-1.0f);      // 法線背向觀察者
                      glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);// Point 1 (Back)
                      glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Point 2 (Back)
                      glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Point 3 (Back)
                      glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);// Point 4 (Back)

                      // 頂面
                      glNormal3f( 0.0f, 1.0f, 0.0f);     // 法線向上
                      glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);// Point 1 (Top)
                      glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Point 2 (Top)
                      glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Point 3 (Top)
                      glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);// Point 4 (Top)

                      // 底面
                      glNormal3f( 0.0f,-1.0f, 0.0f);     // 法線朝下
                      glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);// Point 1 (Bottom)
                      glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);// Point 2 (Bottom)
                      glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Point 3 (Bottom)
                      glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Point 4 (Bottom)

                      // 右側面
                      glNormal3f( 1.0f, 0.0f, 0.0f);    // 法線朝右
                      glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);// Point 1 (Right)
                      glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Point 2 (Right)
                      glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Point 3 (Right)
                      glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Point 4 (Right)

                      // 左側面
                      glNormal3f(-1.0f, 0.0f, 0.0f);    // 法線朝左
                      glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);// Point 1 (Left)
                      glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Point 2 (Left)
                      glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Point 3 (Left)
                      glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Point 4 (Left)
                  glEnd();     ?            ?// 四邊形繪制結束

               下兩行代碼將xotyrot的旋轉值分別增加xspeedyspeed個單位。xspeedyspeed的值越大,立方體轉得就越快。

                  xrot+=xspeed;                // xrot 增加 xspeed 單位
                  yrot+=yspeed;                // yrot 增加 yspeed 單位
                  return TRUE;
              }

            現在轉入WinMain()主函數。我們將在這里增加開關光源、旋轉木箱、切換過濾方式以及將木箱移近移遠的控制代碼。在接近WinMain()函數結束 的地方你會看到SwapBuffers(hDC)這行代碼。然后就在這一行后面添加如下的代碼。代碼將檢查L鍵是否按下過。如果L鍵已按下,但lp的值不是false的話,意味著L鍵還沒有松開,這時什么都不會發生。

                                  SwapBuffers(hDC);  // 交換緩存 (雙緩存)
                                  if (keys[\’L\’] && !lp)// L 鍵已按下并且松開了?
                                  {

               如果lp的值是false的話,意味著L鍵還沒按下,或者已經松開了,接著lp將被設為TRUE。同時檢查這兩個條件的原因是為了防止L鍵被按住后,這段代碼被反復執行,并導致窗體不停閃爍。
              lp設為true之后,計算機就知道L鍵按過了,我們則據此可以切換光源的開/關:布爾變量light控制光源的開關。
                                       lp=TRUE;   // lp 設為 TRUE
                                       light=!light;// 切換光源的 TRUE/FALSE

               下面幾行來檢查光源是否應該打開,并根據light變量的值。

                                       if (!light) // 如果沒有光源
                                       {
                                            glDisable(GL_LIGHTING);
            //禁用光源
                                       }
                                        else
                 // Otherwise
                                       {
                                            glEnable(GL_LIGHTING);
            //啟用光源
                                       }
                                    }

               下面的代碼查看是否松開了“L”鍵。如果松開,變量lp將設為false。這意味著“L”鍵沒有按下。如果不作此檢查,光源第一次打開之后,就無法再關掉了。計算機會以為“L”鍵一直按著呢。

                                  if (!keys[\’L\’])   // L鍵松開了么?
                                  {
                                        lp=FALSE;
              // 若是,則將lp設為FALSE
                                  }

            然后對“F”鍵作相似的檢查。如果有按下“F”?⑶搖癋”鍵沒有處于按著的狀態或者它就從沒有按下過,將變量fp設為true。這意味著這個鍵正被按著 呢。接著將filter變量加一。如果filter變量大于2(因為這里我們的使用的數組是texture[3],大于2的紋理不存在),我們重置 filter變量為0。

                                  if (keys[\’F\’] && !fp)// F鍵按下了么?
                                  {
                                        fp=TRUE;
               // fp 設為 TRUE
                                      filter+=1;  // filter的值加一
                                      if (filter>2)// 大于2了么?
                                      {
                                            filter=0;
             // 若是重置為0
                                      }
                                   }
                                   if (!keys[\’F\’])
               // F鍵放開了么?
                                  {
                                        fp=FALSE;
              // 若是fp設為FALSE
                                  }

               這四行檢查是否按下了PageUp鍵。若是的話,減少z變量的值。這樣DrawGLScene函數中包含的glTranslatef(0.0f,0.0f,z)調用將使木箱離觀察者更遠一點。

                                  if (keys[VK_PRIOR]) // PageUp按下了?
                                  {
                                        z-=0.02f;
             // 若按下,將木箱移向屏幕內部。
                                  }

               接著四行檢查PageDown鍵是否按下,若是的話,增加z變量的值。這樣DrawGLScene函數中包含的glTranslatef(0.0f,0.0f,z)調用將使木箱向著觀察者移近一點。

                                  if (keys[VK_NEXT])  // PageDown按下了么?
                                  {
                                        z+=0.02f;
              //若按下的話,將木箱移向觀察者。
                                  }

               現在檢查方向鍵。按下左右方向鍵xspeed相應減少或增加。按下上下方向鍵yspeed相應減少或增加。記住在以后的教程中如果xspeedyspeed的值增加的話,立方體就轉的更快。如果一直按著某個方向鍵,立方體會在那個方向上轉的越快。

                                  if (keys[VK_UP])    // Up方向鍵按下了么?
                                  {
                                        xspeed-=0.01f;
            // 若是,減少xspeed
                                  }
                                   if (keys[VK_DOWN])
               // Down方向鍵按下了么?
                                  {
                                        xspeed+=0.01f;
            // 若是,增加xspeed
                                  }
                                   if (keys[VK_RIGHT]) 
             // Right方向鍵按下了么?
                                  {
                                        yspeed+=0.01f;
            // 若是,增加yspeed
                                  }
                                   if (keys[VK_LEFT])
               // Left方向鍵按下了么?
                                  {
                                        yspeed-=0.01f;
            // 若是, 減少yspeed
                                  }

               像前幾課一樣,我們最后還需要更正窗體的標題。

                                  if (keys[VK_F1])        // F1鍵按下了么?
                                  {
                                        keys[VK_F1]=FALSE;

                                      KillGLWindow();    // 銷毀當前的窗口
                                      fullscreen=!fullscreen;// 切換 全屏/窗口 模式
                                       // 重建 OpenGL 窗口(修改)
                                      if (!CreateGLWindow("NeHe\’s Textures, Lighting & Keyboard Tutorial",640,480,16,fullscreen))
                                       {
                                            return 0;
            // 如果窗口未能創建,程序退出
                                      }
                                   }

                               }
                           }
                        }

                  // 關閉
                  KillGLWindow();                  // 銷毀窗口
                  return (msg.wParam);                // 退出程序
              }

            posted on 2007-12-11 18:10 sdfasdf 閱讀(699) 評論(0)  編輯 收藏 引用 所屬分類: OPENGL
            久久久久女人精品毛片| 久久九九兔免费精品6| 一本色道久久88精品综合 | 2021最新久久久视精品爱| 青青草国产精品久久久久| 国产精品免费看久久久| 青青热久久综合网伊人| 亚洲欧洲久久av| 日韩精品久久无码中文字幕 | 99麻豆久久久国产精品免费| 97r久久精品国产99国产精| 93精91精品国产综合久久香蕉| 欧美大战日韩91综合一区婷婷久久青草 | 久久国产影院| 日产精品久久久久久久| 国产高潮国产高潮久久久91| 偷窥少妇久久久久久久久| 久久精品国产亚洲沈樵| 国产69精品久久久久APP下载| 97久久久久人妻精品专区 | 亚洲中文久久精品无码ww16| 久久精品国产99国产精品澳门| 亚洲精品tv久久久久| 青青草原综合久久| 久久午夜伦鲁片免费无码| 久久久网中文字幕| 成人国内精品久久久久一区| 久久人妻AV中文字幕| 久久99亚洲综合精品首页| 精品免费tv久久久久久久| 午夜精品久久久久久99热| 一级a性色生活片久久无| 99久久伊人精品综合观看| 久久超乳爆乳中文字幕| 精产国品久久一二三产区区别| 久久97久久97精品免视看秋霞| 久久99精品久久久久久| 久久久久无码精品国产| 国产成人久久精品一区二区三区 | 久久久久亚洲av无码专区导航| 久久影视国产亚洲|