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

            常用鏈接

            留言簿(48)

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

            搜索

            •  

            積分與排名

            • 積分 - 400065
            • 排名 - 59

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            學(xué)習(xí)Texture Map紋理映射(貼圖)有很多好處。比方說您想讓一顆導(dǎo)彈飛過屏幕。根據(jù)前幾課的知識(shí),我們最可行的辦法可能是很多個(gè)多邊形來構(gòu)建導(dǎo)彈的輪廓并加上有趣的顏色。使用紋理映射,您可以使用真實(shí)的導(dǎo)彈圖像并讓它飛過屏幕。您覺得哪個(gè)更好看?照片還是一大堆三角形和四邊形?使用紋理映射的好處還不止是更好看,而且您的程序運(yùn)行會(huì)更快。導(dǎo)彈貼圖可能只是一個(gè)飛過窗口的四邊形。一個(gè)由多邊形構(gòu)建而來的導(dǎo)彈卻很可能包括成百上千的多邊形。很顯然,貼圖極大的節(jié)省了CPU時(shí)間。
               現(xiàn)在我們?cè)诘谝徽n的代碼開始處增加五行新代碼。新增的第一行是#include <stdio.h>。它允許我們對(duì)文件進(jìn)行操作,為了在后面的代碼中使用fopen(),我們?cè)黾恿诉@一行。然后我們?cè)黾恿巳齻€(gè)新的浮點(diǎn)變量...xrotyrotzrot。這些變量用來使立方體繞X、Y、Z軸旋轉(zhuǎn)。最后一行GLuint texture[1]為一個(gè)紋理分配存儲(chǔ)空間。如果您需要不止一個(gè)的紋理,應(yīng)該將數(shù)字1改成您所需要的數(shù)字。

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

              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è)定成全屏模式

              GLfloat xrot;                       // X 旋轉(zhuǎn)量 (新增)
              GLfloat yrot;                       // Y 旋轉(zhuǎn)量 (新增)
              GLfloat zrot;                       // Z 旋轉(zhuǎn)量 (新增)

              GLuint texture[1];                     // 存儲(chǔ)一個(gè)紋理 (新增)

              LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);   // WndProc的定義

            緊跟上面的代碼在ReSizeGLScene()之前,我們?cè)黾恿讼旅孢@一段代碼。這段代碼用來加載位圖文件。如果文件不存在,返回NULL告知程序無法 加載位圖。在我開始解釋這段代碼之前,關(guān)于用作紋理的圖像我想有幾點(diǎn)十分重要,并且您必須明白。此圖像的寬和高必須是2的n次方;寬度和高度最小必須是 64象素;并且出于兼容性的原因,圖像的寬度和高度不應(yīng)超過256象素。如果您的原始素材的寬度和高度不是64,128,256象素的話,使用圖像處理軟 件重新改變圖像的大小。可以肯定有辦法能繞過這些限制,但現(xiàn)在我們只需要用標(biāo)準(zhǔn)的紋理尺寸。
               首先,我們創(chuàng)建一個(gè)文件句柄。句柄是個(gè)用來鑒別資源的數(shù)值,它使程序能夠訪問此資源。我們開始先將句柄設(shè)為NULL 。

              AUX_RGBImageRec *LoadBMP(char *Filename)          // 載入位圖圖象
              {
                   FILE *File=NULL;
                              // 文件句柄

               接下來檢查文件名是否已提供。因?yàn)長(zhǎng)oadBMP()可以無參數(shù)調(diào)用,所以我們不得不檢查一下。您可不想什么都沒載入吧......。

                  if (!Filename)                   // 確保文件名已提供。
                  {
                      return NULL;               // 如果沒提供,返回 NULL
                  }

               接著檢查文件是否存在。下面這一行嘗試打開文件。

                  File=fopen(Filename,"r");              // 嘗試打開文件

               如果我們能打開文件的話,很顯然文件是存在的。使用fclose(File) 關(guān)閉文件。auxDIBImageLoad(Filename) 讀取圖象數(shù)據(jù)并將其返回。

                  if (File)                      // 文件存在么?
                  {
                     fclose(File);
                             // 關(guān)閉句柄
                    return auxDIBImageLoad(Filename);       // 載入位圖并返回指針
                  }

               如果我們不能打開文件,我們將返回NULL。這意味著文件無法載入。程序在后面將檢查文件是否已載入。如果沒有,我們將退出程序并彈出錯(cuò)誤消息。

                  return NULL;                    // 如果載入失敗,返回 NULL
              }

               下一部分代碼載入位圖(調(diào)用上面的代碼)并轉(zhuǎn)換成紋理。

              int LoadGLTextures()                  // 載入位圖(調(diào)用上面的代碼)并轉(zhuǎn)換成紋理
              {

               然后設(shè)置一個(gè)叫做Status的變量。我們使用它來跟蹤是否能夠載入位圖以及能否創(chuàng)建紋理。Status缺省設(shè)為 FALSE(表示沒有載入或創(chuàng)建任何東東)。

                  int Status=FALSE;                 // Status 狀態(tài)指示器

               現(xiàn)在我們創(chuàng)建存儲(chǔ)位圖的圖像記錄。次記錄包含位圖的寬度、高度和數(shù)據(jù)。

                  AUX_RGBImageRec *TextureImage[1];          // 創(chuàng)建紋理的存儲(chǔ)空間

               清除圖像記錄,確保其內(nèi)容為空。

                  memset(TextureImage,0,sizeof(void *) *1);     // 將指針設(shè)為 NULL

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

                  // 載入位圖,檢查有無錯(cuò)誤,如果位圖沒找到則退出。
                  if (TextureImage[0]=LoadBMP("Data/NeHe.bmp"))
                   {
                       Status=TRUE;
                           // 將 Status 設(shè)為 TRUE

               現(xiàn)在使用中TextureImage[0]的數(shù)據(jù)創(chuàng)建紋理。第一行g(shù)lGenTextures(1, &texture[0])告訴OpenGL我們想生成一個(gè)紋理名字(如果您想載入多個(gè)紋理,加大數(shù)字)。值得注意的是,開始我們使用GLuinttexture[1]來創(chuàng)建一個(gè)紋理的存儲(chǔ)空間,您也許會(huì)認(rèn)為第一個(gè)紋理就是存放在&texture[1]中的,但這是錯(cuò)的。正確的地址應(yīng)該是 &texture[0]。同樣如果使用GLuint texture[2]的話,第二個(gè)紋理存放在texture[1]中。(譯者學(xué)C的,在這里應(yīng)該沒有障礙,數(shù)組就是從零開始的呀。) 第二行g(shù)lBindTexture(GL_TEXTURE_2D, texture[0])告訴OpenGL將紋理名字texture[0]綁定到紋理目標(biāo)上。2D紋理只有高度(在Y軸上)和寬度(在X軸上)。主函數(shù)將紋 理名字指派給紋理數(shù)據(jù)。本例中我們告知OpenGL,&texture[0]處的內(nèi)存已經(jīng)可用。我們創(chuàng)建的紋理將存儲(chǔ)在&texture [0]的指向的內(nèi)存區(qū)域。

                      glGenTextures(1, &texture[0]);     // 創(chuàng)建紋理
                       // 使用來自位圖數(shù)據(jù)生成的典型紋理
                      glBindTexture(GL_TEXTURE_2D, texture[0]);

            下來我們創(chuàng)建真正的紋理。下面一行告訴OpenGL此紋理是一個(gè)2D紋理(GL_TEXTURE_2D)。數(shù)字零代表圖像的詳細(xì)程度,通常就由它為零去 了。數(shù)字三是數(shù)據(jù)的成分?jǐn)?shù)。因?yàn)閳D像是由紅色數(shù)據(jù),綠色數(shù)據(jù),藍(lán)色數(shù)據(jù)三種組分組成。TextureImage[0]->sizeX是紋理的寬度。 如果您知道寬度,您可以在這里填入,但計(jì)算機(jī)可以很容易的為您指出此值。TextureImage[0]->sizey是紋理的高度。數(shù)字零是邊框 的值,一般就是零。GL_RGB告訴OpenGL圖像數(shù)據(jù)由紅、綠、藍(lán)三色數(shù)據(jù)組成。
               GL_UNSIGNED_BYTE意味著組成圖像的數(shù)據(jù)是無符號(hào)字節(jié)類型的。最后...TextureImage[0]->data告訴OpenGL紋理數(shù)據(jù)的來源。此例中指向存放在TextureImage[0]記錄中的數(shù)據(jù)。

                      // 生成紋理
                      glTexImage2D(GL_TEXTURE_2D, 0, 3,
                           TextureImage[0]->sizeX, TextureImage[0]->sizeY,
                           0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);

            下面的兩行告訴OpenGL在顯示圖像時(shí),當(dāng)它比放大得原始的紋理大(GL_TEXTURE_MAG_FILTER)或縮小得比原始得紋理小 (GL_TEXTURE_MIN_FILTER)時(shí)OpenGL采用的濾波方式。通常這兩種情況下我都采用GL_LINEAR。這使得紋理從很遠(yuǎn)處到離屏 幕很近時(shí)都平滑顯示。使用GL_LINEAR需要CPU和顯卡做更多的運(yùn)算。如果您的機(jī)器很慢,您也許應(yīng)該采用GL_NEAREST。過濾的紋理在放大的 時(shí)候,看起來斑駁的很(譯者就是馬賽克)。您也可以結(jié)合這兩種濾波方式。在近處時(shí)使用GL_LINEAR,遠(yuǎn)處時(shí)GL_NEAREST。

                      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);// 線形濾波
                      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);// 線形濾波
                  }

               現(xiàn)在我們釋放前面用來存放位圖數(shù)據(jù)的內(nèi)存。我們先查看位圖數(shù)據(jù)是否存放在處。如果是的話,再查看數(shù)據(jù)是否已經(jīng)存儲(chǔ)。如果已經(jīng)存儲(chǔ)的話,刪了它。接著再釋放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)
                  }

               最后返回狀態(tài)變量。如果一切OK,變量Status的值為TRUE。否則為FALSE

                  return Status;                  // 返回 Status
              }

            我只在 InitGL 中增加很少的幾行代碼。但為了方便您查看增加了哪幾行,我這段代碼全部重貼一遍。if (!LoadGLTextures())這行代碼調(diào)用上面講的子例程載入位圖并生成紋理。如果因?yàn)槿魏卧騆oadGLTextures()調(diào)用失敗,接 著的一行返回FALSE。如果一切OK,并且紋理創(chuàng)建好了,我們啟用2D紋理映射。如果您忘記啟用的話,您的對(duì)象看起來永遠(yuǎn)都是純白色,這一定不是什么好 事。

              int InitGL(GLvoid)                     // 此處開始對(duì)OpenGL進(jìn)行所有設(shè)置
              {
                    if (!LoadGLTextures())
                           // 調(diào)用紋理載入子例程(新增)
                  {
                       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); // 真正精細(xì)的透視修正
                  return TRUE;                    // 初始化 OK
              }

            現(xiàn)在我們繪制貼圖(紋理映射)過的立方體。這段代碼被狂注釋了一把,應(yīng)該很好懂。開始兩行代碼 glClear() 和 glLoadIdentity() 是第一課中就有的代碼。 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 清除屏幕并設(shè)為我們?cè)?InitGL() 中選定的顏色,本例中是黑色。深度緩存也被清除。模型觀察矩陣也使用glLoadIdentity()重置。

              int DrawGLScene(GLvoid)                  // 從這里開始進(jìn)行所有的繪制
              {
                   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            // 清除屏幕和深度緩存
                  glLoadIdentity();                 // 重置當(dāng)前的模型觀察矩陣
                  glTranslatef(0.0f,0.0f,-5.0f);           // 移入屏幕 5 個(gè)單位

               下面三行使立方體繞X、Y、Z軸旋轉(zhuǎn)。旋轉(zhuǎn)多少依賴于變量 xrot, yrot 和 zrot 的值。

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

            下一行代碼選擇我們使用的紋理。如果您在您的場(chǎng)景中使用多個(gè)紋理,您應(yīng)該使用來 glBindTexture(GL_TEXTURE_2D, texture[ 所使用紋理對(duì)應(yīng)的數(shù)字 ]) 選擇要綁定的紋理。當(dāng)您想改變紋理時(shí),應(yīng)該綁定新的紋理。有一點(diǎn)值得指出的是,您不能在glBegin()和glEnd()之間綁定紋理,必須在 glBegin()之前或 glEnd()之后綁定。注意我們?cè)诤竺媸侨绾问褂胓lBindTexture來指定和綁定紋理的。

                  glBindTexture(GL_TEXTURE_2D, texture[0]);     // 選擇紋理

              為了將紋理正確的映射到四邊形上,您必須將紋理的右上角映射到四邊形的右上角,紋理的左上角映射到四邊形的左上角,紋理的右下角映射到四邊形的右下角,紋理的左下角映射到四邊形的左下角。如果映射錯(cuò)誤的話,圖像顯示時(shí)可能上下顛倒,側(cè)向一邊或者什么都不是。
               glTexCoord2f的第一個(gè)參數(shù)是X坐標(biāo)。0.0f是紋理的左側(cè)。0.5f是紋理的中點(diǎn),1.0f是紋理的右側(cè)。glTexCoord2f的第二個(gè)參數(shù)是Y坐標(biāo)。0.0f是紋理的底部。0.5f是紋理的中點(diǎn),1.0f是紋理的頂部。
               所以紋理的左上坐標(biāo)是X:0.0f,Y:1.0f,四邊形的左上頂點(diǎn)是X:-1.0f,Y:1.0f。其余三點(diǎn)依此類推。
               試著玩玩glTexCoord2f的X,Y坐標(biāo)參數(shù)。把1.0f改為0.5f 將只顯示紋理的左半部分,把0.0f改為0.5f將只顯示紋理的右半部分。

                  glBegin(GL_QUADS);
                      // 前面
                      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); // 紋理和四邊形的左上

                      // 后面
                      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);// 紋理和四邊形的左下

                      // 頂面
                      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); // 紋理和四邊形的右上

                      // 底面
                      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); // 紋理和四邊形的右下

                      // 右面
                      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); // 紋理和四邊形的左下

                      // 左面
                      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();

               現(xiàn)在增加xrot、yrot及zrot的值。嘗試變化每次各變量的改變值來及調(diào)節(jié)立方體的旋轉(zhuǎn)速度,或改變+/-號(hào)來調(diào)節(jié)立方體的旋轉(zhuǎn)方向。

                  xrot+=0.3f;                    // X 軸旋轉(zhuǎn)
                  yrot+=0.2f;                    // Y 軸旋轉(zhuǎn)
                  zrot+=0.4f;                    // Z 軸旋轉(zhuǎn)
                  return true;                    // 繼續(xù)運(yùn)行
              }
            posted on 2007-12-10 11:39 sdfasdf 閱讀(1112) 評(píng)論(0)  編輯 收藏 引用 所屬分類: OPENGL
            九九久久精品国产| 久久久久久久久久免免费精品| 国产精品毛片久久久久久久 | 久久精品无码免费不卡| 久久久久免费看成人影片| 免费久久人人爽人人爽av| 久久综合视频网站| 91久久成人免费| 国产视频久久| 久久久久久噜噜精品免费直播 | 狠狠色丁香婷婷久久综合五月| 久久影视国产亚洲| 欧美午夜A∨大片久久| 久久天天躁狠狠躁夜夜2020| 一级a性色生活片久久无少妇一级婬片免费放| 亚洲乱亚洲乱淫久久| 久久九九久精品国产| 亚洲国产成人久久笫一页| 亚洲欧美日韩久久精品| 亚洲午夜久久久久妓女影院| 亚洲级αV无码毛片久久精品| 亚洲精品无码久久久久去q| 亚洲国产精品无码成人片久久| 久久精品无码一区二区无码| 精品综合久久久久久97超人| 国内精品欧美久久精品| 久久亚洲精品国产精品婷婷| 青青草原精品99久久精品66| 久久国产亚洲高清观看| 99久久精品免费观看国产| 欧美久久亚洲精品| 久久人爽人人爽人人片AV| 久久国产成人精品麻豆| 亚洲欧洲精品成人久久奇米网| 亚洲乱码精品久久久久..| 91精品国产高清久久久久久国产嫩草 | 色欲av伊人久久大香线蕉影院| 久久久久免费精品国产| 亚洲欧美另类日本久久国产真实乱对白 | 精品多毛少妇人妻AV免费久久| 99久久99久久|