ユーザ用ツール

サイト用ツール

サイドバー

About

Contents

Materials Link

その他

PR


wiki:opengl_es_2.0:tips:002

002 フレームレートを考慮したWindowの作成

概要

Windowを表示してみます。ビルドにはAngle導入時に生成したlibEGL.libとlibGLESv2.libが必要です。 また、実行時にはlibEGL.dllとlibGLESv2.dllを実行ファイルと同じディレクトリに設置してください。

//================================================================================//
//	インクルード
//================================================================================//
#include <tchar.h>
#include <Windows.h>
 
#include <GLES2/gl2.h>
#include <EGL/egl.h>
 
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<EGLNativeWindowType>(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<double>( performanceCounter.QuadPart - g_previousPerformanceCounter.QuadPart) / static_cast<double>(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;
}
Permalink wiki/opengl_es_2.0/tips/002.txt · 最終更新: 2014/11/07 08:22 (外部編集)

oeffentlich