====== 002 フレームレートを考慮したWindowの作成 ====== {{:wiki:opengl_es_2.0:tips:opengles_es20_001.png?200|}} ===== 概要 ===== Windowを表示してみます。ビルドにはAngle導入時に生成したlibEGL.libとlibGLESv2.libが必要です。 また、実行時にはlibEGL.dllとlibGLESv2.dllを実行ファイルと同じディレクトリに設置してください。 //================================================================================// // インクルード //================================================================================// #include #include #include #include static LARGE_INTEGER g_performanceCounterFrequency; static LARGE_INTEGER g_previousPerformanceCounter; static HINSTANCE g_hInstance = NULL; static HWND g_hWnd = NULL; static HDC g_hDC = NULL; static bool g_bExit = false; static bool g_bActive = false; static double g_AccumulatedTime = 0.0; static double g_FrameStep = 1.0 / 60.0; static EGLDisplay g_eglDisplay = EGL_NO_DISPLAY; static EGLSurface g_eglSurface = EGL_NO_SURFACE; static EGLContext g_eglContext = EGL_NO_CONTEXT; static const int SCREEN_SIZE_WIDHT = 320; static const int SCREEN_SIZE_HEIGHT = 480; //--------------------------------------------------------------------------------// // WndProc // // [note] ウインドウプロシージャ。 // //--------------------------------------------------------------------------------// LRESULT CALLBACK WndProc( HWND _hWnd, UINT _uMsg, WPARAM _wParam, LPARAM _lParam ) { switch( _uMsg ) { case WM_ACTIVATE: { } break; case WM_SYSCOMMAND: { switch ( _wParam ) { case SC_SCREENSAVE: case SC_MONITORPOWER: break; default: return DefWindowProc( _hWnd, _uMsg, _wParam, _lParam ); } } break; case WM_CLOSE: { PostQuitMessage( 0 ); } break; case WM_GETMINMAXINFO: { DefWindowProc( _hWnd, _uMsg, _wParam, _lParam ); return 0; } break; default: { return DefWindowProc( _hWnd, _uMsg, _wParam, _lParam ); } } return 0; } //--------------------------------------------------------------------------------// // WndProc // // [note] ウインドウの破棄。 // //--------------------------------------------------------------------------------// void destroyWindow() { if( g_hDC ) { ReleaseDC( g_hWnd, g_hDC ); g_hDC = NULL; } if( g_hWnd ) { DestroyWindow( g_hWnd ); UnregisterClass( TEXT("AppWindowClass"), g_hInstance ); g_hWnd = NULL; } } //--------------------------------------------------------------------------------// // WndProc // // [note] ウインドウの生成。 // //--------------------------------------------------------------------------------// bool createWindow() { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("AppWindowClass"); wc.hIconSm = NULL; if( !RegisterClassEx( &wc ) ) { return false; } RECT WndRect = { 0, 0, SCREEN_SIZE_WIDHT, SCREEN_SIZE_HEIGHT }; DWORD flags = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; DWORD exflags = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; AdjustWindowRectEx( &WndRect, flags, FALSE, exflags ); LONG windowWidth = WndRect.right - WndRect.left; LONG windowHeight = WndRect.bottom - WndRect.top; WndRect.left = (GetSystemMetrics(SM_CXSCREEN) - (WndRect.right - WndRect.left)) / 2; WndRect.top = (GetSystemMetrics(SM_CYSCREEN) - (WndRect.bottom - WndRect.top)) / 2; g_hWnd = CreateWindowEx(exflags, TEXT("AppWindowClass"), TEXT("Title"), flags, WndRect.left, WndRect.top, windowWidth, windowHeight, NULL, NULL, g_hInstance, NULL ); if( !g_hWnd ) { UnregisterClass( TEXT("AppWindowClass"), g_hInstance ); return false; } g_hDC = GetDC( g_hWnd ); if( !g_hDC ) { destroyWindow(); return false; } return true; } //--------------------------------------------------------------------------------// // destroyEGL // // [note] EGLの破棄。 // //--------------------------------------------------------------------------------// void destroyEGL() { if( g_eglContext != EGL_NO_CONTEXT ) { eglMakeCurrent( g_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); eglDestroyContext( g_eglDisplay, g_eglContext ); g_eglContext = EGL_NO_CONTEXT; } if( g_eglSurface != EGL_NO_SURFACE ) { eglDestroySurface( g_eglDisplay, g_eglSurface ); g_eglSurface = EGL_NO_SURFACE; } if( g_eglDisplay != EGL_NO_DISPLAY ) { eglTerminate( g_eglDisplay ); g_eglDisplay = EGL_NO_DISPLAY; } } //--------------------------------------------------------------------------------// // createEGL // // [note] EGLの初期化。 // //--------------------------------------------------------------------------------// bool createEGL() { // バージョンチェック。 DWORD version = GetVersion(); int majorVersion = LOBYTE(LOWORD(version)); int minorVersion = HIBYTE(LOWORD(version)); // ディスプレイの取得。 g_eglDisplay = eglGetDisplay( g_hDC ); if( g_eglDisplay == EGL_NO_DISPLAY ) { // 失敗した時。 g_eglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY ); if ( g_eglDisplay == EGL_NO_DISPLAY ) { return false; } } // EGLの初期化。 if( !eglInitialize( g_eglDisplay, NULL, NULL ) ) { g_eglDisplay = EGL_NO_DISPLAY; return false; } // コンフィグの選択。 const EGLint configs[] = { EGL_LEVEL, 0, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NATIVE_RENDERABLE, EGL_FALSE, EGL_DEPTH_SIZE, EGL_DONT_CARE, EGL_NONE }; EGLConfig configuration; EGLint numFoundConfigurations = 0; if( !eglChooseConfig( g_eglDisplay, configs, &configuration, 1, &numFoundConfigurations ) ) { destroyEGL(); return false; } if( numFoundConfigurations < 1 ) { destroyEGL(); return false; } // サーフェイスを作成する。 g_eglSurface = eglCreateWindowSurface( g_eglDisplay, configuration, static_cast(g_hWnd), NULL ); if( !g_eglSurface ) { destroyEGL(); return false; } // APIをバインドする。 eglBindAPI( EGL_OPENGL_ES_API ); EGLint attribList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; // コンテキストの作成。 g_eglContext = eglCreateContext( g_eglDisplay, configuration, EGL_NO_CONTEXT, attribList ); if( g_eglContext == EGL_NO_CONTEXT ) { destroyEGL(); return false; } // ディスプレイ、サーフェイス、コンテキストを関連づける。 if( !eglMakeCurrent(g_eglDisplay, g_eglSurface, g_eglSurface, g_eglContext ) ) { destroyEGL(); return false; } return true; } //--------------------------------------------------------------------------------// // main // // [note] メイン // //--------------------------------------------------------------------------------// int APIENTRY _tWinMain( HINSTANCE _hInstance, HINSTANCE _hPrevInstance, LPTSTR _lpCmdLine, int _nCmdShow ) { g_hInstance = _hInstance; if (!QueryPerformanceFrequency( &g_performanceCounterFrequency ) ) { return 0; } if ( !createWindow() ) { return 0; } if( !createEGL() ) { destroyWindow(); return 0; } ShowWindow( g_hWnd, SW_SHOW ); SetForegroundWindow( g_hWnd ); SetFocus( g_hWnd ); QueryPerformanceCounter( &g_previousPerformanceCounter ); MSG msg; ZeroMemory( &msg, sizeof(msg) ); while( !g_bExit ) { while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { if( msg.message == WM_QUIT ) { g_bExit = true; } else { TranslateMessage( &msg ); DispatchMessage( &msg ); } } LARGE_INTEGER performanceCounter; QueryPerformanceCounter( &performanceCounter ); if( !g_bActive ) { g_previousPerformanceCounter = performanceCounter; } else { g_AccumulatedTime += static_cast( performanceCounter.QuadPart - g_previousPerformanceCounter.QuadPart) / static_cast(g_performanceCounterFrequency.QuadPart ); g_previousPerformanceCounter = performanceCounter; // 更新。 while( g_AccumulatedTime >= g_FrameStep ) { // ここにUpdate処理を書く。 g_AccumulatedTime -= g_FrameStep; } // 描画。 if (eglMakeCurrent( g_eglDisplay, g_eglSurface, g_eglSurface, g_eglContext ) ) { // ここにRender処理を書く。 glClearColor( 0.5f, 0.5f, 0.7f, 1.0f ); glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); eglSwapBuffers( g_eglDisplay, g_eglSurface ); } } } destroyEGL(); destroyWindow(); return 0; }