화면에 그림을 그리기 위해서는 셰이더를 통해 GPU에 연산을 시키고 그 결과 값을 화면에 띄워줘야한다.
흔히 게임에서는 실시간 조명을 쓰지 않고 미리 조명을 계산하여 나온 값을 텍스쳐에 기록해두고 덮어 씌우는 방식으로 구현한다.
왜냐면 실시간 광원은 매우 무겁기 때문이다.
VRChat은 forward렌더링이라는 과정을 거치는데, 이 렌더링은 n x m 만큼의 연산을 요구한다.
(n = 광원 수, m = 조명에 영향을 받는 물체의 버텍스 수)
광원이 없을 때는 m만큼만 연산하면 된다. 하지만 실시간 광원이 하나라도 존재하는 순간 n x m의 계산을 추가로 하게 된다.
VRChat아바타의 평균 버텍스 수는 8만이다. 이 정도만 해도 sss급 게임의 수준인데 거기에 실시간 광원의 연산이 더해지는 거다.
그런데 VR환경은 같은 물체를 한번 더 렌더링하여 다른 눈에도 띄워줘야한다. 2배로 무거워지는 것.
거기에 광원 연산도 더하니 60프레임 이상이 나오기가 힘든 것이 당연하다.
그래도 실시간 광원 자체는 현대 GPU에서 막 무겁다고 볼 수는 없고 가장 결정적으로 무거운건 그림자 연산이다.
그림자의 원리가 뭐냐면 조명의 위치에서 한번 더 물체를 렌더링하고 조명에서는 안 보이고 내 시점에서는 보이는 곳을 비교하여 검정색으로 칠 해주는 것이다.
사진은 왼쪽이 내가 보는 시점, 오른쪽이 광원이 보는 시점이다.
광원은 안 보이고 나는 보이는 곳을 시각화하면 이런식으로 되는데, 저 부분이 검은색이 되어 그림자가 되는 것이다.
참고로 이건 빛의 방향이 하나뿐인 Directional Light의 경우고, Point라이트는 6방향을 전부 한번 더 렌더링 해야 그림자를 얻어낼 수 있다.
결론)
VRChat아바타의 평균 버텍스 수 8만이 있다고 칠 때 단순 계산만으로 조명이 없으면 8만번의 연산이면 되는 것이
실시간 조명이 하나 추가 되면 16만번이 되는 것이고
그림자가 추가되면 24만번이 되는 것임.
당연하지만 실시간 조명의 연산에 들어가는 추가적인 행렬, 벡터 연산과
그림자 연산에 들어가는 행렬, 벡터 연산은 포함 되지 않았기에 기본보다 최소 3~10배 무겁다 정도만 알아두면 될 것이다.