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

code

#include "openglglut.h"


/**//**
** 紋理映射的學習
** 將一張bmp格式的圖片以紋理貼圖的方式,貼在正方體的6個面
*/

GLfloat xRot=0; /**//** 正方體繞x軸旋轉角度*/

GLfloat yRot=0; /**//** 正方體繞y軸旋轉角度*/

GLfloat zRot=0; /**//** 正方體繞z軸旋轉角度*/

static GLuint texnum; /**//** 定義存儲紋理*/

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


{

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

BITMAP bmp; /**//** 位圖的結構*/

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

if(!bBmp)
return false;

/**//** 獲得圖像數據對象*/
GetObject(bBmp,sizeof(bmp),&bmp);


/**//*
glPixelStroei(GLenum pname,GLint param)
pname: GL_PACK_ALIGNMENT 將影響opengl如何將像素數據存入內存(應該是說存儲結構).
GL_UNPACK_ALIGNMENT 將影響opengl讀取內存中的像素數據后的存儲結構.
param: 為內存中每行像素的起始位置指定校準需求,有四種值
1: byte-alignment
2: rows aligned to even-numbered bytes
4: word-alignment
8: rows start on double-word boundaries

默認值是:4
*/




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


glGenTextures(1,&texid); /**//** 創建一個紋理*/

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


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

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

/**//**
* glTexImage2D的參數比較復雜,
使用 GL_BGR_EXT的原因是: winapi里 bmp存儲的格式是BGR 與opengl中RBG 需要做個轉換
*/

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

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


DeleteObject(bBmp); /**//** 刪除對象,釋放內存*/

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


{

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


glutDisplayFunc(glutDisplay); /**//** 注冊重繪函數*/

glutIdleFunc(glutIdle); /**//** 注冊空閑回調函數*/

glutReshapeFunc(glutResize); /**//** 注冊窗口調整函數*/

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

glutKeyboardFunc(glutKeyboard); /**//** 注冊鍵盤處理函數*/


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

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

glutMainLoop(); /**//** 仿真循環*/
}
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) /**//** 重繪函數*/


{

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

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



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

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

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

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

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

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();
glutSwapBuffers();

}

void glutIdle(void) /**//** 回調函數*/


{

xRot+=0.3; /**//** 繞x軸旋轉角度遞增*/

yRot+=0.2; /**//** 繞y軸旋轉角度遞增*/

zRot+=0.4f; /**//** 繞z軸旋轉角度遞增*/

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

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


{
switch(key)

{

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





最終結果顯示為:

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