青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 131, comments - 12, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

OpenGL可以把紋理映射到指定的圖形的表面上。簡單一點的,就是給平面映射紋理,比如一個四邊形,一個長方體的6個面,都可以指定位圖作為紋理映射到各個面上。

關于將一個位圖作為紋理映射到某個或者多個面上,可以學習Jeff Molofee的OpenGL系列教程。

對于指定的多個紋理,要根據自己的需要映射到不同的面上,需要對位圖創建一個數組,用來存儲位圖的名稱,然后在初始化OpenGL的時候,可以讀取這些位圖,然后生成多個紋理存儲到一個紋理數組中,接著就可以指定繪制的某個面,對該指定的面進行紋理映射。

下面,在的Jeff Molofee教程的第六課的基礎上,實現對6個面分別進行不同的紋理映射。

準備工作就是制作6幅不同的位圖,如圖所示:


關鍵代碼及其說明如下。

創建全局紋理數組

GLuint texture[6];   // 創建一個全局的紋理數組,用來存儲將位圖轉換之后得到的紋理,對應于立方體的6個面

加載位圖文件

加載位圖,也就是把位圖讀取到內存空間,實現紋理的創建,加載位圖的函數說明一下:

AUX_RGBImageRec *LoadBMP(char *Filename)    // 根據位圖文件的名稱進行加載
{
FILE *File=NULL;        // 文件指針

if (!Filename)         // 如果沒有指定位圖文件名稱就返回NULL
{
   return NULL;         
}

File=fopen(Filename,"r");       // 根據指定的位圖文件名稱,打開該位圖文件

if (File)           // 如果位圖文件存在
{
   fclose(File);         // 因為只是需要判斷問題是否存在,而不需要對位圖文件進行寫操作,所以關閉位圖文件
   return auxDIBImageLoad(Filename);   // 其實,只需要一個真正存在的位圖文件的名稱,實現加載位圖文件,并返回一個指針
}

return NULL;          // 位圖文件加載失敗就返回NULL
}

上面實現加載位圖的函數中,AUX_RGBImageRec是glaux.h中定義的類型,該類型的定義如下所示:

/*
** RGB Image Structure
*/

typedef struct _AUX_RGBImageRec {
    GLint sizeX, sizeY;
    unsigned char *data;
} AUX_RGBImageRec;

首先,AUX_RGBImageRec類型是一個RGB圖像結構類型。該結構定義了三個成員:

sizeX —— 圖像的寬度;
sizeY —— 圖像的高度;
data; —— 圖形所包含的數據,其實也就是該圖形在內存中的像素數據的一個指針。

AUX_RGBImageRec類型的變量描述了一幅圖像的特征。

上述函數中,調用了glaux.h庫文件中的auxDIBImageLoad函數,其實它是一個宏,函數原型為auxRGBImageLoadW(LPCWSTR)或者auxRGBImageLoadA(LPCSTR),可以在該庫文件中找到它的定義,如下所示:

/* AUX_RGBImageRec * APIENTRY auxRGBImageLoad(LPCTSTR); */
#ifdef UNICODE
#define auxRGBImageLoad auxRGBImageLoadW
#else
#define auxRGBImageLoad auxRGBImageLoadA
#endif
AUX_RGBImageRec * APIENTRY auxRGBImageLoadA(LPCSTR);
AUX_RGBImageRec * APIENTRY auxRGBImageLoadW(LPCWSTR);

#ifdef UNICODE
#define auxDIBImageLoad auxDIBImageLoadW
#else
#define auxDIBImageLoad auxDIBImageLoadA
#endif
AUX_RGBImageRec * APIENTRY auxDIBImageLoadA(LPCSTR);
AUX_RGBImageRec * APIENTRY auxDIBImageLoadW(LPCWSTR);

宏auxDIBImageLoad實現的功能就是:根據指定的位圖名稱,將該位圖的信息加載到內存中,以便用來創建成為紋理。

創建紋理并加載紋理

用于創建并加載紋理的函數為LoadGLTextures,實現如下所示:

int LoadGLTextures()         // 根據加載的位圖創建紋理
{
int Status=FALSE;         // 指示紋理創建是否成功的標志

AUX_RGBImageRec *TextureImage[6];     // 創建一個紋理圖像數組,這里指定數組大小為6

memset(TextureImage,0,sizeof(void *)*6);          // 初始化紋理圖像數組,為其分配內存

char *pictures[] = {// 創建一個位圖名稱數組,對應6幅位圖
   "Data/No1.bmp",
   "Data/No2.bmp",
   "Data/No3.bmp",
   "Data/No4.bmp",
   "Data/No5.bmp",
   "Data/No6.bmp"
};
for(int i=0; i<6; i++)// 遍歷位圖名稱數組,根據位圖名稱分別生成
{
   if (TextureImage[i]=LoadBMP(pictures[i]))// 加載位圖i成功,修改狀態標志變量Status為TRUE
   {
    Status=TRUE;         

   glGenTextures(1, &texture[i]);     // 為第i個位圖創建紋理
   glBindTexture(GL_TEXTURE_2D, texture[i]);// 將生成的紋理的名稱綁定到指定的紋理上
   glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[i]->sizeX, TextureImage[i]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[i]->data);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   }

   if (TextureImage[i])         // 釋放位圖數組占用的內存空間
   {
    if (TextureImage[i]->data)       
    {
     free(TextureImage[i]->data);    
    }

    free(TextureImage[i]);        
   }
}
return Status;          // 創建紋理并加載,返回成功或者失敗的標志Status
}

上述函數是創建和加載紋理的核心實現。

1、glGenTextures函數

其中,調用了glGenTextures函數,查看MSDN可以看到,聲明如下所示:

void glGenTextures(
GLsizein,         
GLuint *textures  
);

函數參數的含義:

n—— 生成的紋理的名稱的個數;

textures—— 生成的紋理名稱所存儲位置的指針,也就是一個紋理數組的內存地址,或者說是數組首元素的內存地址。

函數被調用,會生成一系列紋理的名字,并存儲到指定的數組中。

2、glBindTexture函數

glBindTexture函數實現了將調用glGenTextures函數生成的紋理的名字綁定到對應的目標紋理上。該函數的聲明如下所示:

void glBindTexture(
GLenumtarget,  
GLuinttexture  
);

函數參數的含義:

target—— 紋理被綁定的目標,它只能取值GL_TEXTURE_1D或者GL_TEXTURE_2D;

texture—— 紋理的名稱,并且,該紋理的名稱在當前的應用中不能被再次使用。

3、glTexImage2D函數

調用glTexImage2D函數,用來指定二維紋理圖像。該函數的聲明如下所示:

void glTexImage2D(
GLenumtarget,       
GLintlevel,         
GLintcomponents,    
GLsizeiwidth,       
GLsizeiheight,      
GLintborder,        
GLenumformat,       
GLenumtype,         
const GLvoid*pixels
);

函數參數的含義:

target—— 指定目標紋理,必須為GL_TEXTURE_2D;

level—— 指定圖像級別的編號,0表示基本圖像,其它可以參考MSDN;

components—— 紋理中顏色組件的編號,可是是1或2或3或4;

width—— 紋理圖像的寬度;

height—— 紋理圖像的高度;

border—— 紋理圖像的邊框寬度,必須是0或1;

format—— 指定像素數據的格式,一共有9個取值:GL_COLOR_INDEX、GL_RED、GL_GREEN、GL_BLUE、GL_ALPHA、GL_RGB、GL_RGBA、GL_BGR_EXT、GL_BGRA_EXT、GL_LUMINANCE、GL_LUMINANCE_ALPHA ,具體含義可以參考MSDN;

type—— 像素數據的數據類型,取值可以為GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, and GL_FLOAT;

pixels—— 內存中像素數據的指針。

4、glTexParameteri函數

glTexParameteri函數或者glTexParameterf函數用來設置紋理參數,聲明如下所示:

void glTexParameterf(
GLenumtarget,
GLenumpname,
GLfloatparam
);

void glTexParameteri(
GLenumtarget,
GLenumpname,
GLintparam   
);

函數參數的含義:

target—— 目標紋理,必須為GL_TEXTURE_1D或GL_TEXTURE_2D;

pname—— 用來設置紋理映射過程中像素映射的問題等,取值可以為:GL_TEXTURE_MIN_FILTER、GL_TEXTURE_MAG_FILTER、GL_TEXTURE_WRAP_S、GL_TEXTURE_WRAP_T,詳細含義可以查看MSDN;

param—— 實際上就是pname的值,可以參考MSDN。

另外,該類函數還有兩個:

void glTexParameterfv(
GLenumtarget,        
GLenumpname,         
const GLfloat*params
);

void glTexParameteriv(
GLenumtarget,      
GLenumpname,       
const GLint*params
);

上述程序中調用如下:

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

功能就是實現線形濾波的功能,當紋理映射到圖形表面以后,如果因為其它條件的設置導致紋理不能更好地顯示的時候,進行過濾,按照指定的方式進行顯示,可能會過濾掉顯示不正常的紋理像素。

紋理映射過程

紋理映射的過程是在DrawGLScene函數中實現的,也就是在繪制圖形的過程中,直接進行我呢里映射,或者稱為,為指定的平面貼紋理,DrawGLScene函數實現如下所示:

int DrawGLScene(GLvoid)         
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();         
glTranslatef(0.0f,0.0f,-5.0f);

glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);


  // Front Face
glBindTexture(GL_TEXTURE_2D, texture[0]);//   選擇第一個紋理texture[0],進行貼紋理
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);
glEnd();

  // Back Face
glBindTexture(GL_TEXTURE_2D, texture[1]);//   選擇第二個紋理texture[1],進行貼紋理
glBegin(GL_QUADS);
   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);
glEnd();

  // Top Face
glBindTexture(GL_TEXTURE_2D, texture[2]);//   選擇第三個紋理texture[2],進行貼紋理
glBegin(GL_QUADS);
   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);
glEnd();

  // Bottom Face
glBindTexture(GL_TEXTURE_2D, texture[3]);//   選擇第四個紋理texture[3],進行貼紋理
glBegin(GL_QUADS);
   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);
glEnd();

  // Right face
glBindTexture(GL_TEXTURE_2D, texture[4]);//   選擇第五個紋理texture[4],進行貼紋理
glBegin(GL_QUADS);
   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);
glEnd();

  // Left Face
glBindTexture(GL_TEXTURE_2D, texture[5]);//   選擇第六個紋理texture[5],進行貼紋理
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);
glEnd();

xrot+=0.3f;
yrot+=0.2f;
zrot+=0.4f;
return TRUE;          
}

因為,通過前面的過程,已經將位圖加載并創建和加載紋理成功,紋理數組已經存在于內存之中,調用上述函數實現紋理映射,即,從內存中取出指定的紋理,將其映射到立方體的指定的面上。

上述函數中調用了glTexCoord2f函數,設置紋理坐標,該函數的聲明如下所示:

void glTexCoord2f(
GLfloats,
GLfloatt
);

glTexCoord2f 的第一個參數是X坐標,當s=0.0f 時是紋理的左側,s=0.5f 時是紋理的中點,s=1.0f 時是紋理的右側。 glTexCoord2f 的第二個參數是Y坐標,t=0.0f 是紋理的底部,t=0.5f 是紋理的中點, t=1.0f 是紋理的頂部。

上述函數在為前面那個面映射紋理的時候調用如下:

   // Front Face
glBindTexture(GL_TEXTURE_2D, texture[0]);
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);
glEnd();

其中:

glTexCoord2f(0.0f, 0.0f);表示將紋理texture[0]的左下角坐標(0.0f, 0.0f)映射到立方體前面那個面的頂點(-1.0f, -1.0f, 1.0)上;

glTexCoord2f(1.0f, 0.0f);表示將紋理texture[0]的右下角坐標(1.0f, 0.0f)映射到立方體前面那個面的頂點(1.0f, -1.0f, 1.0f)上;

glTexCoord2f(1.0f, 1.0f);表示將紋理texture[0]的右上角坐標(1.0f, 1.0f)映射到立方體前面那個面的頂點(1.0f, 1.0f, 1.0f)上;

glTexCoord2f(0.0f, 1.0f);表示將紋理texture[0]的左上角坐標(0.0f, 1.0f)映射到立方體前面那個面的頂點(-1.0f, 1.0f, 1.0f)上。

這樣,紋理texture[0]就被映射到了立方體前面那個面上。

紋理映射結果

為了使立方體能夠運動起來,對立方體進行累的旋轉變換,而且,定義了三個全局變量:

GLfloat xrot;    // 沿著x旋轉的變量
GLfloat yrot;    // 沿著y旋轉的變量
GLfloat zrot;   // 沿著z旋轉的變量

初始化都為0,然后,在每次調用DrawGLScene函數的時候,改變x、y、z的分量值,在DrawGLScene函數中如下所示:

xrot+=0.3f;
yrot+=0.2f;
zrot+=0.4f;

在DrawGLScene函數中還要執行旋轉變換:

glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);

每次重繪都在改變旋轉軸,所以我們繪制的立方體能夠動起來,看到各個進行紋理映射的面的效果,如圖所示





只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美国产三级| 亚洲欧美日韩一区二区三区在线观看 | 欧美激情91| 国产欧美日韩在线视频| 日韩视频在线观看一区二区| 久久久av毛片精品| 一本色道久久综合狠狠躁的推荐| 欧美福利视频在线观看| 久久一区欧美| 在线亚洲免费| 久久亚洲精品欧美| 中文国产亚洲喷潮| 午夜国产精品影院在线观看| 伊人久久综合| 一本色道88久久加勒比精品 | 亚洲激情第一区| 久久综合亚州| 中文在线一区| 欧美黄色一区| 久久在线免费观看| 国产精品ⅴa在线观看h| 欧美国产成人在线| 国产伦精品一区二区三区四区免费 | 欧美黄色片免费观看| 国产精品一区二区久久国产| 亚洲国产精品久久久久婷婷老年| 国产精品视频导航| 亚洲自拍电影| 久久久av毛片精品| 日韩视频免费观看高清在线视频 | 久久夜精品va视频免费观看| 亚洲国产精品成人综合色在线婷婷| 日韩视频精品在线观看| 欧美一区二区三区四区在线| 亚洲欧洲精品一区二区三区| 久久精品一区四区| 狠狠色狠色综合曰曰| 久久久av毛片精品| 欧美在线视频一区二区| 国产日韩三区| 久久精品在这里| 久久久蜜桃精品| 亚洲第一精品久久忘忧草社区| 久久影院亚洲| 男人的天堂亚洲| 中日韩在线视频| 亚洲一区二区免费| 久久精品亚洲精品国产欧美kt∨| 亚洲精品国产精品乱码不99| 欧美久久久久久久久| 亚洲欧美日韩爽爽影院| 久久精品噜噜噜成人av农村| 亚洲国产91色在线| 亚洲天天影视| 亚洲精品国产视频| 午夜欧美精品久久久久久久| 伊人久久男人天堂| 亚洲午夜精品久久| 亚洲精品欧美日韩专区| 亚洲宅男天堂在线观看无病毒| 国产私拍一区| 一区二区高清在线观看| 久久婷婷成人综合色| 欧美二区在线播放| 国产精品亚洲аv天堂网| 亚洲国产va精品久久久不卡综合| 国产精品一区二区欧美| 亚洲精品久久久久久下一站 | 久久影视三级福利片| 欧美激情影音先锋| 欧美成人免费全部| 免费中文日韩| 红杏aⅴ成人免费视频| 亚洲欧美激情精品一区二区| 亚洲少妇中出一区| 欧美日韩一区二区在线视频 | 免费一区视频| 在线观看精品一区| 欧美一区二区网站| 欧美在线首页| 国内精品国产成人| 久久国产精品色婷婷| 麻豆91精品91久久久的内涵| 精品1区2区| 欧美日韩1234| 欧美一区二区三区在线看| 快射av在线播放一区| 亚洲激情综合| 国产精品久久网站| 久久综合影视| 亚洲午夜久久久久久久久电影网| 欧美伊人久久| 中文高清一区| 激情五月***国产精品| 欧美激情1区2区3区| 午夜老司机精品| 99re8这里有精品热视频免费 | 久久久久久综合| 亚洲国产一区二区三区青草影视 | 久久精彩视频| 亚洲黄色精品| 国产日韩欧美综合| 欧美日韩国产麻豆| 美女91精品| 久久精品青青大伊人av| 99国产精品国产精品毛片| 老司机久久99久久精品播放免费| 亚洲精品乱码久久久久久| 国产精品视频专区| 国产精品久久久一区二区三区| 欧美福利小视频| 欧美v亚洲v综合ⅴ国产v| 久久午夜精品一区二区| 久久激情视频| 久久亚洲春色中文字幕久久久 | 久久久久久网站| 性8sex亚洲区入口| 欧美在线精品免播放器视频| 亚洲缚视频在线观看| 在线观看欧美成人| 亚洲国产精品美女| 一本色道久久综合狠狠躁的推荐| 一本色道久久综合亚洲精品按摩 | 亚洲欧美日韩精品久久久| 亚洲精品乱码久久久久久按摩观| 亚洲国产精品一区| 日韩香蕉视频| 欧美亚洲在线观看| 欧美激情无毛| 一区二区三区视频在线播放| 在线综合亚洲| 美女国产一区| 国产伦精品一区二区三区高清版| 狠狠狠色丁香婷婷综合激情| 91久久国产精品91久久性色| 亚洲性视频网站| 亚洲国产精品123| 欧美自拍偷拍午夜视频| 欧美高清在线| 在线不卡亚洲| 久久激情网站| 亚洲一区黄色| 欧美亚韩一区| 亚洲手机在线| 亚洲精品日韩精品| 麻豆精品网站| 亚洲电影免费观看高清完整版| 亚洲欧美在线磁力| 日韩一本二本av| 欧美精品二区| 亚洲精品极品| 亚洲高清视频一区| 欧美国产欧美亚州国产日韩mv天天看完整| 国产精品久久久久久妇女6080| 亚洲国产成人av好男人在线观看| 久久精品一区二区三区中文字幕| 亚洲午夜激情| 国产一区二区三区丝袜| 久久九九有精品国产23| 欧美一区三区三区高中清蜜桃| 国产精品亚发布| 久久综合网hezyo| 欧美成人一区二区| 亚洲综合欧美日韩| 午夜精品久久| 亚洲三级电影在线观看| 一区二区三区久久| 亚洲无限av看| 激情亚洲网站| 一区二区冒白浆视频| 极品日韩久久| 在线亚洲激情| 尤妮丝一区二区裸体视频| 亚洲黄色免费电影| 国产日韩欧美黄色| 亚洲精品欧美| 亚洲大胆人体在线| 亚洲一区二区三区涩| 亚洲国产精品激情在线观看| 亚洲毛片一区二区| 亚洲福利精品| 久久精品成人| 久久狠狠久久综合桃花| 欧美香蕉大胸在线视频观看| 欧美大片一区二区三区| 国产欧美日韩91| 一区二区高清在线| 一区二区成人精品| 欧美激情视频一区二区三区免费| 久久久久国产精品厨房| 国产精品永久| 亚洲欧美日韩在线不卡| 亚洲一级黄色片| 欧美性片在线观看| 亚洲久色影视| 欧美一区二区三区四区在线观看| 欧美视频精品一区| 亚洲影视在线| 久久综合伊人77777蜜臀| 国产亚洲精品综合一区91|