최근 급하게 어떤 프로젝트에 투입되서 작업을 하고 있다. 다른 회사와 같이 일을 하고 있는데, 다른 회사에서 해놓은 것들이 너무 느려서 최적화를 해야했다. 결국 일반적인 잔머리로는 도저히 해결할 수 없는 상황에 봉착했다. 1년 전의 필자였다면 포기하고 안된다고 했었겠지만 다행히 약간의 노하우를 통해 해결할 수 있었다.

상황과 문제?

요즘 한국에서는 VR 게임/컨텐츠들이 굉장히 많이 개발되고 있다. 필자도 그 와중에 떨어진 프로젝트를 하나 받아진행하게 되었다. 개발은 주변 3D 환경을 다른 회사에서 해주고, 게임이 돌아가는 코어 시스템을 필자의 회사에서 작업하기로 되어 있었다. 게임에서의 코어 시스템은 개발을 하였으나 Unity 에 의존적인 코딩은 거의 진행되지 않은 상태에서 한달전 프로젝트에 투입되었다.

그렇게 하나하나 작업을 하면서 코어 시스템과 3D 환경을 결합하는 도중, 터무니 없는 경우를 만났다. 바로 SkinnedMeshRendererAnimator 가 약 800 개 정도되는 상황에 부딫쳤다. 여기서는 두가지의 큰 부하가 있었다. 절대적인 Vertex Skinning 부하와 Animator 가 800개가 한꺼번에 계산되는 부하였다. Vertex 숫자는 LOD 베이커를 구해서 어떻게든 해결이 되었으나, 800개의 Animator 부하는 우회방법이 없었다. 즉 이는 Vertex ShaderCompute Shader 안에서 AnimationClip 의 정보들을 처리하는 정공법이 필요했다.

하지만 기한도 얼마 남지않아 급한 와중에 저것들을 직접 코딩할 여유는 없었다. 게다가 처음 건드려보는 부분이라서 헤멜 코스트까지 합하면 굉장히 암울했다. 혹시 오픈소스가 있나 싶어서 생각을 해보았는데 예전에 SkinRenderer 를 직접 구현하면서 찾아본 오픈소스 레포지토리가 하나 있었다.

Github : GPUSkinning

한 중국인이 개발한 스키닝 툴이다. 이는 두가지의 큰 기능을 담고있다. 하나는 Vertex Shader 에서 Skinning 처리를 해주는 기능과, 하나는 AnimationClip 들을 직접 샘플링해 바이너리 파일로 저장해 GPU 메모리에 텍스쳐의 형태로 올려두어 사용하는 기능이 있다.

Compute ShaderVetex Shader 를 사용해 Skinning 을 구현하는 것은 크게 어려운 것은 아니다. Deformation 하지만 제일 시간이 오래걸리는 부분은 AnimationClip 을 가공하는 부분이 제일 오래 걸리는 부분 중 하나다. 해당 레포지토리에는 그 오래걸리는 부분을 만들어 놓았다. 사실 이 부분으로만으로 꽤 큰 가치가 있다. 부가적으로 원하는 bone 의 위치와 회전값을 Transform 으로 만들어 Hierarchy 상에서 컨트롤이 가능하다.

조금 불편한 점도 몇가지 있다. 한번에 여러개의 샘플링이 안되고, 에디터에서 필수적으로 지원해야할 멀티 에디팅이 안된다. 후자는 간단히 코드를 수정하면 되지만 전자는 샘플링 과정에서 플레이를 해야되기 때문에 직접 수정하기엔 조금 부담스럽다. Vertex Shader 에 스키닝이 물려있기 때문에 Skinning 을 수정하려면 Shader 부분도 바꿔야하고, LOD 기능도 어설프게 들어있어 조금 애매하다.

더 기능을 생각하자면 IK 나 특정 본을 타겟으로 회전을 시키는 기능이 없다. 이는 mecanim 에서 Humanoid 를 타겟으로 지원하는 기능으로 이 기능까지 만들어 놓았으면 엄청 유용 했을것 같다. 다만 구현이 Vertex Shader 에서 되어서 다른 기능을 끼워넣기는 조금 부담스러운 것으로 생각된다.

굳이 단점을 생각하지 않아도 샘플링 코드와 구현만으로도 충분히 가치있는 레포지토리로 생각된다. ComputeShader 를 사용해서 구현했으면 더 좋았을 것 같다는 생각이 문득든다.

써보면서 이게 본격적으로 쓰려고 만들어진 코드는 아닌 것 같다는 생각이 들었다. 기본적인 캐싱도 안되있어서 약간의 삽질을 했었다.

가장 큰 문제는 AnimationClip 이 많으면 많을수록 에디터, 런타임 로드시에 엄청나게 로딩이 걸린다. 아마 ScriptableObject 에 Serialization 으로 저장한 정보들이 많아서 그런듯 하다. 이는 따로 텍스쳐든 뭐든 Unity 에서 직접 관리하는 리소스로 바꾸어야 겠다.

참조