2011-12-08 1 views
0

VSYNC를 사용하지 않고 FPS를 수정하는 것에 대해 빠른 질문이 있습니다.VSYNC없이 고정 프레임 속도 드로 루프 작성에 대한 생각

현재 그리기 사이의 시간을 계산하는 draw 루프가 있습니다 ( ). 그리고 프레임 속도를 안정화하기 위해 그려야하는 시간을 뺍니다.

static clock_t dt = clock(); 
static clock_t startDraw; 
static clock_t endDraw; 

while (_running) 
{ 
    update(); 

    // Draw after desired elapsed time 
    if (clock() - dt >= _timestep) 
    { 
     startDraw = clock(); 
     draw(); 
     _window->SwapBuffer(); 
     endDraw = clock(); 
     dt = clock() - (endDraw- startDraw); 
    } 
} 

_timeStep는 초당 60 프레임을 표현하기 위해 현재 16,하지만 난 나중에 초당 30 프레임으로 변경 할 수 있습니다 :

는 여기에 내가 지금 무슨이다.

VSYNC가 없으면이 값은 40 ~ 62fps 사이에서 변동되므로 접근 방식이 잘못되었거나 뭔가를 간과하고 있는지 확실하지 않습니다.

내 목표는 VSYNC 토글을 사용하는 것이므로이 기능을 추가하고 싶습니다.

참고 : 렌더링을 위해 OpenGL을 사용하고 있습니다. 대부분 OpenGL_2.0입니다.

답변

0

이 코드에 주목 한 몇 가지 점이 있습니다.

첫째로, 당신의 마지막 줄 : 그래서 당신이 현재 측정하는 것은 마지막 무승부라는부터 바로 시간()입니다

endDraw = clock(); 
dt = startDraw; 

:

endDraw = clock() 
dt = clock() - (endDraw - startDraw); 

은 동일합니다. 당신은 실제로 그려야하는 시간을 뺀 것이 아닙니다.

이제 왜 이렇게 변동성이 큰지에 대한 이유는 여러 가지 이유 때문입니다. 타이밍 코드에서 update()를 호출하는 시간과 각 평가에서 draw()를 호출 할 시간을 합한 것입니다. 이는 측정 세분성이 update() + draw()를 실행하는 데 걸리는 시간에 의해 제한된다는 것을 의미합니다. 결과적으로 fps 리미팅 루프는 최대 fps 60fps의 상한선 만 배치하지만 수행중인 작업량에 따라 60fps보다 훨씬 느리게 실행될 수 있습니다. 왜 어떤 경우에는 40fps가 표시되는지 설명합니다. 당신이 보았던 62fps는 아마도 반올림 오류이거나 fps를 측정하는 방법 때문일 것입니다.

예를 들어, update() + draw()가 4ms가 걸리는 경우. 현재 "clock() -dt" 평가는 마지막 무승부 이후 15ms이며, 다음에 마지막 무승부 이후 19ms 였을 것입니다. 이 프레임이 느린 fps로 실행됨을 의미합니다.

별도의 스레드에서 draw() 논리를 실행하면 약간 더 안정적으로 만들 수 있습니다. 즉, 업데이트 비용()은 렌더링 루프에 포함되지 않습니다. 그러나 이것은 업데이트 동기화와 같은 다른 복잡성을 증가 시키므로 몸 위치가 아직 업데이트되지 않은 상태에서 사람의 머리의 업데이트 된 위치를 그려서는 안됩니다.

제 질문은 왜 프레임 속도를 60fps로 제한하려고합니까? 그것은 CPU 사용량을 줄이기 위해 무엇입니까? cpu 사용에 신경 쓰지 않는다면 실제로 트리플 스크린 버퍼 시스템을 사용할 수 있습니다. 가능한 한 자주 draw()를 실행하고 별도의 스레드에서 60fps로 SwapBuffer()를 호출하십시오 (물론 동기화에주의하십시오). SwapBuffer는 draw() 또는 update()보다 훨씬 가볍기 때문에 상당히 안정적인 fps를가집니다.

+0

야, 내 주요 관심사는 CPU 사용이다. 내 목표는 NDK를 통해 Android에 대한 지원을 추가하는 것입니다. 현재 SwapBuffer로 이중 버퍼링을 사용 중입니다. – redsting

+0

당신이 고려할 수있는 한 가지는 draw() 전에 SwapBuffer를 수행하는 것입니다.그렇게하면 디스플레이가 먼저 새로 고침됩니다 (타이밍 코드로 draw() 비용이 발생하지 않음). 이렇게하면 약간 더 안정적인 재생 빈도가 제공됩니다. 유일한주의 사항은 화면 새로 고침이 항상 1 프레임 뒤가되지만 보통 30fps 또는 60fps 응용 프로그램에서 중요하지 않아야한다는 것입니다. – Skyd