日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

win32下的OpenGL绘图环境框架

發布時間:2024/3/13 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 win32下的OpenGL绘图环境框架 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Win32OpenGL入門

主要的步驟包括:添加opengl頭文件,庫文件,鍵盤鼠標響應,像素格式設置,opengl環境初始化,繪圖變量設置,創建窗口,窗口大小改變時響應,繪制場景,源文件

1,?新建一個win32項目(注意,不是console程序),在添加過程中,創建一個空的項目,然后,在解決方案資源管理器的源文件樹目錄下,添加一個cpp文件,文件可以命名為mian.cpp

2,?添加繪圖相關的頭文件和庫文件,在新建的main.cpp中,加入如下頭文件:

?

#include <windows.h>???????????????????????????????????????? // Windows的頭文件

#include <gl\gl.h>???????????????????????????????????????????????? // Header File For The OpenGL32 Library

#include <gl\glu.h>?????????????????????????????????????????????? // Header File For The GLu32 Library

#include <gl\glaux.h>????????????????????? // Header File For The Glaux Library

#include <math.h>?????????????????????????????????????????????? // 引入數學函數庫中的Sin

#include <stdio.h>??????????????????????????????????????????????? // Header File For Standard Input/Output

在項目,配置屬性-連接器-輸入的附加依賴項里,加入opengl32.libglu32.libglaux.lib

glut.lib,如圖所示。

3,為創建繪圖窗口,定義基本的相關變量,這些變量在opengl繪圖中,都必須用到。

HGLRC?????????? hRC=NULL;?? // 窗口著色描述表句柄 HDC???????????? hDC=NULL;??? // OpenGL渲染描述表句柄 HWND??????????? hWnd=NULL;??????????????????? // 保存我們的窗口句柄 HINSTANCE?????? hInstance;???? // 保存程序的實例

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

?

4,為響應鍵盤,鼠標等操作,以及窗口活動情況,是否全屏等

bool??????????? keys[256];???????????????????? // 保存鍵盤按鍵的數組 bool??????????? active=TRUE;??????????????? // 窗口的活動標志,缺省為TRUE bool??????????? fullscreen=TRUE;???????? // 全屏標志缺省,缺省設定成全屏模式 GLfloat???????????? rtri;???? // 用于幾何體旋轉的角度

active 變量用來告知程序窗口是否處于最小化的狀態。如果窗口已經最小化的話,我們可以做從暫停代碼執行到退出程序的任何事情。我喜歡暫停程序。這樣可以使得程序不用在后臺保持運行。

fullscreen 變量的作用相當明顯。如果我們的程序在全屏狀態下運行, fullscreen 的值為TRUE,否則為FALSE。這個全局變量的設置十分重要,它讓每個過程都知道程序是否運行在全屏狀態下。

?

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

LRESULT?CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);?? // WndProc的定義

?

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

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();??????????????????????????????????????????????????? // 重置模型觀察矩陣 }

透視圖設置屏幕。意味著越遠的東西看起來越小。這么做創建了一個現實外觀的場景。此處透視按照基于窗口寬度和高度的45度視角來計算。0.1f,100.0f是我們在場景中所能繪制深度的起點和終點。 glMatrixMode(GL_PROJECTION)指明接下來的兩行代碼將影響projection matrix(投影矩陣)。投影矩陣負責為我們的場景增加透視。 glLoadIdentity()近似于重置。它將所選的矩陣狀態恢復成其原始狀態。調用 glLoadIdentity()之后我們為場景設置透視圖。

glMatrixMode(GL_MODELVIEW)指明任何新的變換將會影響 modelview matrix(模型觀察矩陣)。模型觀察矩陣中存放了我們的物體訊息。最后我們重置模型觀察矩陣。如果您還不能理解這些術語的含義,請別著急。在以后的教程里,我會向大家解釋。只要知道如果您想獲得一個精彩的透視場景的話,必須這么做。

?

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

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

GL_SMOOTH陰影平滑通過多邊形精細的混合色彩,并對外部光進行平滑。我將在另一個教程中更詳細的解釋陰影平滑。

深度緩存:將深度緩存設想為屏幕后面的層。深度緩存不斷的對物體進入屏幕內部有多深進行跟蹤。幾乎所有在屏幕上顯示3D場景OpenGL程序都使用深度緩存。它的排序決定那個物體先畫。這樣您就不會將一個圓形后面的正方形畫到圓形上來。深度緩存是OpenGL十分重要的部分。

?

8,繪圖部分。下一段包括了所有的繪圖代碼。任何您所想在屏幕上顯示的東東都將在此段代碼中出現。 這里,繪制了一個簡單的金字塔,每個頂點采用不用的顏色

int DrawGLScene(GLvoid)????????????????????????????????? // 從這里開始進行所有的繪制 { ??????????????????? glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);????? // 清除屏幕和深度緩存 ??????????????????? glLoadIdentity();??????????????????????????????????????????????????? // 重置當前的模型觀察矩陣 ??????????????????? glTranslatef(-1.5f,0.0f,-6.0f);????????????????????????????? // 左移 1.5 單位,并移入屏幕 6.0 ??????????????????? glRotatef(rtri,0.0f,1.0f,0.0f);??????????? // Y軸旋轉金字塔 ? ??????????????????? glBegin(GL_TRIANGLES);????????????????????????????????? // 開始繪制金字塔的各個面 ???????????????????????????????????????? glColor3f(1.0f,0.0f,0.0f);????????????????????????????????????????????????????????? // 紅色 ???????????????????????????????????????? glVertex3f( 0.0f, 1.0f, 0.0f);???????????? // 三角形的上頂點 (前側面) ???????????????????????????????????????? glColor3f(0.0f,1.0f,0.0f);????????????????????????????????????? // 綠色 ???????????????????????????????????????? glVertex3f(-1.0f,-1.0f, 1.0f);??????????????????????????????? // 三角形的左下頂點 (前側面) ???????????????????????????????????????? glColor3f(0.0f,0.0f,1.0f);????????????????????????????????????? // 藍色 ???????????????????????????????????????? glVertex3f( 1.0f,-1.0f, 1.0f);???????????????????????????????? // 三角形的右下頂點 (前側面) ???????????????????????????????????????? glColor3f(1.0f,0.0f,0.0f);????????????????????????????????????? // 紅色 ???????????????????????????????????????? glVertex3f( 0.0f, 1.0f, 0.0f);???????????????????????????????? // 三角形的上頂點 (右側面) ???????????????????????????????????????? glColor3f(0.0f,0.0f,1.0f);????????????????????????????????????? // 藍色 ???????????????????????????????????????? glVertex3f( 1.0f,-1.0f, 1.0f);???????????????????????????????? // 三角形的左下頂點 (右側面) ???????????????????????????????????????? glColor3f(0.0f,1.0f,0.0f);???????????????? // 綠色 ???????????????????????????????????????? glVertex3f( 1.0f,-1.0f, -1.0f);?????????????????????????????? // 三角形的右下頂點 (右側面) ???????????????????????????????????????? glColor3f(1.0f,0.0f,0.0f);????????????????????????????????????? // 紅色 ???????????????????????????????????????? glVertex3f( 0.0f, 1.0f, 0.0f);???????????????????????????????? // 三角形的上頂點 (后側面) ???????????????????????????????????????? glColor3f(0.0f,1.0f,0.0f);????????????????????????????????????????????????????????? // 綠色 ???????????????????????????????????????? glVertex3f( 1.0f,-1.0f, -1.0f);?????????????????????????????? // 三角形的左下頂點 (后側面) ???????????????????????????????????????? glColor3f(0.0f,0.0f,1.0f);????????????????????????????????????????????????????????? // 藍色 ???????????????????????????????????????? glVertex3f(-1.0f,-1.0f, -1.0f);?????????????????????????????? // 三角形的右下頂點 (后側面) ???????????????????????????????????????? glColor3f(1.0f,0.0f,0.0f);????????????????????????????????????????????????????????? // 紅色 ???????????????????????????????????????? glVertex3f( 0.0f, 1.0f, 0.0f);???????????????????????????????? // 三角形的上頂點 (左側面) ???????????????????????????????????????? glColor3f(0.0f,0.0f,1.0f);????????????????????????????????????????????????????????? // 藍色 ???????????????????????????????????????? glVertex3f(-1.0f,-1.0f,-1.0f);??????????????????????????????? // 三角形的左下頂點 (左側面) ???????????????????????????????????????? glColor3f(0.0f,1.0f,0.0f);????????????????????????????????????????????????????????? // 綠色 ???????????????????????????????????????? glVertex3f(-1.0f,-1.0f, 1.0f);??????????????????????????????? // 三角形的右下頂點 (左側面) ??????????????????? glEnd();????? ??????????????????? rtri+=0.2f;?????????????????????? // 增加三角形的旋轉變量 ???????????????????????????????????????????????????????????????????????????????? ??????????????????? return TRUE;????????????????????????????????????????????????????????????????????????????? }

關于繪圖:在opengl里面繪圖,首先要了解的就是坐標原點,OpenGL的坐標原點默認情況下,在屏幕中心。OpenGL的坐標系統是右手坐標系統,默認情況下,屏幕朝上為y,朝左為x,朝外為z。

9,釋放程序的繪圖指針。在程序退出之前調用。KillGLWindow() 的作用是依次釋放著色描述表,設備描述表和窗口句柄。

GLvoid KillGLWindow(GLvoid)????? // 正常銷毀窗口 { ??????????????????? if (fullscreen)???????????????? // 我們處于全屏模式嗎? ??????????????????? { ???????????????????????????????????????? ChangeDisplaySettings(NULL,0);???????????????????? // 是的話,切換回桌面,因為全屏模式直接關閉窗口,可能引發錯誤 ???????????????????????????????????????? ShowCursor(TRUE);??????????????????????????????????????????? // 顯示鼠標指針 ??????????????????? } ??????????????????? if (hRC)?????????????????????????????????????????????????????????????????? // 我們擁有OpenGL渲染描述表嗎? ??????????????????? { ???????????????????????????????????????? if (!wglMakeCurrent(NULL,NULL))?????????????????? // 我們能否釋放DCRC描述表? ???????????????????????????????????????? { ???????????????????????????????????????????????????????????? MessageBox(NULL,"釋放DCRC失敗。","關閉錯誤",MB_OK | MB_ICONINFORMATION); ???????????????????????????????????????? } ???????????????????????????????????????? if (!wglDeleteContext(hRC))?????????? // 我們能否刪除RC? ???????????????????????????????????????? { ???????????????????????????????????????????????????????????? MessageBox(NULL,"釋放RC失敗。","關閉錯誤",MB_OK | MB_ICONINFORMATION); ???????????????????????????????????????? } ???????????????????????????????????????? hRC=NULL;?????????????????????????????????????????????????????????? // RC設為 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 ??????????????????? } }

?

10,創建窗口。此過程返回布爾變量(TRUE FALSE)。他還帶有5個參數:窗口的標題欄,窗口的寬度,窗口的高度,色彩位數(16/24/32),和全屏標志(TRUE --全屏模式, FALSE--窗口模式 )。返回的布爾值告訴我們窗口是否成功創建。

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) { //我們要求Windows為我們尋找相匹配的象素格式時,Windows尋找結束后將模式值保存在變量PixelFormat ??????????????????? 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;// 移動時重畫,并為窗口取得DCCS_OWNDC為窗口創建一個私有的DC。這意味著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????? = "OpenG";???????????????????????????????????????????????????????????? // 設定類名字 ? ??????????????????? if (!RegisterClass(&wc))?????????????????????????????????????? // 嘗試注冊窗口類 ??????????????????? { ???????????????????????????????????????? MessageBox(NULL,"注冊窗口失敗","錯誤",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,"全屏模式在當前顯卡上設置失敗!\n使用窗口模式?","NeHe G",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) ???????????????????????????????????????????????????????????? { ???????????????????????????????????????????????????????????????????????????????? fullscreen=FALSE;// 選擇窗口模式(Fullscreen=FALSE) ???????????????????????????????????????????????????????????? } ???????????????????????????????????????????????????????????? else ???????????????????????????????????????????????????????????? { ???????????????????????????????????????????????????????????????????????????????? // 彈出一個對話框,告訴用戶程序結束 ???????????????????????????????????????????????????????????????????????????????? MessageBox(NULL,"程序將被關閉","錯誤",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,???????????????????????????????????????? // 擴展窗體風格 ????????????????????????????????????????????????????????????????????????????????????????????????????? "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,"不能創建一個窗口設備描述表","錯誤",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,"不能創建一種相匹配的像素格式","錯誤",MB_OK|MB_ICONEXCLAMATION); ???????????????????????????????????????? return FALSE;??????????????????????????????????????????????????????????????????????????? // 返回 FALSE ??????????????????? } ??????????????????? if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))// Windows 找到相應的象素格式了嗎? ??????????????????? { ???????????????????????????????????????? KillGLWindow();??????????????????????????????????????????????????? // 重置顯示區 ???????????????????????????????????????? MessageBox(NULL,"不能設置像素格式","錯誤",MB_OK|MB_ICONEXCLAMATION); ???????????????????????????????????????? return FALSE;??????????????????????????????????????????????????????? // 返回 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;??????????????????????????????????????????????????????????????????????????? // 返回 FALSE ??????????????????? } ??????????????????? if(!wglMakeCurrent(hDC,hRC))???????????????????????? // 嘗試激活著色描述表 ??????????????????? { ???????????????????????????????????????? KillGLWindow();??????????????????????????????? // 重置顯示區 ???????????????????????????????????????? MessageBox(NULL,"不能激活當前的OpenGL渲然描述表","錯誤",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,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION); ???????????????????????????????????????? return FALSE;??????????????????????????????????? // 返回 FALSE ??????????????????? } ??????????????????? return TRUE;????????????????????????????????????????????????????????? // 成功 }

?

11,建立了窗口類之后,我們接下來完成窗口消息處理函數。

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); }

?

12,好了,南西北風都準備好了,現在只差東風。接下來我們來定義東風——程序的入口。調用窗口創建例程,處理窗口消息,并監視人機交互。

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為窗口模式 ??????????????????? } ??????????????????? // 創建OpenGL窗口 /*CreateGLWindow函數的參數依次為標題、寬度、高度、色彩深度,以及全屏標志。就這么簡單!我很欣賞這段代碼的簡潔。如果未能創建成功,函數返回FALSE。程序立即退出。*/ ??????????????????? if (!CreateGLWindow("win32下的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("NeHe's OpenGL 程序框架",640,480,16,fullscreen)) ???????????????????????????????????????????????????????????????????????????????? { ????????????????????????????????????????????????????????????????????????????????????????????????????? return 0;???? // 如果窗口未能創建,程序退出 ???????????????????????????????????????????????????????????????????????????????? } ???????????????????????????????????????????????????????????? } ???????????????????????????????????????? } ??????????????????? } ??????????????????? // 關閉程序 ??????????????????? KillGLWindow();????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? // 銷毀窗口 ??????????????????? return (msg.wParam);?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? // 退出程序 }

雙緩沖繪圖:使用雙緩存可以實現無閃爍的動畫,繪圖領域一個經常用到的技術,特別是大規模場景的繪圖。我們實際上在另一個看不見的"屏幕"上繪圖。當我們交換緩存后,我們當前的屏幕被隱藏,現在看到的是剛才看不到的屏幕。這也是我們看不到場景繪制過程的原因。場景只是即時顯示。

?

13,好了,運行程序

?

?

?

?

?

?

?

?

附:

常見錯誤列表:

1新建的工程如果出現error C2664: MessageBoxW: 不能將參數2 從const char [42]轉換為LPCWSTR這種錯誤, 將項目->配置屬性->常規->字符集改為支持多字節字符集。

2. error LNK2019: 無法解析的外部符號_main,該符號在函數___tmainCRTStartup 中被引用,找到項目->配置屬性->連接器->系統,將子系統修改為Windows (/SUBSYSTEM:WINDOWS)

轉載于:https://www.cnblogs.com/yanhuiw/archive/2010/08/06/1794467.html

總結

以上是生活随笔為你收集整理的win32下的OpenGL绘图环境框架的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。