建立多窗口openGL程序,可以用来制作各种GL控制或者多视图GL程序,为以后设计组态openGL引擎试验。
基础知识
1.OpenGL与其他窗体应用程序消息循环上的不同
这个大家都知道,因为其他窗体应用程序不需要实时绘制,但需要实时监听消息响应,所以为了提高性能,openGL和其他窗体程序的消息循环写法有一点点不一样。(就因为如此,所以我们需要使用多线程来建立不同的窗口)
a.一般窗体程序(例如MFC)消息循环机制如下:
2 | while (GetMessage(&msg,NULL,0,0)) |
4 | TranslateMessage(&msg); |
这么的话需要等系统的WM_PAINT消息才去重新绘制,对3D动画程序来说肯定效率低下,但对窗体应用程序来说却很节省资源。
b.OpenGL改进后的循环如下:
04 | if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) |
08 | if (msg.message==WM_QUIT) |
14 | TranslateMessage(&msg); |
15 | DispatchMessage(&msg); |
PeekMessage和GetMessage区别就是他不会等函数返回就直接往下执行了,效率当然高很多。
2.多线程
由于第一点原因,所以我们使用多线程。多线程win32api函数:
CreateThread();
返回一个句柄。
这样就能建立多个线程独立运行各个窗口函数,建立其他窗口来控制openGL绘制或者建立多个窗口不同视角来显示GL物体等。窗体间能建立父子关系,可以想象下photoshop,就可以知道这种多窗口程序有多诱人了^ ^.当然还可以做窗口停靠。
示例代码:
文件1:
04 | #include "ControlPad.h" |
08 | glClear(GL_COLOR_BUFFER_BIT); |
15 | glClearColor(0.0,0.0,0.0,0.0); |
16 | glMatrixMode(GL_PROJECTION); |
19 | glOrtho(0.0,1.0,0.0,1.0,-1.0,1.0); |
22 | int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstace, LPSTR lpCmdLine, int nCmdShow) |
25 | char * argv[] = { "Jerry" , "OpenGL" }; |
27 | glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); |
28 | glutInitWindowSize(800,600); |
29 | glutInitWindowPosition(100,100); |
30 | glutCreateWindow( "TestMode" ); |
37 | hThread = CreateThread(NULL,0,WinControlMain,NULL,0,NULL); |
43 | glutDisplayFunc(display); |
文件2:ControlPad.cpp
03 | #include "ControlPad.h" |
05 | LRESULT CALLBACK WinProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
12 | MessageBox(hwnd,szChar, "char" ,0); |
18 | return DefWindowProc(hwnd,uMsg,wParam,lParam); |
23 | DWORD WINAPI WinControlMain( LPVOID lpParameter) |
26 | wndcls.cbClsExtra = 0; |
27 | wndcls.cbWndExtra = 0; |
28 | wndcls.hbrBackground = ( HBRUSH )COLOR_BACKGROUND; |
29 | wndcls.hCursor = LoadCursor(NULL,IDC_CROSS); |
30 | wndcls.hIcon = LoadIcon(NULL,IDI_ERROR); |
32 | wndcls.lpfnWndProc = WinProc; |
33 | wndcls.lpszClassName = "GL Control" ; |
34 | wndcls.lpszMenuName = NULL; |
35 | wndcls.style = CS_HREDRAW | CS_VREDRAW; |
36 | RegisterClass(&wndcls); |
39 | hwnd = CreateWindow( "GL Control" , "GL Control" ,WS_OVERLAPPEDWINDOW,0,0,600,400,NULL,NULL,0,NULL); |
41 | ShowWindow(hwnd,SW_SHOWNORMAL); |
45 | while (GetMessage(&msg,NULL,0,0)) |
47 | TranslateMessage(&msg); |
48 | DispatchMessage(&msg); |
当然我这里写的比较简单,做个示范提供个思路而已,等待以后慢慢扩展。我故意避开mfc,考虑到以后效率问题^^,其实在mfc里可以更简单的做这个,但是咱们提倡直接win32api。