將CKER翻譯的NeHe的VC 的OPENGL框架轉(zhuǎn)成了Delphi版,
希望對(duì)用Delphi學(xué)習(xí)OPENGL的兄弟有所幫助,
不知為什么,我的Delphi環(huán)境下無(wú)法直接運(yùn)行,但是在別的機(jī)器上好像沒(méi)問(wèn)題
我的機(jī)器只能編譯后運(yùn)行EXE文件。
感謝NeHe提供的這么好的框架,感謝CKER翻譯的VC的資料
PRogram Project1;
Uses
opengl,
windows,
Messages;
Const
WND_TITLE = 'OPenGl 基本框架'; //標(biāo)題
Var
//===========================================================================
// 每一個(gè)OpenGL都被連接到一個(gè)著色描述表上。著色描述表將所有的OpenGL調(diào)用命令連
// 接到Device Context(設(shè)備描述表)上,將OpenGL的著色描述表定義為hRC ,要讓程序能
// 夠繪制窗口的話,還需要?jiǎng)?chuàng)建一個(gè)設(shè)備描述表,Windows的設(shè)備描述表被定義為 hDC,
// DC將窗口連接到GDI(Graphics Device Interface圖形設(shè)備接口)。而RC將OpenGL連接
// 到DC。
//===========================================================================
h_RC : HGLRC; // Rendering Context(著色描述表)。
h_DC : HDC; // Device Context(設(shè)備描述表)
h_Wnd : HWND; // 窗口句柄
h_Instance : HINST; // 程序Instance(實(shí)例)。
keys : Array[0..255] Of Boolean; // 用于鍵盤(pán)例程的數(shù)組
{$R *.res}
//==============================================================================
//重新設(shè)置OpenGL場(chǎng)景的大小,而不管窗口的大小是否已經(jīng)改變(假定沒(méi)有使用全屏模式)。
//甚至無(wú)法改變窗口的大小時(shí)(例如在全屏模式下),它至少仍將運(yùn)行一次————————
//在程序開(kāi)始時(shí)設(shè)置透視圖。OpenGL場(chǎng)景的尺寸將被設(shè)置成它顯示時(shí)所在窗口的大小。
//==============================================================================
Procedure glResizeWnd(Width, Height: Integer); // 重置并初始化GL窗口大小
Begin
If (Height = 0) Then // 防止高度為0,產(chǎn)生除0異常
Height := 1;
glViewport(0, 0, Width, Height); // 重置當(dāng)前的視口(Viewport)
//下面幾行為透視圖設(shè)置屏幕。意味著越遠(yuǎn)的東西看起來(lái)越小。這么做創(chuàng)建了一個(gè)現(xiàn)實(shí)
//外觀的場(chǎng)景。此處透視按照基于窗口寬度和高度的45度視角來(lái)計(jì)算。0.1f,100.0f是
//我們?cè)趫?chǎng)景中所能繪制深度的起點(diǎn)和終點(diǎn)。
//glMatrixMode(GL_PROJECTION)指明接下來(lái)的兩行代碼將影響projection matrix(投影矩陣)。
//投影矩陣負(fù)責(zé)為我們的場(chǎng)景增加透視。
//glLoadIdentity()近似于重置。它將所選的矩陣狀態(tài)恢復(fù)成其原始狀態(tài)。
//調(diào)用 glLoadIdentity()之后我們?yōu)閳?chǎng)景設(shè)置透視圖。
glMatrixMode(GL_PROJECTION); // 選擇投影矩陣
glLoadIdentity(); // 重置投影矩陣
gluPerspective(45.0, Width / Height, 0.1, 100.0); // 計(jì)算窗口的外觀比例
//glMatrixMode(GL_MODELVIEW)指明任何新的變換將會(huì)影響 modelview matrix(模型觀察矩陣)。
//模型觀察矩陣中存放了我們的物體訊息。
glMatrixMode(GL_MODELVIEW); // 選擇模型觀察矩陣
glLoadIdentity(); // 重置模型觀察矩陣
//如果現(xiàn)在還不能理解這些術(shù)語(yǔ)的含義,請(qǐng)別著急。
//只要知道如果想獲得一個(gè)精彩的透視場(chǎng)景的話,必須這么做。
End;
//==============================================================================
// 對(duì)OpenGL進(jìn)行所有的設(shè)置。將設(shè)置清除屏幕所用的顏色,打開(kāi)深度緩存,
// 啟用smooth shading(陰影平滑),等等。這個(gè)例程直到OpenGL窗口創(chuàng)建之后才會(huì)被調(diào)用。
// 此過(guò)程將有返回值。但此處的初始化沒(méi)那么復(fù)雜,現(xiàn)在還用不著擔(dān)心這個(gè)返回值。
//==============================================================================
Procedure glInit();
Begin
//設(shè)置清除屏幕時(shí)所用的顏色。如果對(duì)色彩的工作原理不清楚的話,快速解釋一下。
//色彩值的范圍從0.0f到1.0f。0.0f代表最黑的情況,1.0f就是最亮的情況。
//glClearColor 后的第一個(gè)參數(shù)是Red Intensity(紅色分量),第二個(gè)是綠色,第三個(gè)是藍(lán)色。
//最大值也是1.0f,代表特定顏色分量的最亮情況。最后一個(gè)參數(shù)是Alpha值。
//當(dāng)它用來(lái)清除屏幕的時(shí)候,不用關(guān)心第四個(gè)數(shù)字。現(xiàn)在讓它為0.0f。
//通過(guò)混合三種原色(紅、綠、藍(lán)),可以得到不同的色彩
//因此,使用glClearColor(0.0f,0.0f,1.0f,0.0f),您藍(lán)色來(lái)清除屏幕。
//如果用 glClearColor(0.5f,0.0f,0.0f,0.0f)的話,將使用中紅色來(lái)清除屏幕。
//不是最亮(1.0f),也不是最暗 (0.0f)。要得到白色背景,應(yīng)該將所有的顏色設(shè)成最亮(1.0f)。
//要黑色背景的話,該將所有的顏色設(shè)為最暗(0.0f)。
glClearColor(0.0, 0.0, 0.0, 0.0); // 黑色背景
//陰影平滑通過(guò)多邊形精細(xì)的混合色彩,并對(duì)外部光進(jìn)行平滑。
glShadeModel(GL_SMOOTH); // 啟用陰影平滑
//接下來(lái)必須做的是關(guān)于depth buffer(深度緩存)的。將深度緩存設(shè)想為屏幕后面的層。
//深度緩存不斷的對(duì)物體進(jìn)入屏幕內(nèi)部有多深進(jìn)行跟蹤。本程序其實(shí)沒(méi)有真正使用深度緩存,
//但幾乎所有在屏幕上顯示3D場(chǎng)景OpenGL程序都使用深度緩存。它的排序決定那個(gè)物體先畫(huà)。
//這樣您就不會(huì)將一個(gè)圓形后面的正方形畫(huà)到圓形上來(lái)。深度緩存是OpenGL十分重要的部分。
glClearDepth(1.0); // 設(shè)置深度緩存
glEnable(GL_DEPTH_TEST); // 啟用深度測(cè)試
glDepthFunc(GL_LESS); // 所作深度測(cè)試的類型
//接著告訴OpenGL我們希望進(jìn)行最好的透視修正。
//這會(huì)十分輕微的影響性能。但使得透視圖看起來(lái)好一點(diǎn)。
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 真正精細(xì)的透視修正
End;
//==============================================================================
//所有的繪圖代碼。任何您所想在屏幕上顯示的東東都將在此段代碼中出現(xiàn)。
//以后的每個(gè)程序會(huì)在此處增加新的代碼。
//==============================================================================
Procedure glDraw();
Begin
glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度緩存
glLoadIdentity(); // 重置當(dāng)前的模型觀察矩陣
End;
Function WndProc(hWnd: HWND; // 窗口的句柄
Msg: UINT; // 窗口的消息
wParam: WPARAM; // 附加的消息內(nèi)容
lParam: LPARAM // 附加的消息內(nèi)容
): LRESULT; stdcall;
Begin
Result := 0;
Case (Msg) Of // 檢查Windows消息
WM_ACTIVATE: // 監(jiān)視窗口激活消息
Begin
End;
WM_CREATE: // 創(chuàng)建
Begin
End;
WM_CLOSE: // 關(guān)閉
Begin
PostQuitMessage(0); // 發(fā)出退出消息
Result := 0
End;
WM_KEYDOWN: // 按鍵按下
Begin
keys[wParam] := True; // 如果是,設(shè)為T(mén)RUE
Result := 0;
End;
WM_KEYUP: // 按鍵松開(kāi)
Begin
keys[wParam] := False; // 如果是,設(shè)為FALSE
Result := 0;
End;
WM_SIZE: //調(diào)整OpenGL窗口大小
Begin
glResizeWnd(LOWord(lParam), HIWORD(lParam)); //LoWord=Width,HiWord=Height
Result := 0;
End;
WM_TIMER: //timers
Begin
End;
Else //其余的讓W(xué)indows自行處理。
Result := DefWindowProc(hWnd, Msg, wParam, lParam); //向DefWindowProc傳遞所有未處理的消息。
End;
End;
//==============================================================================
// 只在程序退出之前調(diào)用。作用是依次釋放著色描述表,設(shè)備描述表和窗口句柄。
// 加入了許多錯(cuò)誤檢查。如果程序無(wú)法銷毀窗口的任意部分,都會(huì)彈出帶相應(yīng)錯(cuò)誤消息的
// 訊息窗口,
//==============================================================================
Procedure glKillWnd(Fullscreen: Boolean);
Begin
//在KillGLWindow()中所作的第一件事是檢查是否處于全屏模式。
//如果是,要切換回桌面。本應(yīng)在禁用全屏模式前先銷毀窗口,
//但在某些顯卡上這么做可能會(huì)使得桌面崩潰。所以還是先禁用全屏模式。
//這將防止桌面出現(xiàn)崩潰,并在Nvidia和3dfx顯卡上都工作的很好!
If Fullscreen Then // 處于全屏模式嗎?
Begin
// 使用ChangeDisplaySettings(NULL,0)回到原始桌面。
// 將NULL作為第一個(gè)參數(shù),
// 0作為第二個(gè)參數(shù)傳遞強(qiáng)制Windows使用當(dāng)前存放在注冊(cè)表中的值
// (缺省的分辨率、色彩深度、刷新頻率,等等)來(lái)有效的恢復(fù)我原始桌面。
// 換回桌面后,還要使得鼠標(biāo)指針重新可見(jiàn)。
ChangeDisplaySettings(devmode(Nil^), 0); // 是的話,切換回桌面
ShowCursor(True); //顯示鼠標(biāo)
End;
//是否擁有著色描述表(hRC)。
If h_RC > 0 Then
//看我們能否釋放它(將 hRC從hDC分開(kāi))。
If (Not wglMakeCurrent(h_DC, 0)) Then
MessageBox(0, 'DC和RC無(wú)法被釋放!', '錯(cuò)誤', MB_OK Or
MB_ICONERROR);
// 能否刪除著色描述表
If (Not wglDeleteContext(h_RC)) Then
Begin
MessageBox(0, '刪除著色描述表失敗!', '錯(cuò)誤', MB_OK Or
MB_ICONERROR);
h_RC := 0;
End;
//是否存在設(shè)備描述表,如果有嘗試釋放它。
If ((h_DC > 0) And (ReleaseDC(h_Wnd, h_DC) = 0)) Then
Begin
MessageBox(0, '釋放設(shè)備描述表失敗!', '錯(cuò)誤', MB_OK Or
MB_ICONERROR);
h_DC := 0;
End;
//是否存在窗口句柄,調(diào)用 DestroyWindow( hWnd )來(lái)嘗試銷毀窗口
If ((h_Wnd <> 0) And (Not DestroyWindow(h_Wnd))) Then
Begin
MessageBox(0, '無(wú)法銷毀窗體!', '錯(cuò)誤', MB_OK Or
MB_ICONERROR);
h_Wnd := 0;
End;
// 注銷窗口類
//這允許我們正常銷毀窗口,接著在打開(kāi)其他窗口時(shí),
//不會(huì)收到諸如"Windows Class already registered"(窗口類已注冊(cè))的錯(cuò)誤消息。
If (Not UnRegisterClass('OpenGL', hInstance)) Then
Begin
MessageBox(0, '無(wú)法注銷窗口類!', '錯(cuò)誤', MB_OK Or
MB_ICONERROR);
hInstance := 0;
End;
End;
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注