-
[DirectX11] chrono로 정확한 DeltaTime 구하기DirectX11 2023. 12. 18. 17:17
DeltaTime은 프레임 렌더링이 됐을때 이전 프레임에서부터 시간이 얼마나 지났는지를 뜻한다.
1초에 60프레임이 일정하게 나오면 각 프레임 사이의 DeltaTime은 1/60 초씩으로 약 0.01667 초다.
실시간 렌더링에서는 초당 프레임이 높게 나와야하므로 DeltaTime의 값이 매우 작아지게되어 정확도가 중요해진다.
그리고 게임에서는 DeltaTime을 기준으로 작동하는 계산이 많아서 중요도가 높다.
이전 글에서 입력으로 카메라를 조작하는 내용을 다뤘는데 그 중에서 이동 속도는 DeltaTime을 곱해서 적용한다고 했다.
이렇게 하지 않으면 초당 프레임 개수에 따라 이동 속도가 달라지는 문제가 생긴다.
애초에 속도가 초당 이동거리이므로 일정한 이동 속도를 위해서는 DeltaTime이 꼭 필요하다.
그래서 적절한 이동 속도를 구해서 적용해봤는데 이동에 약간 이질감이 들었다.
초당 프레임은 충분히 높지만 그에 비해 이동은 너무 끊기는 느낌이었다.
그래서 화면을 녹화해서 프레임 하나씩 비교해봤더니 이동하는 중에 실제로 끊김이 발생했다.
중간에 점프하듯이 빠르게 이동하고 그 다음 한 프레임동안 멈추는 문제가 2번 발생한다. 문제의 원인은 DeltaTime이었다.
다이렉트x의 예제에서는 시간 계산에서
GetTickCount64()
함수를 사용한다.시스템이 시작된 후 경과된 시간을 밀리초로 리턴해주는 함수다.
예제를 따라서 DeltaTime은 이 함수를 통해 계산하고있었는데 이 함수로 받은 시간의 정확도가 충분하지 않았다.
이 함수로 DeltaTime을 계산한 결과는 아래와 같다.
0.0159999 0 0.015 0 0.016 0 0 0.016 0 0.015 0 0.016 0 0.0159999 0 0
DeltaTime은 주로 0초로 계산이되고, 중간중간에 약 0.016초로 한번씩 튀는 문제가 있다.
이런 문제때문에 갑자기 점프하듯이 이동하게 되었다.
0.016초면 초당 약 60프레임이고, 내 환경에서는 초당 약 144프레임이 나오니 두 프레임에 한번꼴로 이런 문제가 생기는 상태다.
더 정확도가 높은 계산이 필요했다.
그래서 찾은 방법이 chrono다.
chrono를 사용한 DeltaTime 계산은 다음과 같다.
#include <chrono> // ... double CurrentTime; double PrevTime; double DeltaTime; std::chrono::steady_clock::time_point StartTime_chrono; std::chrono::steady_clock::time_point CurrentTime_chrono; std::chrono::steady_clock::time_point PrevTime_chrono; // ... int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { // ... StartTime_chrono = std::chrono::high_resolution_clock::now(); CurrentTime_chrono = StartTime_chrono; PrevTime_chrono = StartTime_chrono; // ... } // ... void UpdateTime() { CurrentTime_chrono = std::chrono::high_resolution_clock::now(); DeltaTime = std::chrono::duration<double, std::chrono::milliseconds::period>(CurrentTime_chrono - PrevTime_chrono).count(); DeltaTime /= 1000.f; PrevTime_chrono = CurrentTime_chrono; CurrentTime = std::chrono::duration<double, std::chrono::milliseconds::period>(CurrentTime_chrono - StartTime_chrono).count(); CurrentTime /= 1000.f; }
적용 후에는 DeltaTime이 더 정밀하게 계산되었다.
0.00719 0.007188 0.0063917 0.0074631 0.0064536 0.0075708 0.0062998 0.007523 0.0063851 0.007333 0.0066719 0.0072219 0.0065646 0.0073098 0.0067868 0.007034 0.006678 0.0071531 0.0073364
1초당 144프레임이면 DeltaTime은 약 0.007초이므로 제대로된 결과다.
'DirectX11' 카테고리의 다른 글
[DirectX11] CubeMap 적용 (1) 2023.12.20 [DirectX11] 1인칭 카메라 조작 (0) 2023.12.18 [DirectX11] 쉐도우 맵과 PCF(Percentage Closer Filtering) (3) 2023.12.15 [DirectX11] 텍스쳐와 노멀매핑 (1) 2023.12.13 [DirectX11] Disney Diffuse (0) 2023.12.12