오늘 적을 내용은 많지 않다. 하지만 디버깅(코드작성이 아닌)에는 정말 많은 시간이 들어갔다.
영상도 찍은 김에 짤막한 내용이라도 적는다.
1. Holographic API는 기본적으로 왼쪽/오른쪽 눈에 대한 view-projection matrix를 넘겨준다. 내 엔진은 왼손 좌표 기준인데, 이 매트릭스들은 빌어먹을 오른손 좌표계 기준이다.
일단 화면을 보는게 급했기 때문에 view matrix로부터 eye position, eye direction, up벡터를 추출해서 왼손좌표계 기준으로 view matrix를 새로 만들었다. 그리고 projection matrix에 대해서는 왼쪽 오른쪽이 다를게 없다고 생각해서(일반적인 싱글 카메라 기준이라면 fov가 실시간으로 변할 일이 없으므로) 엔진에서 사용하는 기본 fov를 주고 새로 하나 만들었다. 그렇게 해서 화면에 캐릭터를 띄울 수 있었고 먼저번 데모영상을 촬영할 수 있었다.
그런데 떨림이 엄청나게 심했다. 프레임 레이트 대비 카메라 움직임을 생각하면 많이 떨리는게 당연하긴 하지만 지금껏 발표영상들을 보면 생각보다 떨림이 없었다. 그래서 뭔가 이것도 개선할 수 있는 방법을 갖고 있지 않을까 추측했다. 문서를 읽어보면 자체적으로 이미지 떨림 보정 알고리즘같은걸 갖고 있는것 같다.
HoloLens가 지원하는 떨림 보정 알고리즘이 있다면, 그리고 그걸 사용하려며 원래 정해진 방법대로 사용해야할것 같아서 projection matrix도 HoloLens에서 던져주는걸 그대로 사용하기로 했다. 좌표계 차이는 HoloLens에서 주는 projection matrix의 몇몇 성분에 -1을 곱해주는걸로 해결. 그렇게 해서 일단 영상은 무사히 출력된다.
그리고 놀랍게도 떨림이 크게 줄었다.
holographicFrame->UpdateCurrentPrediction(); HolographicFramePrediction^ prediction = holographicFrame->CurrentPrediction;
카메라의 위치를 구하기 전에 이런식의 코드를 먼저 실행하고 prediction객체로부터 매트릭스를 얻어온다. Get이 아니라 prediction이란 단어를 사용하는데 주목할 필요가 있다. HoloGraphics API에서 속도와 방향들을 고려한 보정을 적용해서 projection matrix를 던져주는것 같다.
하여간 영상은 잘 출력되고 떨림도 줄어서 만세를 불렀지만 문제가 또 생겼다. 그림자 지는 영역이 촛점이 전혀 맞지 않아서 상당히 어지러웠다. 틀림없이 그림자가 잘못된 위치에 그려지고 있었다. 아니 그보다는 스테레오 그래픽임을 감안해도 왼쪽 오른쪽 눈에 대한 그림자 위치가 너무 많이 어긋났다.
한참 고민하다가 HoloLens에서 주는 projection matrix를 확인해보니 m21,m31,m32성분이 0이 아니었다. projection matrix를 fov와 near-far값을 가지고 만들어면 이 성분들은 0이다.
현재 그림자는 Deffered방식으로 처리한다. 스크린 스페이스에서 depth buffer의 z값을 가지고 그림자를 받을 픽셀의 월드 좌표를 계산한다. 월드 좌표를 계산하기 위해서 projection matrix의 성분들에 대해서 역연산을 하는데 여기서 m21,m31,m32성분이 0이라고 가정했으므로 HoloLens가 주는 projection matrix를 사용하면 deffered shader에서 월드 좌표를 구할때 당연히 문제가 생긴다.
일단 이 부분을 수정하고나니 그림자도 정상적으로(어지러움 없이) 출력된다. 그런데 z-bias문제로 보이는 문제가 꽤 심각하다. 에뮬레이터에선 문제가 없지만 HoloLens를 실제로 쓰고 보면 이동하거나 방향에 따라서 shadow map의 z-bias문제로 보이는 현상이 꽤 두드러진다. 일단 이 문제는 나중에 고민하기로 하자.
2. 에뮬레이터의 동작은 실제 HoloLens 디바이스 동작과 많이 다를 수 있다. 예를 들어 아래와 같은 스샷을 보면 에뮬레이터에선 바닥이 렌더링 되지 않는다.
3개 버전의 렌더링 코드와 쉐이더 코드는 똑같다.
왼쪽 위 – win32 + DX11버전 , 중간아래 – UWP + DX11버전 , 오른쪽 – UWP + DX11 버전 on HoloLens Emulator -> 바닥 렌더링 안됨
내 코드에 뭔가 문제가 있거나 아니면 에뮬레이터 버그를 피해갈 방법이라도 있나 해서 몇시간이나 코드를 고쳐봤지만 어떻게 해도 안나온다. 결국 포기했는데 HoloLens디바이스에선 정상적으로 렌더링된다.
일단 에뮬레이터 자체의 그래픽스 기능을 완전하게 신뢰할 수 없다. 그 외에도 에뮬레이터가 nvidia GPU에서 돌아가는지, intel GPU에서 돌아가는지에 따라서도 작동이 다소 다르다. intel 내장 GPU에서 에뮬레이터가 돌아갈때 버텍스 좌표 보간에 문제가 있는걸 발견했다. HoloLens 에뮬레이터는 Remote FX를 사용하기 때문에 Remote FX + intel GPU가 문제라고 보는게 맞을것 같다. 물론 같은 렌더링 코드를 에뮬레이터가 아닌 win32나 UWP앱으로 같은 intel GPU에서 돌릴땐 아무 문제 없었다.
에뮬레이터에서 양쪽 눈에 대한 매트릭스를 얻어보면 왼쪽 오른쪽 똑같이 나온다. 에뮬레이터가 스테레오 그래픽을 처리할 수 없으므로 어쩌면 당연한건지도 모르겠지만 이건 꽤 문제가 된다. 위의 projection matrix에 대한 디버깅 같은건 에뮬레이터로는 할 수 없다.
3. XBOX ONE S의 컨트롤러를 블루투스로 연결할 수 있다. 아주 잘 작동한다. XBOX 컨트롤러 연결이 가능하더라도 UWP전용의 Windows::Gaming::Input API만 사용 가능한게 아닐까 걱정했다. 다행히도 XInput API도 잘 작동한다. UWP에서도 XInput은 사용할 수 있고 내 프로젝트에선 XInput을 사용한다.
Dx11 공부하면서 많은 힘이 되고있습니다.
이렇게 좋은 내용을 한글로 남겨 주셔서 감사합니다.
한글로 이제 글 안남긴다고 하셔서 큰일 났다고 생각했는데
한글로 좋은내용 남겨주시면 저같은 사람들에게 많은 도움이 될꺼같습니다~ 간간히 질문 올려서 답변받을때 많은 도움이 되었습니당 감사합니다.
좋아요좋아요
김사합니다. 도움이 되셨다니 보람이 있네요. 이건 말 그대로 메모고 나중에 정리해서 하나의 문서로 다시 작성할 생각입니다.
좋아요좋아요