NO IMAGE

程式連結點選開啟連結

必須啟用紋理對映
glEnable(GL_TEXTURE_2D);//啟用紋理對映

AUX_RGBImageRec在glaux.h中宣告的

/*

** RGB Image Structure
*/
typedef struct _AUX_RGBImageRec {
  GLint sizeX, sizeY;
  unsigned char *data;

} AUX_RGBImageRec;

#include <windows.h>		// Windows的標頭檔案
#include <gl/glew.h>		// 包含最新的gl.h,glu.h庫
#include <gl/glut.h>		// 包含OpenGL實用庫
#include <gl/glaux.h>		// GLaux庫的標頭檔案
#include <stdio.h>			// 標準輸入/輸出庫的標頭檔案
GLfloat xrot;
GLfloat yrot;
GLfloat zrot;
GLuint texture[1];			//儲存紋理,如果紋理大於1個改為相應數值
HGLRC hRC=NULL;						//視窗著色描述表控制代碼
HDC hDC=NULL;						//裝置渲染描述表控制代碼
HWND hWND=NULL;						//視窗控制代碼
HINSTANCE hInstance;				//儲存程式的例項
bool keys[256];
bool active=TRUE;					//視窗的活動狀態,預設為true
bool fullscreen=TRUE;				//全屏的預設狀態=true
GLfloat rtri=7;						//用於三角形角度
GLfloat rquad=45;						//用於四邊形角度
LRESULT CALLBACK WndProc(HWND, UINT,WPARAM, LPARAM);
/* 在 ReSizeGLScene() 之前,我們增加了下面這一段程式碼。這段程式碼用來載入點陣圖檔案。
* 如果檔案不存在,返回 NULL 告知程式無法載入點陣圖。
* 關於用作紋理的影象。影象的寬和高必須是2的n次方;寬度和高度最小必須是64象素;
* 並且出於相容性的原因,影象的寬度和高度不應超過256象素。如果您的原始素材的寬度
* 和高度不是64,128,256象素的話,使用影象處理軟體重新改變影象的大小。*/
AUX_RGBImageRec *LoadBMP(char*Filename)
{
// 首先,我們建立一個檔案控制代碼。控制代碼是個用來鑑別資源的數值,它使程式能夠
//訪問此資源。我們開始先將控制代碼設為 NULL 。
FILE *File=NULL;
if (!Filename)		//確保檔名已提供
{
return NULL;
}
File=fopen(Filename,"r");
if (File)// 檔案存在麼?
{
fclose(File);
return auxDIBImageLoad(Filename);	// 載入點陣圖並返回指標
}
return NULL;
}
int LoadGLTextures()//載入點陣圖(呼叫上面的程式碼)並轉換成紋理
{
//然後設定一個叫做 Status 的變數。我們使用它來跟蹤是否能夠載入點陣圖以及能否建立紋理。 
//Status 預設設為 FALSE (表示沒有載入或建立任何東東)。
int Status=FALSE;
//建立儲存點陣圖的影象記錄。次記錄包含點陣圖的寬度、高度和資料。
AUX_RGBImageRec *TextureImage[1];	// 建立紋理的儲存空間
//清除影象記錄,確保其內容為空
memset(TextureImage,0,sizeof(void *)*1);				// 將指標設為 NULL
if (TextureImage[0]=LoadBMP("Data/Nehe.bmp"))
{
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 )。引數“0”代表影象的詳細程度,
通常就由它為零去了。引數三是資料的成分數。因為影象是由紅色資料,綠色資料,藍色資料
三種組分組成。 TextureImage[0]->sizeX 是紋理的寬度。如果您知道寬度,您可以在這裡填入,
但計算機可以很容易的為您指出此值。 TextureImage[0]->sizey 是紋理的高度。引數零是邊框
的值,一般就是“0”。 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_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//線性濾波
}
/*
現在我們釋放前面用來存放點陣圖資料的記憶體。我們先檢視點陣圖資料是否存放在此處。如果是的話,再檢視
資料是否已經儲存。如果已經儲存的話,刪了它。接著再釋放 TextureImage[0] 影象結構以保證所有
的記憶體都能釋放。
*/
if (TextureImage[0])//紋理是否存在
{
if (TextureImage[0]->data)//紋理影象是否存在
{
free(TextureImage[0]->data);//釋放紋理影象佔用的記憶體
}
free(TextureImage[0]);//釋放影象結構
}
return Status;
}
GLvoid ReSizeGLScene(GLsizei width,GLsizei height)
{
if (height==0)
{
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);//y軸傾斜角,寬高比,z軸近距>0,z軸遠距》近距》0
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();				//重置模型檢視矩陣
}
int InitGL(GLvoid)					//開始對GL進行所有設定
{
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;
}
//繪圖工作
int DrawGLScene(GLvoid)
{
//清除螢幕和深度快取
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//重置模型檢視矩陣
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f);//移入螢幕5個單位
//下面三行使立方體繞XYZ軸旋轉
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[ 所使用紋理對應的數字 ]) 選擇要繫結
的紋理。當您想改變紋理時,應該繫結新的紋理。有一點值得指出的是,您不能在
glBegin() 和 glEnd() 之間繫結紋理,必須在 glBegin() 之前或 glEnd() 之後
繫結。注意我們在後面是如何使用 glBindTexture 來指定和繫結紋理的。                                                                     */
/************************************************************************/
glBindTexture(GL_TEXTURE_2D,texture[0]);//選擇紋理
/************************************************************************/
/* 為了將紋理正確的對映到四邊形上,您必須將紋理的右上角對映到四邊形的右上角,
紋理的左上角對映到四邊形的左上角,紋理的右下角對映到四邊形的右下角,紋理的
左下角對映到四邊形的左下角。如果對映錯誤的話,影象顯示時可能上下顛倒,側向
一邊或者什麼都不是。
glTexCoord2f 的第一個引數是X座標。0.0f 是紋理的左側. 0.5f 是紋理的中點, 
1.0f 是紋理的右側。 glTexCoord2f 的第二個引數是Y座標。 0.0f 是紋理的底部。
0.5f 是紋理的中點, 1.0f 是紋理的頂部。
所以紋理的左上座標是 X:0.0f,Y:1.0f ,四邊形的左上頂點是 X: -1.0f,Y:1.0f 。
其餘三點依此類推。
*/
/************************************************************************/
glBegin(GL_QUADS);
//頂面 藍色
//glColor3f(0.0f,0.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);//右下
//底面
//	glColor3f(1.0f,0.5f,0.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,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);			// 四邊形的右下頂點(前面)
//後面
//	glColor3f(1.0f,1.0f,0.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);			// 四邊形的右下頂點(後面)
//左面
//glColor3f(0.0f,1.0f,0.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);			// 四邊形的右下頂點(左面)
//右面
//glColor3f(1.0f,0.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);			// 四邊形的右下頂點(右面)
glEnd();
rtri =0.2f;
//rquad =0.1f;
xrot =0.3f;
yrot =0.2f;
zrot =0.4f;
return TRUE;
}
//程式退出之前呼叫 依次釋放著色描述表RC,裝置描述表DC和視窗控制代碼
GLvoid KillGLWindow(GLvoid)
{
if (fullscreen)
{
ChangeDisplaySettings(NULL,0);  //Windows API 把預設顯示裝置的設定改變為由第一個引數設定的圖形模式
ShowCursor(TRUE);				//Window32API 顯示滑鼠
}
if (hRC)		//是否擁有渲染描述表
{
if (!wglMakeCurrent(NULL,NULL))
{
MessageBox(NULL,"釋放DC或RC失敗","Shutdown Error",MB_OK|MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC))		
{
MessageBox(NULL,"釋放RC失敗","Shutdown Error",MB_OK|MB_ICONINFORMATION);
}
hRC=NULL;					//將hRC設為NULL
}
if (hDC&&!ReleaseDC(hWND,hDC))
{
MessageBox(NULL,"不能釋放DC失敗","Shutdown Error",MB_OK|MB_ICONINFORMATION);
hDC=NULL;
}
if (hWND&&!DestroyWindow(hWND))
{
MessageBox(NULL,"釋放視窗控制代碼失敗","Shutdown Error",MB_OK|MB_ICONINFORMATION);
hWND=NULL;
}
if (!UnregisterClass("OpenGL",hInstance))
{
MessageBox(NULL,"不能登出視窗類","Shutdown Error",MB_OK|MB_ICONINFORMATION);
hInstance=NULL;
}
}
//建立OpenGL視窗  視窗標題 寬 高 顏色位 全屏標誌
BOOL CreateGLWindow(char* title,int width,int height,int bits,bool fullscreenflag)
{
//儲存Windows相匹配的畫素格式值變數
GLuint PixelFormat;
//視窗類結構
WNDCLASS wc;
DWORD dwStyle;//視窗風格
DWORD dwExStyle;//擴充套件視窗風格
RECT WindowRect;
WindowRect.left=(long)0;
WindowRect.right=(long)width;
WindowRect.top=(long)0;
WindowRect.bottom=(long)height;
fullscreen=fullscreenflag;
hInstance=GetModuleHandle(NULL);//獲取一個應用程式或動態連結庫的模組控制代碼 ,NULL返回自身應用程式控制代碼
wc.style=CS_VREDRAW|CS_HREDRAW|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="OpenGL";						//設定類名字
//註冊視窗類
if (!RegisterClass(&wc))
{
MessageBox(NULL,"註冊視窗失敗"," Error",MB_OK|MB_ICONEXCLAMATION);//EXCLAMATION感嘆號
return FALSE;
}
if (fullscreen)//全屏模式
{
DEVMODE dmScreenSettings;					//裝置模式
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));//確保記憶體清空為0
dmScreenSettings.dmSize=sizeof(dmScreenSettings);	//DEVMODE結構的大小
dmScreenSettings.dmPelsWidth=width;
dmScreenSettings.dmPelsHeight=height;				//所選螢幕高度
dmScreenSettings.dmBitsPerPel=bits;					//每畫素顏色數
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSHEIGHT|DM_PELSWIDTH;
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// 若模式失敗,提供兩個選項:退出或在視窗內執行。
if (MessageBox(NULL,"全屏模式在當前顯示卡上設定失敗!\n使用視窗模式","Nehe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=false;
}
else//使用者選擇退出
{
MessageBox(NULL,"程式將被關閉","Error",MB_OK|MB_ICONSTOP);
return 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);	//Windows API真正適合視窗
if (!(hWND=CreateWindowEx(dwExStyle,
"OpenGL",
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,"不能建立視窗","Error",MB_OK|MB_ICONEXCLAMATION);
return 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,"不能建立一種相匹配的畫素格式","錯誤",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
{
KillGLWindow();
MessageBox(NULL,"不能建立畫素格式","錯誤",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd))				// 能夠設定象素格式麼?
{
KillGLWindow();							// 重置顯示區
MessageBox(NULL,"不能設定畫素格式","錯誤",MB_OK|MB_ICONEXCLAMATION);
return FALSE;							// 返回 FALSE
}
if (!(hRC=wglCreateContext(hDC)))
{
KillGLWindow();							// 重置顯示區
MessageBox(NULL,"不能建立OpenGL渲染描述表","錯誤",MB_OK|MB_ICONEXCLAMATION);
return FALSE;	
}
if (!wglMakeCurrent(hDC,hRC))
{
KillGLWindow();							// 重置顯示區
MessageBox(NULL,"不能啟用當前的OpenGL渲然描述表","錯誤",MB_OK|MB_ICONEXCLAMATION);
return FALSE;		
}
ShowWindow(hWND,SW_SHOW);
SetForegroundWindow(hWND);					//提高優先順序
SetFocus(hWND);								//設定焦點
ReSizeGLScene(width,height);
if (!InitGL())								// 初始化新建的GL視窗
{
KillGLWindow();							// 重置顯示區
MessageBox(NULL,"Initialization Failed.","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;						// 返回
}
}
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,"你想在全屏模式下執行麼?", "設定全屏模式",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen=FALSE;						// FALSE為視窗模式
}
if (!CreateGLWindow("NeHe's 3D空間",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								// 如果沒有訊息
{
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("NeHe's 3D空間",640,480,16,fullscreen))
{
return 0;				// 如果視窗未能建立,程式退出
}
}
}
}
KillGLWindow();								// 銷燬視窗
return (msg.wParam);							// 退出程式
}