Это кажется огромным секретом для программистов, никто не хочет делиться своими кодами для этого.Почему?
Я не могу найти работающий ограничитель FPS, который мог бы ограничить FPS по крайней мере до 60 без использования v-sync.
И я хочу, конечно, сделать это правильно.Так что я еще не сделал сам, потому что все они говорят, что им понадобился год, чтобы выучить все приемы в ограничителях fps ...
Edit: вот мой код ограничителя fps, которыйне совершенен, но лучше, чем я мог, он все еще рвется, хотя:
timeBeginPeriod(1);
frame_start_time = TimerGetTime();
while(!done){
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT){
done = 1;
}else{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}else if(active){
draw_everything();
SwapBuffers(hDC);
// fps limiter:
one_frame_limit = 1000.0f/(float)framerate_limit; // 16.666 ms
while((time_left = one_frame_limit-(TimerGetTime()-frame_start_time)) > 0){
if(time_left >= 6.0f){
Sleep((int)(time_left/6.0f));
}else{
Sleep(0); // sleep less than 1ms
}
}
frame_start_time = TimerGetTime();
}
}
EDIT2: вот моя вторая попытка с использованием ожидаемых таймеров, как было предложено:
float one_frame_limit = 1000.0f/(float)framerate_limit;
float time_left = one_frame_limit-(TimerGetTime()-frame_start_time); // 4.7432ms
liDueTime.QuadPart = -(LONGLONG)(time_left*10000.0f);
if(SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0)){
WaitForSingleObject(hTimer, INFINITE);
}
while((time_left = one_frame_limit-(TimerGetTime()-frame_start_time)) > 0.003f){
Sleep(0);
}
frame_start_time = TimerGetTime();
Работает лучше, я думаю.Но все еще разрывается ... Обратите внимание, что я добавил цикл while, потому что разрывался больше, чем без него.
-
Другой вопрос: безопасна ли эта инициализация?:
HANDLE hTimer = NULL;
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = -100000LL; // testing timer: wait for 10ms
hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
if(hTimer == NULL){
waitable_timer_supported = 0;
}else if(!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0)){
waitable_timer_supported = 0;
}else if(WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0){
waitable_timer_supported = 0;
}
Боюсь, что последние 2 проверки могут быть неудачными, даже если таймер ожидания поддерживается ... пока он не сработал.Это правильный подход проверки его поддержки?