1. 程式人生 > >NeHe OpenGL教程 第七課:光照和鍵盤 程式碼

NeHe OpenGL教程 第七課:光照和鍵盤 程式碼

#include <windows.h> // Windows的標頭檔案
#include <glew.h> // 包含最新的gl.h,glu.h庫
#include <glut.h> // 包含OpenGL實用庫
#include <stdio.h>       // 標準輸入/輸出庫的標頭檔案
#include <glaux.h>       // GLaux庫的標頭檔案

HGLRC hRC = NULL; // 視窗著色描述表控制代碼
HDC hDC = NULL; // OpenGL渲染描述表控制代碼
HWND hWnd = NULL; // 儲存我們的視窗控制代碼
HINSTANCE hInstance; // 儲存程式的例項 bool keys[256]; // 儲存鍵盤按鍵的陣列 bool active = TRUE; // 視窗的活動標誌,預設為TRUE bool fullscreen = TRUE; // 全屏標誌預設,預設設定成全屏模式 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // WndProc的定義 GLfloat xrot; // X 旋轉 GLfloat yrot; // Y 旋轉 GLfloat xspeed = 0.0f; // X 旋轉速度 GLfloat yspeed =
0.0f; // Y 旋轉速度 GLfloat z=-5.0f; // 深入螢幕的距離 GLuint texture[3]; // 儲存一個紋理 BOOL light; // 光源的開/關 BOOL lp; // L鍵按下了麼? BOOL fp; // F鍵按下了麼? GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; // 環境光引數 GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; // 漫射光引數 GLfloat LightPosition[
]= { 0.0f, 0.0f, 2.0f, 1.0f }; // 光源位置 GLuint filter; // 濾波型別 GLvoid ReSizeGLScene(GLsizei width, GLsizei height) { // 防止被零除 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();// 重置模型觀察矩陣 } AUX_RGBImageRec *LoadBMP(char *Filename) // 載入點陣圖圖象 { FILE *File=NULL; // 檔案控制代碼 if (!Filename) // 確保檔名已提供 { return NULL; // 如果沒提供,返回 NULL } File=fopen(Filename,"r"); // 嘗試開啟檔案 if (File) // 檔案存在麼? { fclose(File); // 關閉控制代碼 return auxDIBImageLoad(Filename); // 載入點陣圖並返回指標 } return NULL; // 如果載入失敗,返回 NULL } int LoadGLTextures() // 載入點陣圖(呼叫上面的程式碼)並轉換成紋理 { int Status=FALSE; // 狀態指示器 AUX_RGBImageRec *TextureImage[1]; // 建立紋理的儲存空間 memset(TextureImage,0,sizeof(void *)*1); // 將指標設為 NULL // 載入點陣圖,檢查有無錯誤,如果點陣圖沒找到則退出 if (TextureImage[0]=LoadBMP("bitmap1.bmp")) { Status=TRUE; // 將 Status 設為 TRUE // 建立 Nearest 濾波貼圖 glBindTexture(GL_TEXTURE_2D, texture[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); // 建立線性濾波紋理 glBindTexture(GL_TEXTURE_2D, texture[1]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); // 建立 MipMapped 紋理 glBindTexture(GL_TEXTURE_2D, texture[2]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); } if (TextureImage[0]) // 紋理是否存在 { if (TextureImage[0]->data) // 紋理影象是否存在 { free(TextureImage[0]->data); // 釋放紋理影象佔用的記憶體 } free(TextureImage[0]); // 釋放影象結構 } return Status; // 返回 Status } int InitGL(GLvoid) // 此處開始對OpenGL進行所有設定 { if (!LoadGLTextures()) // 呼叫紋理載入子例程 { return FALSE; // 如果未能載入,返回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); // 真正精細的透視修正 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // 設定環境光 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // 設定漫射光 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // 設定光源位置 glEnable(GL_LIGHT1); return TRUE; // 初始化 OK } int DrawGLScene(GLvoid) // 從這裡開始進行所有的繪製 { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除螢幕和深度快取 glLoadIdentity(); // 重置當前的模型觀察矩陣 glTranslatef(0.0f,0.0f,z); // 移入/移出螢幕 z 個單位 glRotatef(xrot,1.0f,0.0f,0.0f); // 繞X軸旋轉 glRotatef(yrot,0.0f,1.0f,0.0f); // 繞Y軸旋轉 glBindTexture(GL_TEXTURE_2D, texture[filter]); // 選擇由filter決定的紋理 glBegin(GL_QUADS); // 開始繪製四邊形 // 前側面 glNormal3f( 0.0f, 0.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); // 後側面 glNormal3f( 0.0f, 0.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); // 頂面 glNormal3f( 0.0f, 1.0f, 0.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); // 底面 glNormal3f( 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); // 右側面 glNormal3f( 1.0f, 0.0f, 0.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); // 左側面 glNormal3f(-1.0f, 0.0f, 0.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); glEnd(); // 四邊形繪製結束 xrot+=xspeed; // xrot 增加 xspeed 單位 yrot+=yspeed; // yrot 增加 yspeed 單位 return TRUE; } GLvoid KillGLWindow(GLvoid) { // 正常銷燬視窗 if (fullscreen) { // 我們處於全屏模式嗎? ChangeDisplaySettings(NULL, 0);// 是的話,切換回桌面 ShowCursor(TRUE); // 顯示滑鼠指標 } if (hRC) { // 我們擁有OpenGL渲染描述表嗎? if (!wglMakeCurrent(NULL, NULL)) { // 我們能否釋放DC和RC描述表? MessageBox(NULL, "釋放DC或RC失敗", "關閉錯誤", MB_OK | MB_ICONINFORMATION); } if (!wglDeleteContext(hRC)) { MessageBox(NULL, "釋放RC失敗。", "關閉錯誤", MB_OK | MB_ICONINFORMATION); } hRC = NULL; } if (hDC && !ReleaseDC(hWnd, hDC)) // 我們能否釋放 DC? { MessageBox(NULL, "釋放DC失敗。", "關閉錯誤", MB_OK | MB_ICONINFORMATION); hDC = NULL; // 將 DC 設為 NULL } if (hWnd && !DestroyWindow(hWnd)) // 能否銷燬視窗? { MessageBox(NULL, "釋放視窗控制代碼失敗。", "關閉錯誤", MB_OK | MB_ICONINFORMATION); hWnd = NULL; // 將 hWnd 設為 NULL } if (!UnregisterClass("OpenG", hInstance)) // 能否登出類? { MessageBox(NULL, "不能登出視窗類。", "關閉錯誤", MB_OK | MB_ICONINFORMATION); hInstance = NULL; // 將 hInstance 設為 NULL } } // 建立OpenGL視窗 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