學(xué)習(xí)如何使用紋理貼圖,紋理貼圖的一般步驟,紋理坐標(biāo)的初體驗(yàn).,設(shè)定步驟如下
glGenTextures(1,&texnum); //創(chuàng)建一個(gè)紋理
glBindTexture(GL_TEXTURE_2D,texnum); //指定一個(gè)紋理
//設(shè)置紋理的一些數(shù)據(jù)等...
.....
...
glEnable(GL_TEXTURE_2D); //啟用紋理功能
選擇一個(gè)紋理,提供紋理坐標(biāo)
glBindTexture(GL_TEXTURE_2D,texnum);
glTexCoord2f(x,y) //設(shè)定每個(gè)點(diǎn)的紋理坐標(biāo)
一張二維紋理貼圖,相當(dāng)于一個(gè)矩形數(shù)據(jù)..
最左邊對(duì)應(yīng) x-->0.0,最右邊對(duì)應(yīng) x-->1.0
最下邊對(duì)應(yīng) y->0.0 最上邊對(duì)應(yīng) y-->1.0
其次對(duì)于一張bmp圖片,應(yīng)為glut中并不提供讀取圖像數(shù)據(jù)的方法.而紋理貼圖中圖像的數(shù)據(jù)必須得自己
創(chuàng)建函數(shù)從文件中讀取出來 最后綁定在紋理上..
這里我將使用的是win API 的方法讀取一張bmp文件
WINUSERAPI HANDLE WINAPI LoadImage( HINSTANCE, LPCWSTR, UINT,int, int, UINT);
參數(shù)分別表示如下:
HINSTANCE---------包含所需要圖片的實(shí)例的句柄。
LPCSTR--------------圖片所在路徑及文件名。
UINT-------------------圖片類型。
int-----------------------圖片寬度。
int-----------------------圖片高度。
UINT-------------------load flags
HINSTANCE ---將使用GetModuleHandle(NULL) 獲得..就是獲得一個(gè)應(yīng)用程序的句柄,NULL代表當(dāng)前這個(gè)程序
獲得了位圖的句柄之后 使用以下函數(shù)獲得圖像數(shù)據(jù)
int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
使用以下代碼時(shí)候,需要在lesson_1中的openglglut.h 添加一個(gè)函數(shù)聲明: void InitTexture(void);

code

#include "openglglut.h"


/**//**
** 紋理映射的學(xué)習(xí)
** 將一張bmp格式的圖片以紋理貼圖的方式,貼在正方體的6個(gè)面
*/

GLfloat xRot=0; /**//** 正方體繞x軸旋轉(zhuǎn)角度*/

GLfloat yRot=0; /**//** 正方體繞y軸旋轉(zhuǎn)角度*/

GLfloat zRot=0; /**//** 正方體繞z軸旋轉(zhuǎn)角度*/

static GLuint texnum; /**//** 定義存儲(chǔ)紋理*/

/**//** 這是一個(gè)通過WIN API 載入一張bmp格式圖片的方法*/
bool LoadBmpTexture(LPTSTR filename,GLuint& texid)


{

HBITMAP bBmp; /**//** 位圖文件的句柄*/

BITMAP bmp; /**//** 位圖的結(jié)構(gòu)*/

/**//** 通過API LoadImage 讀入bmp文件,獲得句柄*/
bBmp=(HBITMAP)LoadImage(GetModuleHandle(NULL),filename,IMAGE_BITMAP,0,0,
LR_CREATEDIBSECTION | LR_LOADFROMFILE);

if(!bBmp)
return false;

/**//** 獲得圖像數(shù)據(jù)對(duì)象*/
GetObject(bBmp,sizeof(bmp),&bmp);


/**//*
glPixelStroei(GLenum pname,GLint param)
pname: GL_PACK_ALIGNMENT 將影響opengl如何將像素?cái)?shù)據(jù)存入內(nèi)存(應(yīng)該是說存儲(chǔ)結(jié)構(gòu)).
GL_UNPACK_ALIGNMENT 將影響opengl讀取內(nèi)存中的像素?cái)?shù)據(jù)后的存儲(chǔ)結(jié)構(gòu).
param: 為內(nèi)存中每行像素的起始位置指定校準(zhǔn)需求,有四種值
1: byte-alignment
2: rows aligned to even-numbered bytes
4: word-alignment
8: rows start on double-word boundaries

默認(rèn)值是:4
*/




glPixelStorei(GL_UNPACK_ALIGNMENT,4); /**//** ? */


glGenTextures(1,&texid); /**//** 創(chuàng)建一個(gè)紋理*/

glBindTexture(GL_TEXTURE_2D,texid); /**//** 為它指定一個(gè)紋理*/


glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); /**//** 線性濾波 */

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); /**//** 線性濾波 */

/**//**
* glTexImage2D的參數(shù)比較復(fù)雜,
使用 GL_BGR_EXT的原因是: winapi里 bmp存儲(chǔ)的格式是BGR 與opengl中RBG 需要做個(gè)轉(zhuǎn)換
*/

glTexImage2D(GL_TEXTURE_2D,0,3,bmp.bmWidth,bmp.bmHeight

,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,bmp.bmBits); /**//** 生成紋理*/


DeleteObject(bBmp); /**//** 刪除對(duì)象,釋放內(nèi)存*/

return true;
}
int main(int argc,char** argv)


{

createWindow("opengl lesson_6",&argc,argv); /**//** 初始化并創(chuàng)建窗口*/


glutDisplayFunc(glutDisplay); /**//** 注冊(cè)重繪函數(shù)*/

glutIdleFunc(glutIdle); /**//** 注冊(cè)空閑回調(diào)函數(shù)*/

glutReshapeFunc(glutResize); /**//** 注冊(cè)窗口調(diào)整函數(shù)*/

glutSpecialFunc(glutSpecial); /**//** 注冊(cè)特殊按鍵窗口*/

glutKeyboardFunc(glutKeyboard); /**//** 注冊(cè)鍵盤處理函數(shù)*/


InitTexture(); /**//** 初始化啟用紋理映射并加載紋理*/

InitOpenGL(); /**//** 初始化opengl*/

glutMainLoop(); /**//** 仿真循環(huán)*/
}
void InitTexture(void)


{

/**//** 讀入工程目錄下data文件中的bmp文件*/
if(!LoadBmpTexture(L"..\\Data\\NeHe.bmp",texnum))

{
printf("load texture error!\n");
exit(0);
}

/**//** 若載入紋理成功 則啟用紋理映射*/
glEnable(GL_TEXTURE_2D);
}

void glutDisplay(void) /**//** 重繪函數(shù)*/


{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);/**//** 清除顏色緩存和深度緩存*/

glLoadIdentity(); /**//** 初始化當(dāng)前矩陣為單位矩陣*/



glTranslatef(0.0,0.0,-6.0); /**//** 往左移動(dòng)和往屏幕內(nèi)部移動(dòng),繪制正方體*/

glRotatef(xRot,1.0,0.0,0.0); /**//** 正方體繞x軸旋轉(zhuǎn)xRot角度*/

glRotatef(yRot,0.0,1.0,0.0); /**//** 正方體繞y軸旋轉(zhuǎn)yRot角度*/

glRotatef(zRot,0.0,0.0,1.0); /**//** 正方體繞z軸旋轉(zhuǎn)zRot角度*/

glBindTexture(GL_TEXTURE_2D,texnum); /**//** 選擇一個(gè)紋理*/

glBegin(GL_QUADS); /**//** 通過繪制六個(gè)正方形組成正方體,并為每一面都貼上紋理*/
//前面
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();
glutSwapBuffers();

}

void glutIdle(void) /**//** 回調(diào)函數(shù)*/


{

xRot+=0.3; /**//** 繞x軸旋轉(zhuǎn)角度遞增*/

yRot+=0.2; /**//** 繞y軸旋轉(zhuǎn)角度遞增*/

zRot+=0.4f; /**//** 繞z軸旋轉(zhuǎn)角度遞增*/

glutPostRedisplay(); /**//** 使得函數(shù)完成后進(jìn)行窗口重繪*/
}

void glutKeyboard(unsigned char key,int x,int y)


{
switch(key)

{

case 27: /**//** Esc按鍵按下后退出程序 */
exit(0);
break;
default:
break;
}
}





最終結(jié)果顯示為:

末尾總結(jié):
使用紋理的步驟 應(yīng)當(dāng)如下:
1.創(chuàng)建紋理對(duì)象,并為它指定一個(gè)紋理
2. 確定紋理是如何應(yīng)用到每個(gè)像素上
3.啟用紋理貼圖功能
4.繪制場(chǎng)景,提供紋理和幾何坐標(biāo)
其次,如何使用winapi讀取bmp圖像數(shù)據(jù).在以后的學(xué)習(xí)中可能還會(huì)遇到各種圖像貼圖的讀取.
對(duì)于各種格式的文件很有可能都將要?jiǎng)?chuàng)建一種方法去讀取數(shù)據(jù),才能最終應(yīng)用到紋理上?
posted on 2009-07-17 20:46
米游 閱讀(1013)
評(píng)論(3) 編輯 收藏 引用 所屬分類:
OpenGL/OSG