wglSwapInterval関数で引数に1を指定することで、垂直同期をONにしたものの、60fps付近にはならず、32fps付近で安定してしまいます。
ディスプレイのリフレッシュレートはGetDeviceCaps関数より60fpsであること、DirectXを使用すれば60fpsで垂直同期を取れることも確認しています。
また、変な症状として、chromeでyoutubeを表示した状態にすると60fpsで安定化するという現象が発生します。
このように、いろいろと試してみてはいるのですが、どうすれば常にOpenGLで60fps付近をキープできるのか完全にお手上げ状態です。
なにかヒントや解決法などありましたら、ぜひご教授ください。
ちなみに当方環境は
OS:windows8.1
GPU:Intel HD Graphics 4000(ドライバは10.18.10.4061)
です。
以下にサンプルコードを載せます。
#include <Windows.h>
#include <tchar.h>
#include <gl\glcorearb.h>
#include <gl\wglext.h>
#include <chrono>
#include <sstream>
#pragma comment(lib, "opengl32.lib")
bool closed = false;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_DESTROY){ PostQuitMessage(0); return 0; }
if (msg == WM_CLOSE){ closed = true; return 0; }
return DefWindowProc(hWnd, msg, wParam, lParam);
}
bool MessageProcessing()
{
MSG msg;
if (closed){ return false; }
if (PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE) == 0){ return true; }
if (GetMessage(&msg, nullptr, 0, 0) <= 0){ return false; }
TranslateMessage(&msg);
DispatchMessage(&msg);
return true;
}
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
//ウィンドウ作成→HWND&HDC取得
WNDCLASSEX WindowClass;
WindowClass.cbSize = sizeof(WNDCLASSEX);
WindowClass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_DBLCLKS;
WindowClass.lpfnWndProc = WindowProc;
WindowClass.cbClsExtra = 0;
WindowClass.cbWndExtra = 0;
WindowClass.hInstance = hInstance;
WindowClass.hIcon = nullptr;
WindowClass.hCursor = nullptr;
WindowClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
WindowClass.lpszMenuName = nullptr;
WindowClass.lpszClassName = _T("TestWindowClass\n");
WindowClass.hIconSm = nullptr;
if (RegisterClassEx(&WindowClass) == 0){ return -1; }
const UINT WindowCreationStyle = WS_OVERLAPPEDWINDOW & ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
const UINT WindowStyleEx = 0;
RECT Size = { 0, 0, 640, 480 };
AdjustWindowRectEx(&Size, WindowCreationStyle, FALSE, WindowStyleEx);
HWND hWnd = CreateWindowEx(WindowStyleEx, WindowClass.lpszClassName, _T("Test\n"), WindowCreationStyle,
CW_USEDEFAULT, CW_USEDEFAULT, Size.right - Size.left, Size.bottom - Size.top,
nullptr, nullptr, nullptr, nullptr);
if (hWnd == nullptr){ return -1; }
ShowWindow(hWnd, nCmdShow);
HDC hDC = GetDC(hWnd);
// HGLRCの作成
PIXELFORMATDESCRIPTOR pfd = {};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.cColorBits = 24;
pfd.cRedBits = 8;
pfd.cGreenBits = 8;
pfd.cBlueBits = 8;
pfd.cAlphaBits = 8;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
int PixelFormat = ChoosePixelFormat(hDC, &pfd);
if (PixelFormat == 0){ return -1; }
if (SetPixelFormat(hDC, PixelFormat, &pfd) != TRUE){ return -1; }
HGLRC hGLRC = wglCreateContext(hDC);
if (!wglMakeCurrent(hDC, hGLRC)){ return -1; }
//関数ポインタの取得
PFNGLCLEARCOLORPROC glClearColor = reinterpret_cast<PFNGLCLEARCOLORPROC>(wglGetProcAddress("glClearColor"));
PFNGLCLEARDEPTHPROC glClearDepth = reinterpret_cast<PFNGLCLEARDEPTHPROC>(wglGetProcAddress("glClearDepth"));
PFNGLCLEARSTENCILPROC glClearStencil = reinterpret_cast<PFNGLCLEARSTENCILPROC>(wglGetProcAddress("glClearStencil"));
PFNGLCLEARPROC glClear = reinterpret_cast<PFNGLCLEARPROC>(wglGetProcAddress("glClear"));
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(wglGetProcAddress("wglSwapIntervalEXT"));
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = reinterpret_cast<PFNWGLGETSWAPINTERVALEXTPROC>(wglGetProcAddress("wglGetSwapIntervalEXT"));
PFNGLFLUSHPROC glFlush = reinterpret_cast<PFNGLFLUSHPROC>(wglGetProcAddress("glFlush"));
glClearColor(0.f, 0.f, 0.f, 1.f);
glClearDepth(1.f);
glClearStencil(0);
wglSwapIntervalEXT(1);//垂直同期ON
auto begin = std::chrono::system_clock::now();
auto end = std::chrono::system_clock::now();
//メインループ(fpsの計測は10フレームをまとめて行う)
for (unsigned int count = 0; MessageProcessing(); count++)
{
if (count % 10 == 0){ begin = std::chrono::system_clock::now(); }
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glFlush();
if (SwapBuffers(hDC) == FALSE){ return -1; }
if (count % 10 == 9)
{
end = std::chrono::system_clock::now();
std::basic_stringstream<TCHAR> Title;
Title << "No:" << count + 1 << " " << "RR:" << GetDeviceCaps(hDC, VREFRESH) / wglGetSwapIntervalEXT() << " " << "FPS:" << 1000.f / std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() * 10 << "\n";
SetWindowText(hWnd, Title.str().c_str());
}
}
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(hGLRC);
ReleaseDC(hWnd, hDC);
DestroyWindow(hWnd);
return 0;
}