WindowsでOpenGLES --- ANGLE準備
WindowsでOpenGLESを使いたい場合は、Google開発のANGLEが利用できます。
GitHub - google/angle: A conformant OpenGL ES implementation for Windows, Mac and Linux.
ANGLEを利用すれば、OpenGLESで記述したものを、Direct3DやDesktop OpenGLでレンダリングしてくれます。(現在デフォルトでDirect3D11を利用。eglGetPlatformDisplayEXTで変更可能)
今回はANGLEをビルドして、動作確認をしてみたいと思います。
ビルド
WindowsでビルドするにはGypを利用する必要がありますが、Microsoftが下記のリポジトリを作成してくれているので、こちらを利用します。
GitHub - Microsoft/angle: ANGLE: OpenGL ES to DirectX translation for Windows Store, Windows Phone and Desktop
ダウンロードしたら、src/angle.slnを開いてビルドします。
gypフォルダの下にビルド結果が配置されます。
基本的に利用するのはlibEGL.dllとlibGLESv2.dllの2つです。
ウィンドウ準備
今回はWin32APIでウィンドウを作成します。
ちなみにANGLEではウィンドウ(HWND)を準備することなくオフスクリーンレンダリングすることも可能です。
WNDCLASSEX wndclass; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = GetModuleHandle(NULL); wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = L"GL Window"; wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wndclass); HWND hwnd = CreateWindow( L"GL Window", L"GL Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wndclass.hInstance, NULL); ShowWindow(hwnd, SW_SHOWNORMAL);
WndProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); }
OpenGLES初期化
display、config、contextの順に作成し、最後にsurfaceを作成しMakeCurrentを行います。
今回はES3.0を利用するよう初期化しています。
hwndは上記で作成したものを利用します。
#include <EGL\egl.h> #pragma comment(lib, "libEGL.lib") // display EGLDisplay display = eglGetDisplay(GetDC(hwnd)); assert(display); EGLint major, minor; assert(eglInitialize(display, &major, &minor)); assert(eglBindAPI(EGL_OPENGL_ES_API)); // config EGLint configAttributes[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_BUFFER_SIZE, 32, EGL_NONE }; EGLConfig config; EGLint num_config; assert(eglChooseConfig(display, configAttributes, &config, 1, &num_config)); // context EGLint contextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE }; EGLContext context = eglCreateContext(display, config, NULL, contextAttributes); assert(context); // surface EGLSurface surface = eglCreateWindowSurface(display, config, hwnd, NULL); assert(surface); assert(eglMakeCurrent(display, surface, surface, context));
描画
WndProcのWM_PAINTに描画処理を追加します。
今回は背景を灰色に塗るだけです。
#define GL_GLEXT_PROTOTYPES #include <GLES3\gl3.h> #pragma comment(lib, "libGLESv2.lib") case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); glClearColor(0.5, 0.5, 0.5, 1); glClear(GL_COLOR_BUFFER_BIT); assert(eglSwapBuffers(display, surface)); EndPaint(hwnd, &ps); }
Run
メッセージループを開始します。
灰色に塗りつぶされたウィンドウが表示されます。
MSG msg; while (GetMessage(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }