第01課 OpenGL窗口(1)

教程的這一節在2000年一月徹底重寫了一遍。將會教您如何設置一個 OpenGL窗口。它可以只是一個窗口或是全屏幕的、可以任意 大小、任意色彩深度。此處的代碼很穩定且很強大,您可以在您所有的OpenGL項目中使用。我所有的教程都將基於此節的代碼!所有的錯誤都有被報告。所以應該沒有內存泄漏,代碼也很容易閱讀和修改。感謝Fredric Echols對代碼所做的修改!


現在就讓我們直接從代碼開始吧。第一件事是打開VC然後創建一個新工程。如果您不知道如何創建的話,您也許不該學習OpenGL,而應該先學學VC。某些版本的VC需要將 bool 改成 BOOL , true 改成 TRUE , false 改成 FALSE ,請自行修改。


在您創建一個新的Win32程序(不是console控制檯程序)後,您還需要鏈接OpenGL庫文件。在VC中操作如下:Project-> Settings,然後單擊LINK標籤。在"Object/Library Modules"選項中的開始處(在 kernel32.lib 前)增加 OpenGL32.lib GLu32.lib 和 GLaux.lib 後單擊OK按鈕。現在可以開始寫您的OpenGL程序了。


代碼的前4行包括了我們使用的每個庫文件的頭文件。如下所示:

#include <windows.h>		// Header File For Windows   Windows的頭文件
#include <GL/gl.h>			// Header File For The OpenGL32 Library   包含最新的gl.h,glu.h庫
#include <GL/glut.h>			// Header File For The GLu32 Library  包含OpenGL實用庫
//#include <gl\glaux.h>		// Header File For The Glaux Library

接下來您需要設置您計劃在您的程序中使用的所有變量。本節中的例程將創建一個空的OpenGL窗口,因此我們暫時還無需設置大堆的變量。餘下需要設置的變量不多,但十分重要。您將會在您以後所寫的每一個OpenGL程序中用到它們。


第一行設置的變量是Rendering Context(着色描述表)。每一個OpenGL都被連接到一個着色描述表上。着色描述表將所有的OpenGL調用命令連接到Device Context(設備描述表)上。我將OpenGL的着色描述表定義爲 hRC 。要讓您的程序能夠繪製窗口的話,還需要創建一個設備描述表,也就是第二行的內容。Windows的設備描述表被定義爲 hDC 。DC將窗口連接到GDI(Graphics Device Interface圖形設備接口)。而RC將OpenGL連接到DC。第三行的變量 hWnd 將保存由Windows給我們的窗口指派的句柄。最後,第四行爲我們的程序創建了一個Instance(實例)。

HGLRC           hRC=NULL;							// 窗口着色描述表句柄

HDC             hDC=NULL;							// OpenGL渲染描述表句柄

HWND            hWnd=NULL;							// 保存我們的窗口句柄

HINSTANCE       hInstance;							// 保存程序的實例

下面的第一行設置一個用來監控鍵盤動作的數組。有許多方法可以監控鍵盤的動作,但這裏的方法很可靠,並且可以處理多個鍵同時按下的情況。

active 變量用來告知程序窗口是否處於最小化的狀態。如果窗口已經最小化的話,我們可以做從暫停代碼執行到退出程序的任何事情。我喜歡暫停程序。這樣可以使得程序不用在後臺保持運行。
fullscreen 變量的作用相當明顯。如果我們的程序在全屏狀態下運行, fullscreen 的值爲TRUE,否則爲FALSE。這個全局變量的設置十分重要,它讓每個過程都知道程序是否運行在全屏狀態下。

bool	keys[256];								// 保存鍵盤按鍵的數組

bool	active=TRUE;								// 窗口的活動標誌,缺省爲TRUE

bool	fullscreen=TRUE;							// 全屏標誌缺省,缺省設定成全屏模式


現在我們需要先定義WndProc()。必須這麼做的原因是CreateGLWindow()有對WndProc()的引用,但WndProc()在CreateGLWindow()之後纔出現。在C語言中,如果我們想要訪問一個當前程序段之後的過程和程序段的話,必須在程序開始處先申明所要訪問的程序段。所以下面的一行代碼先行定義了WndProc(),使得CreateGLWindow()能夠引用WndProc()。
LRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);				// WndProc的定義

下面的代碼的作用是重新設置OpenGL場景的大小,而不管窗口的大小是否已經改變(假定您沒有使用全屏模式)。甚至您無法改變窗口的大小時(例如您在全屏模式下),它至少仍將運行一次--在程序開始時設置我們的透視圖。OpenGL場景的尺寸將被設置成它顯示時所在窗口的大小。

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)				// 重置OpenGL窗口大小
{
	if (height==0)								// 防止被零除
	{
		height=1;							// 將Height設爲1
	}
	glViewport(0, 0, width, height);					// 重置當前的視口

下面幾行爲透視圖設置屏幕。意味着越遠的東西看起來越小。這麼做創建了一個現實外觀的場景。此處透視按照基於窗口寬度和高度的45度視角來計算。0.1f,100.0f是我們在場景中所能繪製深度的起點和終點。

glMatrixMode(GL_PROJECTION)指明接下來的兩行代碼將影響projection matrix(投影矩陣)。投影矩陣負責爲我們的場景增加透視。 glLoadIdentity()近似於重置。它將所選的矩陣狀態恢復成其原始狀態。調用 glLoadIdentity()之後我們爲場景設置透視圖。
glMatrixMode(GL_MODELVIEW)指明任何新的變換將會影響 modelview matrix(模型觀察矩陣)。模型觀察矩陣中存放了我們的物體訊息。最後我們重置模型觀察矩陣。如果您還不能理解這些術語的含義,請彆着急。在以後的教程裏,我會向大家解釋。只要知道如果您想獲得一個精彩的透視場景的話,必須這麼做。

glMatrixMode(GL_PROJECTION);						// 選擇投影矩陣

	glLoadIdentity();							// 重置投影矩陣

	// 設置視口的大小

	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

	glMatrixMode(GL_MODELVIEW);						// 選擇模型觀察矩陣

	glLoadIdentity();							// 重置模型觀察矩陣
}

接下的代碼段中,我們將對OpenGL進行所有的設置。我們將設置清除屏幕所用的顏色,打開深度緩存,啓用smooth shading(陰影平滑),等等。這個例程直到OpenGL窗口創建之後纔會被調用。此過程將有返回值。但我們此處的初始化沒那麼複雜,現在還用不着擔心這個返回值。

int InitGL(GLvoid)								// 此處開始對OpenGL進行所有設置

{


下一行啓用smooth shading(陰影平滑)。陰影平滑通過多邊形精細的混合色彩,並對外部光進行平滑。我將在另一個教程中更詳細的解釋陰影平滑。
<span style="white-space:pre">	</span>glShadeModel(GL_SMOOTH);						// 啓用陰影平滑

下一行設置清除屏幕時所用的顏色。如果您對色彩的工作原理不清楚的話,我快速解釋一下。色彩值的範圍從0.0f到1.0f。0.0f代表最黑的情況,1.0f就是最亮的情況。glClearColor 後的第一個參數是Red Intensity(紅色分量),第二個是綠色,第三個是藍色。最大值也是1.0f,代表特定顏色分量的最亮情況。最後一個參數是Alpha值。當它用來清除屏幕的時候,我們不用關心第四個數字。現在讓它爲0.0f。我會用另一個教程來解釋這個參數。

通過混合三種原色(紅、綠、藍),您可以得到不同的色彩。希望您在學校裏學過這些。因此,當您使用glClearColor(0.0f,0.0f,1.0f,0.0f),您將用亮藍色來清除屏幕。如果您用 glClearColor(0.5f,0.0f,0.0f,0.0f)的話,您將使用中紅色來清除屏幕。不是最亮(1.0f),也不是最暗 (0.0f)。要得到白色背景,您應該將所有的顏色設成最亮(1.0f)。要黑色背景的話,您該將所有的顏色設爲最暗(0.0f)。

<span style="white-space:pre">	</span>glClearColor(0.0f, 0.0f, 0.0f, 0.0f);					// 黑色背景

接下來的三行必須做的是關於depth buffer(深度緩存)的。將深度緩存設想爲屏幕後面的層。深度緩存不斷的對物體進入屏幕內部有多深進行跟蹤。我們本節的程序其實沒有真正使用深度緩存,但幾乎所有在屏幕上顯示3D場景OpenGL程序都使用深度緩存。它的排序決定那個物體先畫。這樣您就不會將一個圓形後面的正方形畫到圓形上來。深度緩存是OpenGL十分重要的部分。

<span style="white-space:pre">	</span>glClearDepth(1.0f);							// 設置深度緩存

	glEnable(GL_DEPTH_TEST);						// 啓用深度測試

	glDepthFunc(GL_LEQUAL);							// 所作深度測試的類型

接着告訴OpenGL我們希望進行最好的透視修正。這會十分輕微的影響性能。但使得透視圖看起來好一點。

<span style="white-space:pre">	</span>glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// 告訴系統對透視進行修正

最後,我們返回TRUE。如果我們希望檢查初始化是否OK,我們可以查看返回的 TRUE或FALSE的值。如果有錯誤發生的話,您可以加上您自己的代碼返回FALSE。目前,我們不管它。

<span style="white-space:pre">	</span>return TRUE;								// 初始化 OK
}















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章