사진은 Camera-relative rendering이 적용되었을 때와 그렇지 않을 때의 그래픽 깨짐을 비교한거임. 좌표는 8백만 근처. 다 내가 짠건 아니고 LÖVE 프레임워크 위에 g3d라는 라이브러리를 마개조해서 구동시키고 있음.
참고로 난 선형대수학은 물론이고 행렬조차 기본적인 이해 말고는 없는 수포자임으로 내 설명이 항상 맞다고는 보장 못함.
3D 모델을 화면에 출력하는 과정이 생각보다 간단하다는 것을 알고는 좀 놀랐음. 그냥 pm, vm, mm을 순서대로 곱하고 마지막에 위치값을 곱해주는 거였다는 사실.
근데 이 방식은 조금 문제가 있는데 원점 근처에서는 정확도가 높지만 원점에서 멀어질수록 세밀한 표현이 어려워진다는 문제점이 있다. 그래서 모델이 왕창 깨지게 되고 사물의 분간이 어려워진다.
이 문제를 해결하려면 몇가지 방법을 시도할 수 있다고 답을 들었다.
1. 배정밀도 사용하기: 이미 Lua는 배정밀도를 사용하고 있다. 문제는 그래픽이다. 따라서 올바른 해답이 아니다.
2. 특정 좌표계를 사용하기: 모르겠다. 이해못함.
3. 카메라 상대적인 렌더링 사용하기: 처음에는 ? 했지만 곧 깨닫게 되었다.
보통 컴퓨터 그래픽 공간에서의 이동은 뷰 행렬이 이동해서 결과를 만들어 낸다. 그 대신에 모델 자체가 이동하게 해서 같은 결과를 서로 다른 과정으로 만들어 내라는 것이였다.
행렬곱을 잘 모르겠지만 아무튼 높은 좌표에 있는 모델을 높은 좌표를 가진 뷰 행렬로 렌더링을 시도하면 나중에 버텍스 포지션 값의 정밀도에 영향을 끼쳐서 이런 문제가 발생한다고 추측했다. 그래서 버텍스 포지션의 정밀도를 높게 유지할려면 전체 연산 과정에서 행렬의 모든 원소가 0에 근접한 값이여야만 한다.
근데 뷰 행렬이 이동하지 않으면 카메라의 이동은 어떻게 처리하지? 그건 눈속임으로 해결할 수 있다. 카메라는 실제로 좌표가 이동하는 것으로 처리된다. 하지만 뷰 행렬은 불변이다. 대신 카메라의 좌표의 역을 각 모델 행렬에 더하면 뷰 행렬은 원점에 그대로 있지만 모델 행렬이 점점 원점에 가까워져서 카메라가 직접 이동한 것과 다름없는 결과물을 만들어낸다.
그리고 이 과정은 CPU 연산없이 GPU 상에서 병렬로 수행할 수 있으므로 모델이 몇개나 있어도 성능에 영향은 없다.
이제 모든 문제가 해결된 줄 알았는데... LÖVE의 라이브러리들이 전부 단정밀도를 사용해서 완전한 LWC(Large World Coordinates)는 구현이 불가능하게 되었다는 것이다... ㅠㅠ
그러므로 원점에서 멀리 떨어질수록 움직임이 이상해지는 jitteriness는 감수하고 사용해야 한다는 말이다. 물론 내가 최소한 마지노선이라고 생각하는 2의 15제곱 안팎의 좌표도 충분히 넓기 때문에 내가 만들 수준의 게임에서는 좌표계와 관련해서는 어떤 문제도 발생하지 않는다고 보장할 수 있따.
소스 코드는 엄연히 g3d를 개작한 것이기 때문에 내가 추가한 부분의 라이선스가 불분명해서 나중에 기능 추가와 개선이 이루어지면 간단한 게임과 함께 들고 오겠음.
절반 밖에 이해 못하긴 했는데 재밌네. 유니티 같은 게임엔진에선 어떻게 처리했을까도 궁금해지네.
그거 관련해서 내가 알아본 바로는 유니티는 아예 게임의 최대 공간을 50유닛으로 제한해서 해결했다고 들었음. (아마도 정수값으로는 50000정도?) 그리고 Camera-relative 말고도 사실 해결 방법이 많아서 내가 생각한 방법보다 더 괜찮은 방법도 있을 것 같음!
오우 알려줘서 고마워!! 유니티에 최대공간 한계가 있었구나 그건 몰랐네
아 완벽히 이해했어