{
貼圖可以極大的節省CPU時間。呵呵,但是這一節費了我比較多的時間 : (
因為用到了opengl的輔助庫,現在這個庫的函數已經很少有人用了,但是我還是找到了,感謝zdcnow(磁效應),他給我提供的這個輔助庫的delphi版本。在學習本節之前,請大家到網上下載glaux.dll、Glaux.pas文件,并加到項目中。
好了,讓我們繼續OPENGL之路.
首先我們需要加進SysUtils單元,因為我們這節要用到文件操作,我們還要將Glaux單元加進來。
然后我們在第一課的基礎上加上幾個變量,xrot , yrot 和 zrot 。這些變量用來使立方體繞X、Y、Z軸旋轉。texture[] 為一個紋理分配存儲空間。如果您需要不止一個的紋理,應該將數字1改成您所需要的數字。
}
VAR
h_RC : HGLRC; // Rendering Context(著色描述表)。
h_DC : HDC; // Device Context(設備描述表)
h_Wnd : HWND; // 窗口句柄
h_Instance : HINST; // 程序Instance(實例)。
keys : Array[0..255] Of Boolean; // 用于鍵盤例程的數組
xrot, // X 旋轉量 ( 新增 )
yrot, // Y 旋轉量 ( 新增 )
zrot : GLfloat; // Z 旋轉量 ( 新增 )
Texture : Array[0..1] Of GLuint; // 存儲一個紋理 ( 新增 )
{然后引載入opengl32.dll中的兩個過程,我們要用到他們}
PRocedure glGenTextures(n: GLsizei; Var textures: GLuint); stdcall; external
opengl32;
Procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external
opengl32;
{接下來我們需要增加一個新的函數,用來再入圖像,該函數的返回類型在Glaux.pas中定義如下:
TAUX_RGBImageRec= record
sizeX, sizeY: GLint;
data: pointer;
end;
PTAUX_RGBImageRec= ^TAUX_RGBImageRec;
具體含義會在后面介紹}
Function LoadBmp(filename: pchar): PTAUX_RGBImageRec;
Var
BitmapFile : Thandle; // 文件句柄
Begin
//接下來檢查文件名是否已提供
If Filename = '' Then // 確保文件名已提供。
result := Nil; // 如果沒提供,返回 NULL
//接著檢查文件是否存在。
BitmapFile := FileOpen(Filename, fmOpenWrite); //嘗試打開文件
//如果我們能打開文件的話,很顯然文件是存在的。
If BitmapFile > 0 Then // 文件存在么?
Begin
//關閉文件。
FileClose(BitmapFile); // 關閉句柄
//auxDIBImageLoad(Filename) 讀取圖象數據并將其返回。
result := auxDIBImageLoadA(filename); //載入位圖并返回指針
End
Else
//如果我們不能打開文件,我們將返回NiL。
result := Nil; // 如果載入失敗,返回NiL。
End;
//接下來在創建一個新函數,用來載入紋理貼圖
Function LoadTexture: boolean;
//Status 的變量。我們使用它來跟蹤是否能夠載入位圖以及能否創建紋理。
// Status 缺省設為 FALSE (表示沒有載入或創建任何東東)。
//TextureImage變量PTAUX_RGBImageRec類型 存儲位圖的圖像記錄。
//次記錄包含位圖的寬度、高度和數據。
Var
Status : boolean;
TextureImage : Array[0..1] Of PTAUX_RGBImageRec;
Begin
Status := false;
ZeroMemory(@TextureImage, sizeof(TextureImage)); // 將指針設為 NULL
TextureImage[0] := LoadBMP('Texture.bmp');
If TextureImage[0] <> Nil Then
Begin
Status := TRUE; // 將 Status 設為 TRUE
//現在使用中 TextureImage[0] 的數據創建紋理。
//glGenTextures(1, texture[0]) 告訴OpenGL我們想生成一個紋理名字
//(如果您想載入多個紋理,加大數字)。
//glBindTexture(GL_TEXTURE_2D, texture[0]) 告訴OpenGL將紋理名字 texture[0] 綁定到紋理目標上。
//2D紋理只有高度(在 Y 軸上)和寬度(在 X 軸上)。
//主函數將紋理名字指派給紋理數據。
//本例中我們告知OpenGL, &texture[0] 處的內存已經可用。
//我們創建的紋理將存儲在 &texture[0] 的 指向的內存區域。
glGenTextures(1, texture[0]); // 創建紋理
glBindTexture(GL_TEXTURE_2D, texture[0]); // 使用來自位圖數據生成 的典型紋理
//下來我們創建真正的紋理。
//下面一行告訴OpenGL此紋理是一個2D紋理 ( GL_TEXTURE_2D )。
//數字零代表圖像的詳細程度,通常就由它為零去了。
//數字三是數據的成分數。因為圖像是由紅色數據,綠色數據,藍色數據三種組分組成。
//TextureImage[0].sizeX 是紋理的寬度。
//如果您知道寬度,您可以在這里填入,但計算機可以很容易的為您指出此值。
// TextureImage[0].sizey 是紋理的高度。
//數字零是邊框的值,一般就是零。
// GL_RGB 告訴OpenGL圖像數據由紅、綠、藍三色數據組成。
//GL_UNSIGNED_BYTE 意味著組成圖像的數據是無符號字節類型的。
//最后... TextureImage[0].data 告訴OpenGL紋理數據的來源。
//此例中指向存放在 TextureImage[0] 記錄中的數據。
// 生成紋理
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
TextureImage[0].data);
//下面的兩行告訴OpenGL在顯示圖像時,
//當它比放大得原始的紋理大(GL_TEXTURE_MAG_FILTER)
//或縮小得比原始得紋理小(GL_TEXTURE_MIN_FILTER)時OpenGL采用的濾波方式。
//通常這兩種情況下我都采用 GL_LINEAR。這使得紋理從很遠處到離屏幕很近時都平滑顯示。
//使用 GL_LINEAR需要CPU和顯卡做更多的運算。
//如果您的機器很慢,您也許應該采用 GL_NEAREST 。
//過濾的紋理在放大的時候,看起來斑駁的很(馬賽克啦)。
//您也可以結合這兩種濾波方式。在近處時使用 GL_LINEAR ,遠處時 GL_NEAREST 。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 線形濾波
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 線形濾波
End;
//現在我們釋放前面用來存放位圖數據的內存。
//我們先查看位圖數據是否存放在處。
//如果是的話,再查看數據是否已經存儲。
//如果已經存儲的話,刪了它。
//接著再釋放 TextureImage[0] 圖像結構以保證所有的內存都能釋放。
If assigned(TextureImage[0]) Then // 紋理是否存在
If assigned(TextureImage[0].data) Then // 紋理圖像是否存在
TextureImage[0].data := Nil; // 釋放紋理圖像占用的內存
TextureImage[0] := Nil; // 釋放圖像結構
// 最后返回狀態變量。如果一切OK,變量 Status 的值為 TRUE 。否則為 FALSE
result := Status; // 返回 Status
End;
新聞熱點
疑難解答
圖片精選