天天看點

Nehe第六課

這一課主要講解了OpenGL如何映射紋理。我仔細研究了一下Nehe的源代碼,并且自己嘗試着寫出了可以運作的程式,Nehe代碼的可重用性還是非常高的,當然如果按照我使用win32的程式的習慣,我可能會直接 LoadImage或者LoadBitmap,但是我估計自己是無法寫出像Nehe那樣健壯,移植性的代碼。

下面按照Nehe的課程講解一下具體的步驟

①加載位圖。 

②加載并且設定紋理資源。

③初始化InitGL的時候調用加載紋理資源。

④用紋理繪制三維圖形。

//加載位圖資源
AUX_RGBImageRec *LoadBMP(char *Filename)
{
	FILE *File = NULL;                                          //建立檔案句柄
	if (Filename == NULL)									    //確定檔案路徑名已經提供
	{
		return NULL;
	}
	File = fopen(Filename,"r");								    //嘗試打開檔案
	if (File != NULL)
	{
		fclose(File);                                           //關閉檔案
		return auxDIBImageLoad(Filename);                       //載入位圖并且傳回指針
	}
	return NULL;	
}           
//載入位圖并且轉化成紋理
int LoadGLTextures()
{
	int Status = FALSE;
	AUX_RGBImageRec *TextureImage[1];							//建立紋理的存儲空間
	memset(TextureImage,0,sizeof(void*)*1);						//講指針設定為NULL
	TextureImage[0] = LoadBMP("Data/NeHe.bmp");					//載入位圖
	int k = GetLastError();
	if (TextureImage[0])										
	{
		Status = TRUE;

		glGenTextures(1,&texture[0]);//建立紋理
		glBindTexture(GL_TEXTURE_2D,texture[0]);//使用來自位圖資料生成的典型紋理
		//生成紋理
		glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//線性濾波
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//線性濾波
	}
	
	if (TextureImage[0])//紋理是否存在
	{
		if (TextureImage[0]->data)//紋理圖像是否存在
		{
			free(TextureImage[0]->data);
		}
		free(TextureImage[0]);
	}
	return Status;
}           
int InitGL(GLvoid)												// 此處開始對OpenGL進行所有設定
{
	if (!LoadGLTextures())										//調入紋理載入子例程
	{
		return FALSE;
	}
	
	glEnable(GL_TEXTURE_2D);
	glShadeModel(GL_SMOOTH);									// 啟用陰影平滑
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);						// 黑色背景
	glClearDepth(1.0f);											// 設定深度緩存
	glEnable(GL_DEPTH_TEST);									// 啟用深度測試
	glDepthFunc(GL_LEQUAL);										// 所作深度測試的類型
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// 告訴系統對透視進行修正
	return TRUE;												// 初始化 OK
}           
int DrawGLScene(GLvoid)											// 從這裡開始進行所有的繪制
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear The Screen And The Depth Buffer
	glLoadIdentity();									// Reset The View
	glTranslatef(0.0f,0.0f,-5.0f);

	glRotatef(xrot,1.0f,0.0f,0.0f);
	glRotatef(yrot,0.0f,1.0f,0.0f);
	glRotatef(zrot,0.0f,0.0f,1.0f);

	glBindTexture(GL_TEXTURE_2D, texture[0]);			//選擇紋理

	glBegin(GL_QUADS);
	// Front Face
	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);
	// Back Face
	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);
	// Top Face
	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);
	// Bottom Face
	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);
	// Right face
	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);
	// Left Face
	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();

	xrot+=0.3f;
	yrot+=0.2f;
	zrot+=0.4f;
	return TRUE;	
}           

整個程式的源代碼:

#include <Windows.h>
#include <stdio.h>

#include <gl\glut.h>
#include <gl\glaux.h>
#include <gl\GL.h>
#include <gl\GLU.h>

GLfloat xrot;
GLfloat yrot;
GLfloat zrot;
GLuint  texture[1];												//存儲一個紋理

HGLRC           hRC=NULL;							            // 視窗着色描述表句柄
HDC             hDC=NULL;										// OpenGL渲染描述表句柄
HWND            hWnd=NULL;										// 儲存我們的視窗句柄
HINSTANCE       hInstance;										// 儲存程式的執行個體

bool	keys[256];												// 儲存鍵盤按鍵的數組
bool	active=TRUE;											// 視窗的活動标志,預設為TRUE
bool	fullscreen=TRUE;										// 全屏标志預設,預設設定成全屏模式

float	rtri = 0.0f;
float   rquads = 0.0f;

AUX_RGBImageRec *LoadBMP(char *Filename);                       //加載位圖資源
int LoadGLTextures();
LRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);	
GLvoid ReSizeGLScene(GLsizei width, GLsizei height);			// 重置OpenGL視窗大小
int InitGL(GLvoid);												// 此處開始對OpenGL進行所有設定
int DrawGLScene(GLvoid);										// 從這裡開始進行所有的繪制
GLvoid KillGLWindow(GLvoid);									// 正常銷毀視窗

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
	GLuint		PixelFormat;									// 儲存查找比對的結果
	WNDCLASS	wc;												// 視窗類結構
	DWORD		dwExStyle;										// 擴充視窗風格
	DWORD		dwStyle;										// 視窗風格

	RECT WindowRect;											// 取得矩形的左上角和右下角的坐标值
	WindowRect.left=(long)0;									// 将Left   設為 0
	WindowRect.right=(long)width;								// 将Right  設為要求的寬度
	WindowRect.top=(long)0;										// 将Top    設為 0
	WindowRect.bottom=(long)height;								// 将Bottom 設為要求的高度

	fullscreen=fullscreenflag;									// 設定全局全屏标志

	hInstance			= GetModuleHandle(NULL);				// 取得我們視窗的執行個體
	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	// 移動時重畫,并為視窗取得DC
	wc.lpfnWndProc		= (WNDPROC) WndProc;					// WndProc處理消息
	wc.cbClsExtra		= 0;									// 無額外視窗資料
	wc.cbWndExtra		= 0;									// 無額外視窗資料
	wc.hInstance		= hInstance;							// 設定執行個體
	wc.hIcon			= LoadIcon(NULL, IDI_WINLOGO);			// 裝入預設圖示
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);			// 裝入滑鼠指針
	wc.hbrBackground	= NULL;									// GL不需要背景
	wc.lpszMenuName		= NULL;									// 不需要菜單
	wc.lpszClassName	= TEXT("OpenG");		

	if (!RegisterClass(&wc))									// 嘗試注冊視窗類
	{
		MessageBox(NULL,TEXT("注冊視窗失敗"),TEXT("錯誤"),MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// 退出并傳回FALSE
	}

	if (fullscreen)												// 要嘗試全屏模式嗎?
	{
		DEVMODE dmScreenSettings;								// 裝置模式
		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));	// 確定記憶體清空為零
		dmScreenSettings.dmSize=sizeof(dmScreenSettings);		// Devmode 結構的大小
		dmScreenSettings.dmPelsWidth	= width;				// 所選螢幕寬度
		dmScreenSettings.dmPelsHeight	= height;				// 所選螢幕高度
		dmScreenSettings.dmBitsPerPel	= bits;					// 每象素所選的色彩深度
		dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

		// 嘗試設定顯示模式并傳回結果。注: CDS_FULLSCREEN 移去了狀态條。
		if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
		{
			// 若模式失敗,提供兩個選項:退出或在視窗内運作。
			if (MessageBox(NULL,TEXT("全屏模式在目前顯示卡上設定失敗!\n使用視窗模式?"),TEXT("NeHe G"),MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
			{
				fullscreen=FALSE;								// 選擇視窗模式(Fullscreen=FALSE)
			}
			else
			{
				// 彈出一個對話框,告訴使用者程式結束
				MessageBox(NULL,TEXT("程式将被關閉"),TEXT("錯誤"),MB_OK|MB_ICONSTOP);
				return FALSE;									//  退出并傳回 FALSE
			}
		}
	}

	if (fullscreen)												// 仍處于全屏模式嗎?
	{
		dwExStyle=WS_EX_APPWINDOW;								// 擴充窗體風格
		dwStyle=WS_POPUP;										// 窗體風格
		ShowCursor(FALSE);										// 隐藏滑鼠指針
	}
	else
	{
		dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;			// 擴充窗體風格
		dwStyle=WS_OVERLAPPEDWINDOW;							//  窗體風格
	}

	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);	// 調整視窗達到真正要求的大小

	if (!(hWnd=CreateWindowEx(	dwExStyle,						// 擴充窗體風格
								TEXT("OpenG"),					// 類名字
								title,							// 視窗标題
								WS_CLIPSIBLINGS |				// 必須的窗體風格屬性
								WS_CLIPCHILDREN |				// 必須的窗體風格屬性
								dwStyle,						// 選擇的窗體屬性
								0, 0,								// 視窗位置
								WindowRect.right-WindowRect.left,	// 計算調整好的視窗寬度
								WindowRect.bottom-WindowRect.top,	// 計算調整好的視窗高度
								NULL,							// 無父視窗
								NULL,							// 無菜單
								hInstance,						// 執行個體
								NULL)))							// 不向WM_CREATE傳遞任何東東
	{
		KillGLWindow();											// 重置顯示區
		MessageBox(NULL,TEXT("不能建立一個視窗裝置描述表"),TEXT("錯誤"),MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// 傳回 FALSE
	}

	static	PIXELFORMATDESCRIPTOR pfd=							// /pfd 告訴視窗我們所希望的東東,即視窗使用的像素格式
	{
		sizeof(PIXELFORMATDESCRIPTOR),							// 上述格式描述符的大小
		1,														// 版本号
		PFD_DRAW_TO_WINDOW |									// 格式支援視窗
		PFD_SUPPORT_OPENGL |									// 格式必須支援OpenGL
		PFD_DOUBLEBUFFER,										// 必須支援雙緩沖
		PFD_TYPE_RGBA,											// 申請 RGBA 格式
		bits,													// 標明色彩深度
		0, 0, 0, 0, 0, 0,										// 忽略的色彩位
		0,														// 無Alpha緩存
		0,														// 忽略Shift Bit
		0,														// 無累加緩存
		0, 0, 0, 0,												// 忽略聚集位
		16,														// 16位 Z-緩存 (深度緩存)
		0,														// 無蒙闆緩存
		0,														// 無輔助緩存
		PFD_MAIN_PLANE,											// 主繪圖層
		0,														// Reserved
		0, 0, 0													// 忽略層遮罩
	};
			
	if (!(hDC=GetDC(hWnd)))										// 取得裝置描述表了麼?
	{
		KillGLWindow();											// 重置顯示區
		MessageBox(NULL,TEXT("不能建立一種相比對的像素格式"),TEXT("錯誤"),MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// 傳回 FALSE
	}

	if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))				// Windows 找到相應的象素格式了嗎?
	{
		KillGLWindow();											// 重置顯示區
		MessageBox(NULL,TEXT("不能設定像素格式"),TEXT("錯誤"),MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// 傳回 FALSE
	}

	if(!SetPixelFormat(hDC,PixelFormat,&pfd))					// 能夠設定象素格式麼?
	{
		KillGLWindow();											// 重置顯示區
		MessageBox(NULL,TEXT("不能設定像素格式"),TEXT("錯誤"),MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// 傳回 FALSE
	}

	if (!(hRC=wglCreateContext(hDC)))							// 能否取得着色描述表?
	{
		KillGLWindow();											// 重置顯示區
		MessageBox(NULL,TEXT("不能建立OpenGL渲染描述表"),TEXT("錯誤"),MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// 傳回 FALSE
	}
		
	if(!wglMakeCurrent(hDC,hRC))								// 嘗試激活着色描述表
	{
		KillGLWindow();											// 重置顯示區
		MessageBox(NULL,TEXT("不能激活目前的OpenGL渲然描述表"),TEXT("錯誤"),MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// 傳回 FALSE
	}

	ShowWindow(hWnd,SW_SHOW);									// 顯示視窗
	SetForegroundWindow(hWnd);									// 略略提高優先級
	SetFocus(hWnd);												// 設定鍵盤的焦點至此視窗
	ReSizeGLScene(width, height);								// 設定透視 GL 螢幕

	if (!InitGL())												// 初始化建立的GL視窗
	{
		KillGLWindow();											// 重置顯示區
		MessageBox(NULL,TEXT("Initialization Failed."),TEXT("ERROR"),MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// 傳回 FALSE
	}

	return TRUE;												// 成功
}

LRESULT CALLBACK WndProc(	HWND	hWnd,						// 視窗的句柄
							UINT	uMsg,						// 視窗的消息
							WPARAM	wParam,						// 附加的消息内容
							LPARAM	lParam)						// 附加的消息内容
{
	switch (uMsg)												// 檢查Windows消息
	{
	case WM_ACTIVATE:											// 監視視窗激活消息
		{
			if (!HIWORD(wParam))								// 檢查最小化狀态
			{
				active=TRUE;									// 程式處于激活狀态
			}
			else
			{
				active=FALSE;									// 程式不再激活
			}

			return 0;											// 傳回消息循環
		}

	case WM_SYSCOMMAND:											// 系統中斷指令
		{		
			switch (wParam)										// 檢查系統調用
			{
			case SC_SCREENSAVE:									// 屏保要運作?
			case SC_MONITORPOWER:								// 顯示器要進入節電模式?
				return 0;										// 阻止發生
			}
			break;												// 退出
		}

	case WM_CLOSE:												// 收到Close消息?
		{
			PostQuitMessage(0);									// 發出退出消息
			return 0;											// 傳回
		}		

	case WM_KEYDOWN:											// 有鍵按下麼?
		{
			keys[wParam] = TRUE;								// 如果是,設為TRUE
			return 0;											// 傳回
		}

	case WM_KEYUP:												// 有鍵放開麼?
		{
			keys[wParam] = FALSE;								// 如果是,設為FALSE
			return 0;											// 傳回
		}

	case WM_SIZE:												// 調整OpenGL視窗大小
		{
			ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));		// LoWord=Width,HiWord=Height
			return 0;											// 傳回
		}
	}
	// 向 DefWindowProc傳遞所有未處理的消息。
	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

int WINAPI WinMain(	HINSTANCE	hInstance,						// 目前視窗執行個體
					HINSTANCE	hPrevInstance,					// 前一個視窗執行個體
					LPSTR		lpCmdLine,						// 指令行參數
					int		    nCmdShow)						// 視窗顯示狀态
{
	MSG	msg;													// Windowsx消息結構
	BOOL	done=FALSE;											// 用來退出循環的Bool 變量
	// 提示使用者選擇運作模式
	if (MessageBox(NULL,TEXT("你想在全屏模式下運作麼?"), TEXT("設定全屏模式"),MB_YESNO|MB_ICONQUESTION)==IDNO)
	{
		fullscreen=FALSE;										// FALSE為視窗模式
	}
	// 建立OpenGL視窗
	if (!CreateGLWindow(TEXT("My OpenGL"),640,480,16,fullscreen))
	{
		return 0;												// 失敗退出
	}
	while(!done)												// 保持循環直到 done=TRUE
	{
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))				// 有消息在等待嗎?
		{
			if (msg.message==WM_QUIT)							// 收到退出消息?
			{
				done=TRUE;										// 是,則done=TRUE
			}
			else												// 不是,處理視窗消息
			{
				TranslateMessage(&msg);							// 翻譯消息
				DispatchMessage(&msg);							// 發送消息
			}
		}
		else													// 如果沒有消息
		{
			// 繪制場景。監視ESC鍵和來自DrawGLScene()的退出消息
			if (active)											// 程式激活的麼?
			{
				if (keys[VK_ESCAPE])							// ESC 按下了麼?
				{
					done=TRUE;									// ESC 發出退出信号
				}
				else											// 不是退出的時候,重新整理螢幕
				{
					DrawGLScene();								// 繪制場景
					SwapBuffers(hDC);							// 交換緩存 (雙緩存)
				}			
			}
			if (keys[VK_F1])									// F1鍵按下了麼?
			{
				keys[VK_F1]=FALSE;								// 若是,使對應的Key數組中的值為 FALSE
				KillGLWindow();									// 銷毀目前的視窗
				fullscreen=!fullscreen;							// 切換 全屏 / 視窗 模式
				// 重建 OpenGL 視窗
				if (!CreateGLWindow("My OpenGL",640,480,16,fullscreen))
				{
					return 0;									// 如果視窗未能建立,程式退出
				}
			}
		}
	}
	// 關閉程式
	KillGLWindow();												// 銷毀視窗
	return (msg.wParam);										// 退出程式
}

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)				// 重置OpenGL視窗大小
{
	if (height==0)												// 防止被零除
	{
		height=1;												// 将Height設為1
	}

	glViewport(0, 0, width, height);							// 重置目前的視口
	glMatrixMode(GL_PROJECTION);								// 選擇投影矩陣
	glLoadIdentity();											// 重置投影矩陣

	// 設定視口的大小
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

	glMatrixMode(GL_MODELVIEW);									// 選擇模型觀察矩陣
	glLoadIdentity();											// 重置模型觀察矩陣
}

int InitGL(GLvoid)												// 此處開始對OpenGL進行所有設定
{
	if (!LoadGLTextures())										//調入紋理載入子例程
	{
		return FALSE;
	}
	
	glEnable(GL_TEXTURE_2D);
	glShadeModel(GL_SMOOTH);									// 啟用陰影平滑
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);						// 黑色背景
	glClearDepth(1.0f);											// 設定深度緩存
	glEnable(GL_DEPTH_TEST);									// 啟用深度測試
	glDepthFunc(GL_LEQUAL);										// 所作深度測試的類型
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// 告訴系統對透視進行修正
	return TRUE;												// 初始化 OK
}

int DrawGLScene(GLvoid)											// 從這裡開始進行所有的繪制
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear The Screen And The Depth Buffer
	glLoadIdentity();									// Reset The View
	glTranslatef(0.0f,0.0f,-5.0f);

	glRotatef(xrot,1.0f,0.0f,0.0f);
	glRotatef(yrot,0.0f,1.0f,0.0f);
	glRotatef(zrot,0.0f,0.0f,1.0f);

	glBindTexture(GL_TEXTURE_2D, texture[0]);			//選擇紋理

	glBegin(GL_QUADS);
	// Front Face
	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);
	// Back Face
	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);
	// Top Face
	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);
	// Bottom Face
	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);
	// Right face
	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);
	// Left Face
	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();

	xrot+=0.3f;
	yrot+=0.2f;
	zrot+=0.4f;
	return TRUE;	
}


GLvoid KillGLWindow(GLvoid)										// 正常銷毀視窗
{				
	if (fullscreen)												// 我們處于全屏模式嗎?
	{
		ChangeDisplaySettings(NULL,0);							// 是的話,切換回桌面
		ShowCursor(TRUE);										// 顯示滑鼠指針
	}

	if (hRC)													// 我們擁有OpenGL渲染描述表嗎?
	{
		if (!wglMakeCurrent(NULL,NULL))							// 我們能否釋放DC和RC描述表?
		{
			MessageBox(NULL,TEXT("釋放DC或RC失敗。"),TEXT("關閉錯誤"),MB_OK | MB_ICONINFORMATION);
		}
		if (!wglDeleteContext(hRC))								// 我們能否删除RC?
		{
			MessageBox(NULL,TEXT("釋放RC失敗。"),TEXT("關閉錯誤"),MB_OK | MB_ICONINFORMATION);
		}
		hRC=NULL;												// 将RC設為 NULL
	}

	if (hDC && !ReleaseDC(hWnd,hDC))							// 我們能否釋放 DC?
	{
		MessageBox(NULL,TEXT("釋放DC失敗。"),TEXT("關閉錯誤"),MB_OK | MB_ICONINFORMATION);
		hDC=NULL;												// 将 DC 設為 NULL
	}

	if (hWnd && !DestroyWindow(hWnd))							// 能否銷毀視窗?
	{
		MessageBox(NULL,TEXT("釋放視窗句柄失敗。"),TEXT("關閉錯誤"),MB_OK | MB_ICONINFORMATION);
		hWnd=NULL;												// 将 hWnd 設為 NULL
	}

	if (!UnregisterClass(TEXT("OpenG"),hInstance))				// 能否登出類?
	{
		MessageBox(NULL,TEXT("不能登出視窗類。"),TEXT("關閉錯誤"),MB_OK | MB_ICONINFORMATION);
		hInstance=NULL;											// 将 hInstance 設為 NULL
	}
}
//加載位圖資源
AUX_RGBImageRec *LoadBMP(char *Filename)
{
	FILE *File = NULL;                                          //建立檔案句柄
	if (Filename == NULL)									    //確定檔案路徑名已經提供
	{
		return NULL;
	}
	File = fopen(Filename,"r");								    //嘗試打開檔案
	if (File != NULL)
	{
		fclose(File);                                           //關閉檔案
		return auxDIBImageLoad(Filename);                       //載入位圖并且傳回指針
	}
	return NULL;	
}
//載入位圖并且轉化成紋理
int LoadGLTextures()
{
	int Status = FALSE;
	AUX_RGBImageRec *TextureImage[1];							//建立紋理的存儲空間
	memset(TextureImage,0,sizeof(void*)*1);						//講指針設定為NULL
	TextureImage[0] = LoadBMP("Data/NeHe.bmp");					//載入位圖
	int k = GetLastError();
	if (TextureImage[0])										
	{
		Status = TRUE;

		glGenTextures(1,&texture[0]);//建立紋理
		glBindTexture(GL_TEXTURE_2D,texture[0]);//使用來自位圖資料生成的典型紋理
		//生成紋理
		glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//線性濾波
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//線性濾波
	}
	
	if (TextureImage[0])//紋理是否存在
	{
		if (TextureImage[0]->data)//紋理圖像是否存在
		{
			free(TextureImage[0]->data);
		}
		free(TextureImage[0]);
	}
	return Status;
}