>_<: 首先推荐一个企业版的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 #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 }
具体说明可以参看那位作者的说明,很详细滴~
>_<: 再说说用VC6.0自带的OpenGL工程建立的项目,其实他也是Win32应用程序,只是模块化更清晰,仔细对比两个程序,会发现有很大的相同点的。一般只要在MainWnd.cpp中做相应的修改就行啦:
1 void DrawScene(); 2 void KillScene(); 3 void InitScene(); 4 void Tick(BOOL &bRedrawScene);
这是MainWnd类的几个成员函数,其中第一个就是负责显示的,第三个就是负责初始化相关,第四个负责更新参数,就相当于时间轴,更直白的说就是每隔一定时间就会执行一次的函数,你把一些运动相关的参数放进里面就可以实现递增或递减或复杂的变化关系~
PS: 接下来我会使用VC自带的工程做,如果你还是个新手建议用那位作者的框架~
[OpenGL] 1、环境搭建及最小系统,布布扣,bubuko.com
原文:http://www.cnblogs.com/zjutlitao/p/3910525.html