정글에서 온 개발자

12/25 TIL SDL 라이브러리, 스크린 테어링, 델타 시간 본문

TIL

12/25 TIL SDL 라이브러리, 스크린 테어링, 델타 시간

dev-diver 2024. 12. 25. 23:34

SDL 라이브러리

* Simple DirectMedia Layer 라이브러리
* Mac, Window 상관 없이 윈도우 생성, 기본 2D 그래픽 처리, 입력 처리, 오디오 출력 등을 가능하게 해주는 게임 개발 라이브러리

게임 프레임의 구조

  1. 입력
  2. 게임 세계 갱신
  3. 출력

* 메인 함수 안에 Game.RunLoop() 가 있고, RunLoop의 while문 안에 Game.입력, Game.갱신, Game.출력 메소드가 들어있는 구조

SDL_PollEvent

while(SDL_PollEvent(&event))
{
}

위 코드에서 , 큐에 요소가 있는한 계속 true를 반환한다. 
큐 쌓이는 속도가 while문 처리속도보다 빠르면 frame이 밀릴 수도 있다. 이걸 어떻게 해결하는지는 찾아봐도 모르겠다.
직접 처리속도를 제한하는 방법은 없고, 큐에 들어갈 이벤트를 필터링 한다거나 특정 이벤트들을 제거하는 간접적인 방법이 있다고 한다.

이 코드를 쓰는 것만으로도 윈도우 이동등의 일부 이벤트를 SDL이 자동으로 처리한다.

스크린 테어링, 더블 버퍼링, vsync

현재의 디스플레이는 전체 화면을 한순간에 갱신할 수 없다.(위부터 순차적으로 갱신해야 함)  하지만 게임은 그래픽 카드를 쓰면 갱신이 더 빠를 수 있다.
이때, 하나의 버퍼를 사용하면 디스플레이가 색상 버퍼로부터 데이터를 읽는 도중에 게임이 (다음 장면을) 버퍼에 덮어 씌울 수 있다.
이러면 화면이 찢어질 수 있는데 이 현상을 '스크린 테어링' 이라고 한다.

이걸 해결하기 위해, 게임은 후면버퍼에 쓰고, 디스플레이는 전면 버퍼에서 읽으며 프레임이 완료된 후 버퍼를 서로 교환하는 방법을 쓸 수 있다. (더블 버퍼링)

이렇게 해도 스크린 테어링은 여전히 있을 수 있는데, 게임이 너무 빨리 업데이트 되는 경우에 디스플레이가 자기 버퍼를 모두 그릴 때까지 기다려서 해결할 수 있다. (수직 동기화, vsync)

이런 기다림 때문에 vsync는 버벅거림(stuttering)을 유발할 수 있는데, 모니터 주사율이 높은 경우에도 일어날 수 있다. (주사율이 fps의 배수가 아닌경우)

그래서 게이머가 vsync on/off를 켜고 끄게 할 수도 있고 '적응형 화면 재생 빈도' 등으로 해결 할 수 있다. 그러나 모니터도 해당 기술을 지원해야 한다.

스크린 테어링

델타 시간

실시간과 게임시간은 구분되어야 한다. (불릿 타임 등 일부러 느리게 가는 시간도 있다.)
'게임 갱신' 단계에서는 경과된 게임 시간을 고려해야 한다.
델타시간은 마지막 프레임 이후로 경과된 게임 시간을 말한다. (1초에 대한 상대적 시간)

GetTicks는 49.7일이 지나면 오버플로우가 발생할 수 있다. 부호 없는 정수로 랩핑하면, deltatime 계산에는 크게 문제가 없다. 
혹은 분기처리를 해주거나, 타임 초기화를 짧게 가져가자

틱 시간으로 계산해도 오차는 쌓일 수 있으므로, 네트워크 게임에서는 시간 공유는 서버를 기준으로 하는 게 좋다.

참조

Game Programming in C++ , 산자이 마드하브