質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

470閲覧

WGLの表示時の描画ラグ

Weapon

総合スコア106

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/02/14 05:55

前提・実現したいこと

以前の質問WGLの初期化 プロシージャの記法についての回答を踏まえコード全体の流れを理解し直しながら書き直しWGLでウィンドウにレンダリングまではうまくいったのですが実行時に最初白い画面が表示された後WGLによって描画された画面が表示されます.このラグをなくすためにはどうしたらいいでしょうか?
また画面サイズの取得はGetClientRect()WM_SIZELPARAMでもできますが取得方法で描画速度に影響は出てくるでしょうか?WM_SIZEWM_PAINTの呼ばれるタイミング次第でしょうか?

該当のコード

C

1#define UNICODE 2 3#pragma comment(lib,"opengl32.lib") 4 5#include <windows.h> 6#include <gl/GL.h> 7 8 9LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 10 11const wchar_t CLASS_NAME[] = L"Class_Name"; 12 13int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR nCmdLine, int nCmdShow) { 14 UNREFERENCED_PARAMETER(hPrevInstance); 15 UNREFERENCED_PARAMETER(nCmdLine); 16 17 WNDCLASSEX wc = { 18 sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW, WindowProc, 19 0, 0, hInstance, 20 NULL, (HCURSOR)LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(WHITE_BRUSH), 21 NULL, CLASS_NAME, NULL 22 }; 23 24 if (!RegisterClassEx(&wc)) { 25 MessageBox(NULL, L"Register Failed", L"CAUTION", MB_OK); 26 return -1; 27 } 28 29 HWND hwnd = CreateWindowEx( 30 0, CLASS_NAME, L"Device Independent", WS_OVERLAPPEDWINDOW, 31 CW_USEDEFAULT, CW_USEDEFAULT, 960, 540, 32 NULL, NULL, hInstance, NULL 33 ); 34 35 if (hwnd == NULL) { 36 MessageBox(NULL, L"HWND Failed", L"CAUTION", MB_OK); 37 return -1; 38 } 39 40 ShowWindow(hwnd, nCmdShow); 41 UpdateWindow(hwnd); 42 43 MSG msg = {}; 44 45 while (GetMessage(&msg, hwnd, 0, 0) > 0) { 46 TranslateMessage(&msg); 47 DispatchMessage(&msg); 48 } 49 50 return (int)msg.wParam; 51} 52 53LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 54 static int iWidth; 55 static int iHeight; 56 static RECT rc; 57 switch (uMsg) { 58 case WM_ERASEBKGND: 59 return -1; 60 61 case WM_CREATE: 62 break; 63 64 case WM_PAINT: 65 { 66 GetClientRect(hwnd, &rc); 67 iWidth = rc.right - rc.left; 68 iHeight = rc.bottom - rc.top; 69 70 /* Make Memory Device Context */ 71 BITMAPINFO bmi = { 72 sizeof(BITMAPINFOHEADER), iWidth, iHeight, 1, 24, BI_RGB, 0, 0, 0, 0, 0, NULL 73 }; 74 75 HDC tmpDIB = CreateCompatibleDC(NULL); 76 77 if (tmpDIB == NULL)MessageBox(NULL, L"CCDC Failed", L"Caution", MB_OK); 78 79 void *pv; 80 81 HBITMAP hbmDIB = CreateDIBSection(tmpDIB, &bmi, DIB_RGB_COLORS, &pv, NULL, 0); 82 83 if (hbmDIB == NULL)MessageBox(NULL, L"DIBSec Failed", L"Caution", MB_OK); 84 85 HGDIOBJ test_a = SelectObject(tmpDIB, hbmDIB); 86 87 if (test_a == NULL)MessageBox(NULL, L"SelectObject Failed", L"Caution", MB_OK); 88 /* END Make Memory Device Context */ 89 /* SET PIXELFORMATDESCRIPTOR */ 90 PIXELFORMATDESCRIPTOR pfd = { 91 sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP, PFD_TYPE_RGBA, 24, 92 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0, 93 }; 94 95 96 int format = ChoosePixelFormat(tmpDIB, &pfd); 97 if (format == 0) { 98 MessageBox(NULL, L"ChoosePixelFormat Failed", L"CAUTION", MB_OK); 99 GetLastError(); 100 } 101 if (SetPixelFormat(tmpDIB, format, &pfd) == FALSE)MessageBox(NULL, L"SetPixelFormat Failed", L"CAUTION", MB_OK); 102 103 HGLRC mglrc = wglCreateContext(tmpDIB); 104 if (mglrc == NULL)MessageBox(NULL, L"wglCreateContext Failed", L"CAUTION", MB_OK); 105 106 /* END PIXELFORMATDESCRIPTOR*/ 107 wglMakeCurrent(tmpDIB, mglrc); 108 /* GL Initialization */ 109 glEnable(GL_COLOR_MATERIAL); 110 glEnable(GL_BLEND); 111 112 113 glViewport(0, 0, iWidth, iHeight); 114 glMatrixMode(GL_PROJECTION); 115 glLoadIdentity(); 116 glMatrixMode(GL_MODELVIEW); 117 glLoadIdentity(); 118 /* END GL Initialization */ 119 /* GL Contents */ 120 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 121 122 glPushMatrix(); 123 124 glColor3f(0, 1, 1); 125 glBegin(GL_TRIANGLES); 126 glColor3f(1.0f, 0.0f, 0.0f); 127 glVertex3f(0.0f, 1.0f, 0.0f); 128 glVertex3f(-1.0f, -1.0f, 0.0f); 129 glColor3f(0.0f, 0.0f, 1.0f); 130 glVertex3f(1.0f, -1.0f, 0.0f); 131 glEnd(); 132 133 glPopMatrix(); 134 glFlush(); 135 /* END GL Contents */ 136 /* PASS DC */ 137 138 PAINTSTRUCT ps; 139 HDC hdc = BeginPaint(hwnd, &ps); 140 BitBlt(hdc, 0, 0, iWidth, iHeight, tmpDIB, 0, 0, SRCCOPY); 141 EndPaint(hwnd, &ps); 142 143 DeleteDC(tmpDIB); 144 DeleteObject(mglrc); 145 } 146 break; 147 148 case WM_DESTROY: 149 break; 150 } 151 152 return DefWindowProc(hwnd, uMsg, wParam, lParam); 153}

補足情報

Windows10 Pro
VisualStudio2017 Community

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

このラグをなくすためにはどうしたらいいでしょうか?

WM_PAINT 内で OpenGL の初期化処理を実行しているため、単純に処理速度が間にあっていないのだと思われます。初回、ウィンドウが表示されて描画が完了するまでの主要なウィンドウメッセージは以下の順番になります。
WM_CREATE
WM_SHOWWINDOW ← このタイミングでウィンドウが表示される。かつ、背景ブラシで塗りつぶされた状態となる。
WM_ERASEBKGND ← WM_ERASEBKGND は処理していないので塗りつぶしは実行されない。
WM_SIZE
WM_PAINT ← このタイミングで OpenGL の処理が実行される。

一瞬表示されてしまうのを抑えるためには、前回の質問にあった元のサンプルのように WM_SIZE 時点で初期化してしまうのが一番単純で良いです。

また画面サイズの取得はGetClientRect()やWM_SIZEのLPARAMでもできますが取得方法で描画速度に影響は出てくるでしょうか?WM_SIZEとWM_PAINTの呼ばれるタイミング次第でしょうか?

その差が描画速度に影響を与えることはありません。ただし、WM_PAINT 内で取得するなら問題ありませんが、WM_SIZE で実施した方がウィンドウの最小化が判断しやすいのでお勧めではあります。

上記を踏まえて解決案を示します。

##1.OpenGL の初期化処理の位置を変更する。

WM_SIZE だけで実施するとウィンドウが表示済みであるため間に合わない可能性が高いです。そのため、WM_CREATE と WM_SIZE の両方で処理して、サイズが前と同じ場合、処理しないようにしてあります。

C++

1#define UNICODE 2 3#pragma comment(lib,"opengl32.lib") 4 5#include <windows.h> 6#include <gl/GL.h> 7 8 9LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 10 11const wchar_t CLASS_NAME[] = L"Class_Name"; 12 13int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR nCmdLine, int nCmdShow) { 14 UNREFERENCED_PARAMETER(hPrevInstance); 15 UNREFERENCED_PARAMETER(nCmdLine); 16 17 WNDCLASSEX wc = { 18 sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW, WindowProc, 19 0, 0, hInstance, 20 NULL, (HCURSOR)LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(WHITE_BRUSH), 21 NULL, CLASS_NAME, NULL 22 }; 23 24 if (!RegisterClassEx(&wc)) { 25 MessageBox(NULL, L"Register Failed", L"CAUTION", MB_OK); 26 return -1; 27 } 28 29 HWND hwnd = CreateWindowEx( 30 0, CLASS_NAME, L"Device Independent", WS_OVERLAPPEDWINDOW, 31 CW_USEDEFAULT, CW_USEDEFAULT, 960, 540, 32 NULL, NULL, hInstance, NULL 33 ); 34 35 if (hwnd == NULL) { 36 MessageBox(NULL, L"HWND Failed", L"CAUTION", MB_OK); 37 return -1; 38 } 39 40 ShowWindow(hwnd, nCmdShow); 41 UpdateWindow(hwnd); 42 43 MSG msg = {}; 44 45 while (GetMessage(&msg, hwnd, 0, 0) > 0) { 46 TranslateMessage(&msg); 47 DispatchMessage(&msg); 48 } 49 50 return (int)msg.wParam; 51} 52 53LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 54 static int iWidth; 55 static int iHeight; 56 static RECT rc; 57 static HDC tmpDIB; 58 static HBITMAP hbmDIB; 59 static HGDIOBJ test_a; 60 static HGLRC mglrc; 61 switch (uMsg) { 62 case WM_ERASEBKGND: 63 return -1; 64 65 case WM_CREATE: 66 case WM_SIZE: 67 { 68 GetClientRect(hwnd, &rc); 69 if (iWidth == rc.right - rc.left && iHeight == rc.bottom - rc.top) { 70 break; 71 } else if (rc.right - rc.left == 0 || rc.bottom - rc.top == 0) { 72 break; 73 } 74 iWidth = rc.right - rc.left; 75 iHeight = rc.bottom - rc.top; 76 77 if (mglrc != NULL) { 78 wglMakeCurrent(NULL, NULL); 79 wglDeleteContext(mglrc); 80 mglrc = NULL; 81 } 82 if (test_a != NULL) { 83 SelectObject(tmpDIB, test_a); 84 test_a = NULL; 85 } 86 if (hbmDIB != NULL) { 87 DeleteObject(hbmDIB); 88 hbmDIB = NULL; 89 } 90 if (tmpDIB != NULL) { 91 DeleteDC(tmpDIB); 92 tmpDIB = NULL; 93 } 94 95 /* Make Memory Device Context */ 96 BITMAPINFO bmi = { 97 sizeof(BITMAPINFOHEADER), iWidth, iHeight, 1, 24, BI_RGB, 0, 0, 0, 0, 0, NULL 98 }; 99 100 tmpDIB = CreateCompatibleDC(NULL); 101 102 if (tmpDIB == NULL)MessageBox(NULL, L"CCDC Failed", L"Caution", MB_OK); 103 104 void *pv; 105 106 hbmDIB = CreateDIBSection(tmpDIB, &bmi, DIB_RGB_COLORS, &pv, NULL, 0); 107 108 if (hbmDIB == NULL)MessageBox(NULL, L"DIBSec Failed", L"Caution", MB_OK); 109 110 test_a = SelectObject(tmpDIB, hbmDIB); 111 112 if (test_a == NULL)MessageBox(NULL, L"SelectObject Failed", L"Caution", MB_OK); 113 /* END Make Memory Device Context */ 114 /* SET PIXELFORMATDESCRIPTOR */ 115 PIXELFORMATDESCRIPTOR pfd = { 116 sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP, PFD_TYPE_RGBA, 24, 117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0, 118 }; 119 120 int format = ChoosePixelFormat(tmpDIB, &pfd); 121 if (format == 0) { 122 MessageBox(NULL, L"ChoosePixelFormat Failed", L"CAUTION", MB_OK); 123 GetLastError(); 124 } 125 if (SetPixelFormat(tmpDIB, format, &pfd) == FALSE)MessageBox(NULL, L"SetPixelFormat Failed", L"CAUTION", MB_OK); 126 127 mglrc = wglCreateContext(tmpDIB); 128 if (mglrc == NULL)MessageBox(NULL, L"wglCreateContext Failed", L"CAUTION", MB_OK); 129 130 /* END PIXELFORMATDESCRIPTOR*/ 131 wglMakeCurrent(tmpDIB, mglrc); 132 /* GL Initialization */ 133 glEnable(GL_COLOR_MATERIAL); 134 glEnable(GL_BLEND); 135 136 137 glViewport(0, 0, iWidth, iHeight); 138 glMatrixMode(GL_PROJECTION); 139 glLoadIdentity(); 140 glMatrixMode(GL_MODELVIEW); 141 glLoadIdentity(); 142 /* END GL Initialization */ 143 /* GL Contents */ 144 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 145 146 glPushMatrix(); 147 148 glColor3f(0, 1, 1); 149 glBegin(GL_TRIANGLES); 150 glColor3f(1.0f, 0.0f, 0.0f); 151 glVertex3f(0.0f, 1.0f, 0.0f); 152 glVertex3f(-1.0f, -1.0f, 0.0f); 153 glColor3f(0.0f, 0.0f, 1.0f); 154 glVertex3f(1.0f, -1.0f, 0.0f); 155 glEnd(); 156 157 glPopMatrix(); 158 glFlush(); 159 /* END GL Contents */ 160 /* PASS DC */ 161 } 162 break; 163 164 case WM_PAINT: 165 { 166 PAINTSTRUCT ps; 167 HDC hdc = BeginPaint(hwnd, &ps); 168 BitBlt(hdc, 0, 0, iWidth, iHeight, tmpDIB, 0, 0, SRCCOPY); 169 EndPaint(hwnd, &ps); 170 } 171 break; 172 173 case WM_DESTROY: 174 if (mglrc != NULL) { 175 wglMakeCurrent(NULL, NULL); 176 wglDeleteContext(mglrc); 177 mglrc = NULL; 178 } 179 if (test_a != NULL) { 180 SelectObject(tmpDIB, test_a); 181 test_a = NULL; 182 } 183 if (hbmDIB != NULL) { 184 DeleteObject(hbmDIB); 185 hbmDIB = NULL; 186 } 187 if (tmpDIB != NULL) { 188 DeleteDC(tmpDIB); 189 tmpDIB = NULL; 190 } 191 break; 192 } 193 194 return DefWindowProc(hwnd, uMsg, wParam, lParam); 195}

とは言っても、PC の性能次第では上記のように処理を変えても一瞬表示されてしまうと思います。それを回避するための別案は以下の通りです。

##2.ウィンドウの背景色を黒くする。

ウィンドウの背景色そのものを黒くしてしまえば、描画の遅延は目立ちません。

C++

1 WNDCLASSEX wc = { 2 sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW, WindowProc, 3 0, 0, hInstance, 4 NULL, (HCURSOR)LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), 5 NULL, CLASS_NAME, NULL 6 };

##3.背景色を白にする。

2とは逆に OpenGL での描画時の背景色を白くしてしまっても目立たないようにはできます。

C++

1 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 2 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

投稿2019/02/14 13:49

atata0319

総合スコア881

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問