• <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++博客 :: 首頁(yè) :: 聯(lián)系 ::  :: 管理
              163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(48)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            積分與排名

            • 積分 - 398977
            • 排名 - 59

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

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

              #include <windows.h>                    // Windows的頭文件
              #include <stdio.h>                     // 標(biāo)準(zhǔn)輸入/輸出庫(kù)的頭文件 (新增)
              #include <gl\\gl.h>                     // OpenGL32庫(kù)的頭文件
              #include <gl\\glu.h>                    // GLu32庫(kù)的頭文件
              #include <gl\\glaux.h>                   // GLaux庫(kù)的頭文件

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

              bool keys[256];                      // 用于鍵盤例程的數(shù)組
              bool active=TRUE;                     // 窗口的活動(dòng)標(biāo)志,缺省為TRUE
              bool fullscreen=TRUE;                   // 全屏標(biāo)志缺省設(shè)定成全屏模式

               下面幾行是新的。我們?cè)黾尤齻€(gè)布爾變量。light變量跟蹤光照是否打開。變量lpfp用來存儲(chǔ)‘L’和‘F’鍵是否按下的狀態(tài)。后面我會(huì)解釋這些變量的重要性。現(xiàn)在,先放在一邊吧。

              BOOL light;                   ?    ?// 光源的開/關(guān)
              BOOL lp;                          // L鍵按下了么?
              BOOL fp;                          // F鍵按下了么?

               現(xiàn)在設(shè)置5個(gè)變量來控制繞x軸和y軸旋轉(zhuǎn)角度的步長(zhǎng),以及繞x軸和y軸的旋轉(zhuǎn)速度。另外還創(chuàng)建了一個(gè)z變量來控制進(jìn)入屏幕深處的距離。

              GLfloat xrot;                       // X 旋轉(zhuǎn)
              GLfloat yrot;                       // Y 旋轉(zhuǎn)
              GLfloat xspeed;                      // X 旋轉(zhuǎn)速度
              GLfloat yspeed;                      // Y 旋轉(zhuǎn)速度

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

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

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

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

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

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

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

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

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

               現(xiàn)在載入一個(gè)位圖,并用它創(chuàng)建三種不同的紋理。這一課使用glaux輔助庫(kù)來載入位圖,因此在編譯時(shí)您應(yīng)該確認(rèn)是否包含了glaux庫(kù)。我知道Delphi和VC++都包含了glaux庫(kù),但別的語言不能保證都有。(譯者glaux是OpenGL輔助庫(kù),根據(jù)OpenGL的跨平臺(tái)特性,所有平臺(tái)上的代碼都應(yīng)通用。但輔助庫(kù)不是正式的OpenGL標(biāo)準(zhǔn)庫(kù),沒有出現(xiàn)在所有的平臺(tái)上。但正好在Win32平臺(tái)上可用。呵呵,BCB當(dāng)然也沒問題了。)這里我只對(duì)新增的代碼做注解。如果您對(duì)某行代碼有疑問的話,請(qǐng)查看教程六。那一課很詳細(xì)的解釋了載入、創(chuàng)建紋理的內(nèi)容。
               在上一段代碼后面及ReSizeGLScene()之前的位置,我們?cè)黾恿讼旅娴拇a。這和第六課中載入位圖的代碼幾乎相同。

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

               這段代碼調(diào)用前面的代碼載入位圖,并將其轉(zhuǎn)換成3個(gè)紋理。Status變量跟蹤紋理是否已載入并被創(chuàng)建了。

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

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

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

               現(xiàn)在我們已經(jīng)將圖像數(shù)據(jù)載入TextureImage[0]。我們將用它來創(chuàng)建3個(gè)紋理。下面的行告訴OpenGL我們要?jiǎng)?chuàng)建三個(gè)紋理,它們將存放在texture[0]、texture[1]、texture[2] 中。

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

            第六課中我們使用了線性濾波的紋理貼圖。這需要機(jī)器有相當(dāng)高的處理能力,但它們看起來很不錯(cuò)。這一課中,我們接著要?jiǎng)?chuàng)建的第一種紋理使用 GL_NEAREST方式。從原理上講,這種方式?jīng)]有真正進(jìn)行濾波。它只占用很小的處理能力,看起來也很差。唯一的好處是這樣我們的工程在很快和很慢的機(jī) 器上都可以正常運(yùn)行。
            您會(huì)注意到我們?cè)贛IN和MAG時(shí)都采用了GL_NEAREST,你可以混合使用GL_NEAREST和GL_LINEAR。紋理看起來效果會(huì)好些,但我 們更關(guān)心速度,所以全采用低質(zhì)量貼圖。MIN_FILTER在圖像繪制時(shí)小于貼圖的原始尺寸時(shí)采用。MAG_FILTER在圖像繪制時(shí)大于貼圖的原始尺寸 時(shí)采用。

                      // 創(chuàng)建 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);

               下個(gè)紋理與第六課的相同,線性濾波。唯一的不同是這次放在了texture[1]中。因?yàn)檫@是第二個(gè)紋理。如果放在texture[0]中的話,他將覆蓋前面創(chuàng)建的GL_NEAREST紋理。

                      // 創(chuàng)建線性濾波紋理
                      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);

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

                      // 創(chuàng)建 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紋理。我們使用三種顏色(紅,綠,藍(lán))來生成一個(gè)2D紋理。TextureImage[0]->sizeX 是位圖寬度,extureImage[0]->sizeY是位圖高度,GL_RGB意味著我們依次使用RGB色彩。 GL_UNSIGNED_BYTE意味著紋理數(shù)據(jù)的單位是字節(jié)。TextureImage[0]->data指向我們創(chuàng)建紋理所用的位圖。

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

               現(xiàn)在釋放用來存放位圖數(shù)據(jù)的內(nèi)存。我們先查看位圖數(shù)據(jù)是否存放在TextureImage[0]中,如果有,刪掉。然后釋放位圖結(jié)構(gòu)以確保內(nèi)存被釋放。

                  if (TextureImage[0])                // 紋理是否存在
                  {
                       if (TextureImage[0]->data)
                     // 紋理圖像是否存在
                      {
                           free(TextureImage[0]->data);
                // 釋放紋理圖像占用的內(nèi)存
                      }
                       free(TextureImage[0]);
                       // 釋放圖像結(jié)構(gòu)
                  }

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

                  return Status;                  // 返回 Status 變量
              }

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

              int InitGL(GLvoid)                    // 此處開始對(duì)OpenGL進(jìn)行所有設(shè)置
              {
                   if (!LoadGLTextures())
                          // 跳轉(zhuǎn)到紋理載入例程
                  {
                       return FALSE;
                           // 如果不能載入紋理返回 FALSE
                  }

                  glEnable(GL_TEXTURE_2D);             // 啟用紋理映射
                  glShadeModel(GL_SMOOTH);             // 啟用陰影平滑
                  glClearColor(0.0f, 0.0f, 0.0f, 0.5f);       // 黑色背景
                  glClearDepth(1.0f);                // 深度緩存設(shè)置
                  glEnable(GL_DEPTH_TEST);             // 啟用深度測(cè)試
                  glDepthFunc(GL_LEQUAL);              // 所作的深度測(cè)試類型
                  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// 高度優(yōu)化的透視投影計(jì)算

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

                  glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);  // 設(shè)置環(huán)境光

               接下來我們?cè)O(shè)置漫射光的發(fā)光量。它存放在LightDiffuse數(shù)組中(全亮度白光)。

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

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

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

               最后,我們啟用一號(hào)光源。我們還沒有啟用GL_LIGHTING,所以您看不見任何光線。記住:只對(duì)光源進(jìn)行設(shè)置、定位、甚至啟用,光源都不會(huì)工作。除非我們啟用GL_LIGHTING。

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

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

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

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

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

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

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

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

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

                      // 前側(cè)面
                      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)

                      // 后側(cè)面
                      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)

                      // 右側(cè)面
                      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)

                      // 左側(cè)面
                      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();     ?            ?// 四邊形繪制結(jié)束

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

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

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

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

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

               下面幾行來檢查光源是否應(yīng)該打開,并根據(jù)light變量的值。

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

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

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

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

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

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

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

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

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

               現(xiàn)在檢查方向鍵。按下左右方向鍵xspeed相應(yīng)減少或增加。按下上下方向鍵yspeed相應(yīng)減少或增加。記住在以后的教程中如果xspeedyspeed的值增加的話,立方體就轉(zhuǎn)的更快。如果一直按著某個(gè)方向鍵,立方體會(huì)在那個(gè)方向上轉(zhuǎn)的越快。

                                  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
                                  }

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

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

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

                               }
                           }
                        }

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

            posted on 2007-12-11 18:10 sdfasdf 閱讀(697) 評(píng)論(0)  編輯 收藏 引用 所屬分類: OPENGL
            久久精品aⅴ无码中文字字幕不卡 久久精品成人欧美大片 | 久久青青草原综合伊人| 一级做a爱片久久毛片| 久久久久亚洲AV片无码下载蜜桃 | 久久国产V一级毛多内射| 亚洲成色WWW久久网站| 欧美无乱码久久久免费午夜一区二区三区中文字幕| 狠狠色丁香婷婷久久综合| 久久国产香蕉一区精品| 久久被窝电影亚洲爽爽爽| 婷婷久久久亚洲欧洲日产国码AV| 精品综合久久久久久888蜜芽| 亚洲va久久久久| 久久亚洲sm情趣捆绑调教| 7777久久亚洲中文字幕| 97精品久久天干天天天按摩| 欧美久久一区二区三区| 久久综合九色综合精品| 亚洲国产欧洲综合997久久| 久久国产精品免费| 久久99国产精品久久99| 久久久久久久女国产乱让韩| 久久久久亚洲AV综合波多野结衣 | 亚洲国产精品无码久久九九| 久久精品视屏| 超级碰久久免费公开视频| 精品久久久无码中文字幕| 久久久精品国产sm调教网站| 久久91精品国产91久久小草| 久久人妻无码中文字幕| 亚洲国产天堂久久综合| 国产精品xxxx国产喷水亚洲国产精品无码久久一区| 中文精品久久久久人妻不卡| 久久精品亚洲一区二区三区浴池 | 国产精品无码久久四虎| 久久精品国产99久久无毒不卡| 囯产精品久久久久久久久蜜桃 | 久久精品一区二区三区不卡| 久久精品亚洲中文字幕无码麻豆| 亚洲精品美女久久777777| 无遮挡粉嫩小泬久久久久久久|