[OpenGL] 1、环境搭建及最小系统

 

>_<: 首先推荐一个企业版的VC6.0自带OpenGL和DirectX,非常方便:http://pan.baidu.com/s/1mgIAGi8

PS: 要注意这里的OpenGL建立的工程有一点小错误,即:#include <glu.h> #include <gl.h>要在前面加上GL\(因为这两个文件是在include/GL文件夹内的)

此外,还要推荐一个非常好的OpenGL学习网站:http://www.yakergong.net/nehe/

PS: 由于这个网站的作者采用的是另一种Win32架构,用VC6.0默认的模板建立的工程可能有点不同,这里我把如何建立一个他那样的OpenGL的工程给介绍一下:

  1. 直接看创建一个OpenGL窗口的部分,你要建立一个Win32 Application空工程
  2. 建好之后引入OpenGL的动态链接库,Project-> Settings,然后单击LINK标签。在"Object/Library Modules"选项中的开始处(在 kernel32.lib 前)增加 OpenGL32.lib GLu32.lib 和 GLaux.lib 后单击OK按钮。现在可以开始写您的OpenGL程序了。
  3. 建立一个CPP文件放入下面的代码[就是他第一课的代码]
  1 #include <windows.h>                                                // Windows的头文件
  2 #include <GL/glu.h>                                                    // 包含最新的gl.h,glu.h库
  3 #include <GL/gl.h>
  4 #include <GL/glut.h>                                                // 包含OpenGL实用库
  5 
  6 HGLRC           hRC=NULL;                                            // 窗口着色描述表句柄
  7 HDC             hDC=NULL;                                            // OpenGL渲染描述表句柄
  8 HWND            hWnd=NULL;                                            // 保存我们的窗口句柄
  9 HINSTANCE       hInstance;                                            // 保存程序的实例
 10 
 11 bool    keys[256];                                                    // 保存键盘按键的数组
 12 bool    active=TRUE;                                                // 窗口的活动标志,缺省为TRUE
 13 bool    fullscreen=TRUE;                                            // 全屏标志缺省,缺省设定成全屏模式
 14 
 15 LRESULT    CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);                // WndProc的定义
 16 GLvoid ReSizeGLScene(GLsizei width, GLsizei height)                    // 重置OpenGL窗口大小
 17 {
 18     if (height==0)                                                    // 防止被零除
 19     {
 20         height=1;                                                    // 将Height设为1
 21     }
 22     glViewport(0, 0, width, height);                                // 重置当前的视口
 23     glMatrixMode(GL_PROJECTION);                                    // 选择投影矩阵
 24     glLoadIdentity();                                                // 重置投影矩阵
 25     // 设置视口的大小
 26     gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
 27     glMatrixMode(GL_MODELVIEW);                                        // 选择模型观察矩阵
 28     glLoadIdentity();                                                // 重置模型观察矩阵
 29 }
 30 
 31 int InitGL(GLvoid)                                                    // 此处开始对OpenGL进行所有设置
 32 {
 33     glShadeModel(GL_SMOOTH);                                        // 启用阴影平滑
 34     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                            // 黑色背景
 35     glClearDepth(1.0f);                                                // 设置深度缓存
 36     glEnable(GL_DEPTH_TEST);                                        // 启用深度测试
 37     glDepthFunc(GL_LEQUAL);                                            // 所作深度测试的类型
 38     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);                // 告诉系统对透视进行修正
 39     return TRUE;                                                    // 初始化 OK
 40 }
 41 
 42 int DrawGLScene(GLvoid)                                                // 从这里开始进行所有的绘制
 43 {
 44     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                // 清除屏幕和深度缓存
 45     glLoadIdentity();                                                // 重置当前的模型观察矩阵
 46     return TRUE;                                                    //  一切 OK
 47 }
 48 
 49 GLvoid KillGLWindow(GLvoid)                                            // 正常销毁窗口
 50 {
 51     if (fullscreen)                                                    // 我们处于全屏模式吗?
 52     {
 53         ChangeDisplaySettings(NULL,0);                                // 是的话,切换回桌面
 54         ShowCursor(TRUE);                                            // 显示鼠标指针
 55     }
 56     if (hRC)                                                        // 我们拥有OpenGL渲染描述表吗?
 57     {
 58         if (!wglMakeCurrent(NULL,NULL))                                // 我们能否释放DC和RC描述表?
 59         {
 60             MessageBox(NULL,"释放DC或RC失败。","关闭错误",MB_OK | MB_ICONINFORMATION);
 61         }
 62         if (!wglDeleteContext(hRC))                                    // 我们能否删除RC?
 63         {
 64             MessageBox(NULL,"释放RC失败。","关闭错误",MB_OK | MB_ICONINFORMATION);
 65         }
 66         hRC=NULL;                                                    // 将RC设为 NULL
 67     }
 68     if (hDC && !ReleaseDC(hWnd,hDC))                                // 我们能否释放 DC?
 69     {
 70         MessageBox(NULL,"释放DC失败。","关闭错误",MB_OK | MB_ICONINFORMATION);
 71         hDC=NULL;                                                    // 将 DC 设为 NULL
 72     }
 73     if (hWnd && !DestroyWindow(hWnd))                                // 能否销毁窗口?
 74     {
 75         MessageBox(NULL,"释放窗口句柄失败。","关闭错误",MB_OK | MB_ICONINFORMATION);
 76         hWnd=NULL;                                                    // 将 hWnd 设为 NULL
 77     }
 78     if (!UnregisterClass("OpenG",hInstance))                        // 能否注销类?
 79     {
 80         MessageBox(NULL,"不能注销窗口类。","关闭错误",MB_OK | MB_ICONINFORMATION);
 81         hInstance=NULL;                                                // 将 hInstance 设为 NULL
 82     }
 83 }
 84 
 85 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
 86 {
 87     GLuint        PixelFormat;                                        // 保存查找匹配的结果
 88     WNDCLASS    wc;                                                    // 窗口类结构
 89     DWORD        dwExStyle;                                            // 扩展窗口风格
 90     DWORD        dwStyle;                                            // 窗口风格
 91     RECT WindowRect;                                                // 取得矩形的左上角和右下角的坐标值
 92     WindowRect.left=(long)0;                                        // 将Left   设为 0
 93     WindowRect.right=(long)width;                                    // 将Right  设为要求的宽度
 94     WindowRect.top=(long)0;                                            // 将Top    设为 0
 95     WindowRect.bottom=(long)height;                                    // 将Bottom 设为要求的高度
 96     fullscreen=fullscreenflag;                                        // 设置全局全屏标志
 97     
 98     hInstance        = GetModuleHandle(NULL);                        // 取得我们窗口的实例
 99     wc.style        = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;            // 移动时重画,并为窗口取得DC
100     wc.lpfnWndProc        = (WNDPROC) WndProc;                        // WndProc处理消息
101     wc.cbClsExtra        = 0;                                        // 无额外窗口数据
102     wc.cbWndExtra        = 0;                                        // 无额外窗口数据
103     wc.hInstance        = hInstance;                                // 设置实例
104     wc.hIcon        = LoadIcon(NULL, IDI_WINLOGO);                    // 装入缺省图标
105     wc.hCursor        = LoadCursor(NULL, IDC_ARROW);                    // 装入鼠标指针
106     wc.hbrBackground    = NULL;                                        // GL不需要背景
107     wc.lpszMenuName        = NULL;                                        // 不需要菜单
108     wc.lpszClassName    = "OpenG";                                    // 设定类名字
109     
110     if (!RegisterClass(&wc))                                        // 尝试注册窗口类
111     {
112         MessageBox(NULL,"注册窗口失败","错误",MB_OK|MB_ICONEXCLAMATION);
113         return FALSE;                                                // 退出并返回FALSE
114     }
115     
116     if (fullscreen)                                                    // 要尝试全屏模式吗?
117     {
118         DEVMODE dmScreenSettings;                                    // 设备模式
119         memset(&dmScreenSettings,0,sizeof(dmScreenSettings));        // 确保内存清空为零
120         dmScreenSettings.dmSize=sizeof(dmScreenSettings);            // Devmode 结构的大小
121         dmScreenSettings.dmPelsWidth    = width;                    // 所选屏幕宽度
122         dmScreenSettings.dmPelsHeight    = height;                    // 所选屏幕高度
123         dmScreenSettings.dmBitsPerPel    = bits;                        // 每象素所选的色彩深度
124         dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
125         // 尝试设置显示模式并返回结果。注: CDS_FULLSCREEN 移去了状态条。
126         if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
127         {
128             // 若模式失败,提供两个选项:退出或在窗口内运行。
129             if (MessageBox(NULL,"全屏模式在当前显卡上设置失败!\n使用窗口模式?","NeHe G",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
130             {
131                 fullscreen=FALSE;                                    // 选择窗口模式(Fullscreen=FALSE)
132             }
133             else
134             {
135                 // 弹出一个对话框,告诉用户程序结束
136                 MessageBox(NULL,"程序将被关闭","错误",MB_OK|MB_ICONSTOP);
137                 return FALSE;                                        //  退出并返回 FALSE
138             }
139         }
140     }
141     if (fullscreen)                                                    // 仍处于全屏模式吗?
142     {
143         dwExStyle=WS_EX_APPWINDOW;                                    // 扩展窗体风格
144         dwStyle=WS_POPUP;                                            // 窗体风格
145         ShowCursor(FALSE);                                            // 隐藏鼠标指针
146     }    
147     else
148     {
149         dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;                // 扩展窗体风格
150         dwStyle=WS_OVERLAPPEDWINDOW;                                // 窗体风格
151     }
152     AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);        // 调整窗口达到真正要求的大小
153     if (!(hWnd=CreateWindowEx(    dwExStyle,                            // 扩展窗体风格
154         "OpenG",                                                    // 类名字
155         title,                                                        // 窗口标题
156         WS_CLIPSIBLINGS |                                            // 必须的窗体风格属性
157         WS_CLIPCHILDREN |                                            // 必须的窗体风格属性
158         dwStyle,                                                    // 选择的窗体属性
159         0, 0,                                                        // 窗口位置
160         WindowRect.right-WindowRect.left,                            // 计算调整好的窗口宽度
161         WindowRect.bottom-WindowRect.top,                            // 计算调整好的窗口高度
162         NULL,                                                        // 无父窗口
163         NULL,                                                        // 无菜单
164         hInstance,                                                    // 实例
165         NULL)))                                                        // 不向WM_CREATE传递任何东东
166     {
167         KillGLWindow();                                                // 重置显示区
168         MessageBox(NULL,"不能创建一个窗口设备描述表","错误",MB_OK|MB_ICONEXCLAMATION);
169         return FALSE;                                                // 返回 FALSE
170     }
171     static    PIXELFORMATDESCRIPTOR pfd=                                // /pfd 告诉窗口我们所希望的东东,即窗口使用的像素格式
172     {
173         sizeof(PIXELFORMATDESCRIPTOR),                                // 上述格式描述符的大小
174             1,                                                        // 版本号
175             PFD_DRAW_TO_WINDOW |                                    // 格式支持窗口
176             PFD_SUPPORT_OPENGL |                                    // 格式必须支持OpenGL
177             PFD_DOUBLEBUFFER,                                        // 必须支持双缓冲
178             PFD_TYPE_RGBA,                                            // 申请 RGBA 格式
179             bits,                                                    // 选定色彩深度
180             0, 0, 0, 0, 0, 0,                                        // 忽略的色彩位
181             0,                                                        // 无Alpha缓存
182             0,                                                        // 忽略Shift Bit
183             0,                                                        // 无累加缓存
184             0, 0, 0, 0,                                                // 忽略聚集位
185             16,                                                        // 16位 Z-缓存 (深度缓存)
186             0,                                                        // 无蒙板缓存
187             0,                                                        // 无辅助缓存
188             PFD_MAIN_PLANE,                                            // 主绘图层
189             0,                                                        // Reserved
190             0, 0, 0                                                    // 忽略层遮罩
191     };
192     if (!(hDC=GetDC(hWnd)))                                            // 取得设备描述表了么?
193     {
194         KillGLWindow();                                                // 重置显示区
195         MessageBox(NULL,"不能创建一种相匹配的像素格式","错误",MB_OK|MB_ICONEXCLAMATION);
196         return FALSE;                                                // 返回 FALSE
197     }
198     if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))                    // Windows 找到相应的象素格式了吗?
199     {
200         KillGLWindow();                                                // 重置显示区
201         MessageBox(NULL,"不能设置像素格式","错误",MB_OK|MB_ICONEXCLAMATION);
202         return FALSE;                                                // 返回 FALSE
203     }
204     if(!SetPixelFormat(hDC,PixelFormat,&pfd))                        // 能够设置象素格式么?
205     {
206         KillGLWindow();                                                // 重置显示区
207         MessageBox(NULL,"不能设置像素格式","错误",MB_OK|MB_ICONEXCLAMATION);
208         return FALSE;                                                // 返回 FALSE
209     }
210     if (!(hRC=wglCreateContext(hDC)))                                // 能否取得着色描述表?
211     {
212         KillGLWindow();                                                // 重置显示区
213         MessageBox(NULL,"不能创建OpenGL渲染描述表","错误",MB_OK|MB_ICONEXCLAMATION);
214         return FALSE;                                                // 返回 FALSE
215     }
216     if(!wglMakeCurrent(hDC,hRC))                                    // 尝试激活着色描述表
217     {
218         KillGLWindow();                                                // 重置显示区
219         MessageBox(NULL,"不能激活当前的OpenGL渲然描述表","错误",MB_OK|MB_ICONEXCLAMATION);
220         return FALSE;                                                // 返回 FALSE
221     }
222     ShowWindow(hWnd,SW_SHOW);                                        // 显示窗口
223     SetForegroundWindow(hWnd);                                        // 略略提高优先级
224     SetFocus(hWnd);                                                    // 设置键盘的焦点至此窗口
225     ReSizeGLScene(width, height);                                    // 设置透视 GL 屏幕
226     if (!InitGL())                                                    // 初始化新建的GL窗口
227     {
228         KillGLWindow();                                                // 重置显示区
229         MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
230         return FALSE;                                                // 返回 FALSE
231     }
232     return TRUE;                                                    // 成功
233 }
234 
235 LRESULT CALLBACK WndProc(    HWND    hWnd,                            // 窗口的句柄
236                          UINT    uMsg,                                // 窗口的消息
237                          WPARAM    wParam,                                // 附加的消息内容
238                          LPARAM    lParam)                                // 附加的消息内容
239 {
240     switch (uMsg)                                                    // 检查Windows消息
241     {
242     case WM_ACTIVATE:                                                // 监视窗口激活消息
243         {
244             if (!HIWORD(wParam))                                    // 检查最小化状态
245             {
246                 active=TRUE;                                        // 程序处于激活状态
247             }
248             else
249             {
250                 active=FALSE;                                        // 程序不再激活
251             }
252             return 0;                                                // 返回消息循环
253         }
254     case WM_SYSCOMMAND:                                                // 系统中断命令
255         {
256             switch (wParam)                                            // 检查系统调用
257             {
258             case SC_SCREENSAVE:                                        // 屏保要运行?
259             case SC_MONITORPOWER:                                    // 显示器要进入节电模式?
260                 return 0;                                            // 阻止发生
261             }
262             break;                                                    // 退出
263         }
264     case WM_CLOSE:                                                    // 收到Close消息?
265         {
266             PostQuitMessage(0);                                        // 发出退出消息
267             return 0;                                                // 返回
268         }
269     case WM_KEYDOWN:                                                // 有键按下么?
270         {
271             keys[wParam] = TRUE;                                    // 如果是,设为TRUE
272             return 0;                                                // 返回
273         }
274     case WM_KEYUP:                                                    // 有键放开么?
275         {
276             keys[wParam] = FALSE;                                    // 如果是,设为FALSE
277             return 0;                                                // 返回
278         }
279     case WM_SIZE:                                                    // 调整OpenGL窗口大小
280         {
281             ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));            // LoWord=Width,HiWord=Height
282             return 0;                                                // 返回
283         }
284     }
285     // 向 DefWindowProc传递所有未处理的消息。
286     return DefWindowProc(hWnd,uMsg,wParam,lParam);
287 }
288 
289 
290 int WINAPI WinMain(    HINSTANCE    hInstance,                            // 当前窗口实例
291                    HINSTANCE    hPrevInstance,                        // 前一个窗口实例
292                    LPSTR        lpCmdLine,                            // 命令行参数
293                    int        nCmdShow)                                // 窗口显示状态
294 {
295     MSG    msg;                                                        // Windowsx消息结构
296     BOOL    done=FALSE;                                                // 用来退出循环的Bool 变量
297     // 提示用户选择运行模式
298     if (MessageBox(NULL,"你想在全屏模式下运行么?", "设置全屏模式",MB_YESNO|MB_ICONQUESTION)==IDNO)
299     {
300         fullscreen=FALSE;                                            // FALSE为窗口模式
301     }
302     // 创建OpenGL窗口
303     if (!CreateGLWindow("NeHe's OpenGL程序框架",640,480,16,fullscreen))
304     {
305         return 0;                                                    // 失败退出
306     }
307     while(!done)                                                    // 保持循环直到 done=TRUE
308     {
309         if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))                    // 有消息在等待吗?
310         {
311             if (msg.message==WM_QUIT)                                // 收到退出消息?
312             {
313                 done=TRUE;                                            // 是,则done=TRUE
314             }
315             else                                                    // 不是,处理窗口消息
316             {
317                 TranslateMessage(&msg);                                // 翻译消息
318                 DispatchMessage(&msg);                                // 发送消息
319             }
320         }
321         else                                                        // 如果没有消息
322         {
323             // 绘制场景。监视ESC键和来自DrawGLScene()的退出消息
324             if (active)                                                // 程序激活的么?
325             {
326                 if (keys[VK_ESCAPE])                                // ESC 按下了么?
327                 {
328                     done=TRUE;                                        // ESC 发出退出信号
329                 }
330                 else                                                // 不是退出的时候,刷新屏幕
331                 {
332                     DrawGLScene();                                    // 绘制场景
333                     SwapBuffers(hDC);                                // 交换缓存 (双缓存)
334                 }
335             }
336             if (keys[VK_F1])                                        // F1键按下了么?
337             {
338                 keys[VK_F1]=FALSE;                                    // 若是,使对应的Key数组中的值为 FALSE
339                 KillGLWindow();                                        // 销毁当前的窗口
340                 fullscreen=!fullscreen;                                // 切换 全屏 / 窗口 模式
341                 // 重建 OpenGL 窗口
342                 if (!CreateGLWindow("NeHe's OpenGL 程序框架",640,480,16,fullscreen))
343                 {
344                     return 0;                                        // 如果窗口未能创建,程序退出
345                 }
346             }
347         }
348     }
349     // 关闭程序
350     KillGLWindow();                                                    // 销毁窗口
351     return (msg.wParam);                                            // 退出程序
352 }
hehe.cpp

具体说明可以参看那位作者的说明,很详细滴~

>_<: 再说说用VC6.0自带的OpenGL工程建立的项目,其实他也是Win32应用程序,只是模块化更清晰,仔细对比两个程序,会发现有很大的相同点的。一般只要在MainWnd.cpp中做相应的修改就行啦:

1 void DrawScene();
2 void KillScene();
3 void InitScene();    
4 void Tick(BOOL &bRedrawScene);

这是MainWnd类的几个成员函数,其中第一个就是负责显示的,第三个就是负责初始化相关,第四个负责更新参数,就相当于时间轴,更直白的说就是每隔一定时间就会执行一次的函数,你把一些运动相关的参数放进里面就可以实现递增或递减或复杂的变化关系~

PS: 接下来我会使用VC自带的工程做,如果你还是个新手建议用那位作者的框架~

 

posted @ 2014-08-13 16:51  beautifulzzzz  阅读(793)  评论(2编辑  收藏  举报