[그래픽스] three.js기초지식 (texture vs material)과 파일형식(glb vs gltf)
카테고리: graphics
🚀Introduction
3D . three.js관련 포트폴리오를 준비하거나, 프로젝트를 하고있다면 최적화를 생각해볼 것이다. (필자처럼)3D 에셋 데이터에 대한 지식이 부족한 사람들을 위해, 엔지니어링을 시도하기 전 알고 진행하면 좋을법한 내용들에 대해 작성해볼 것이다.
다음글인 3d lazy loading
에 대해 알아보기 전 알아야 할 기본 지식들이다.
🚀시작 전…
⭐️기본지식: object와 mesh (geometry + material)
3d 데이터를 떠올린다면 통상 물체를 object
라고 할 것이다. 하지만 three.js에서는 mesh
라고 한다. geometry와 material의 조합을 mesh라고 한다. 따라서, 통상 3D데이터에서 하나의 오브젝트를 떠올릴 떄, three.js에서는 mesh를 떠올리면 될 것 같다. 내가 방금 가져온 사람모양의데이터는, 하나의 사람mesh인 것이고, 기본으로 생성된 큐브object(라고 생각되는것도) 하나의 mesh라고 생각하면 편할 것이다(three.js라이브러리 소스코드를 살펴보면 Object3D클래스
를 상속받은게 mesh이긴 하다). 초보자라면 object는 mesh이다!!! 뼈다귀(geometry)와 material(껍데기)를 합한게 mesh이다!!! 라고 생각해도 큰 무리가 없다.
geometry + material 은 three.js에서 mesh이다
⭐️기본지식: material
그렇다면 그 외의 속성은 어디에 있을까? 금속성(metalness), 거칠기(roughness), 색상(color) 등의 정보는 어디에 있을까? 정답은 material 내부 속성으로 존재한다.
금속성, 거칠기, 색상, 투명도 등등은 material속성에 존재한다.
⭐️기본지식: texture
아이언맨의 새빨간 금속성 재질, 공대생 체크무늬 셔츠의 체크무늬 패턴 등등은 어떻게 정의되는걸까? 이는 texture에 있다. 그렇다면 geometry는 뭔가 점으로 이어진 모양
에 관한 정보이고, material
은 그 껍데이같은 느낌이니, texture도 material
에 포함되어있을까?
material
은 texture
를 포함하고 있나요? 라고 묻는다면 정답은 녜니요다. texture은 material 내부에 있지 않다. 하지만, material은 texture들을 참조하고 있다. 즉, 다양한 종류의 material이 모두 동일한 texture를 참조하고 있을 수도 있다. 예를들면, 빨간돌맹이, 파란돌맹이, 초록돌맹이는 돌맹이.png
로 정의되어있는 이미지를 참조하지만, 각각의 material속성들(색상, 금속성, 거칠기)은 다를수도 있는 것이다.
즉, material은 texture정보의 참조값을 들고있다.
🚀three.js 최적화를 위한 지식
⭐️geometry와 texture의 크기
geometry와 material중 어떤것이 더 용량을 많이 차지할까?
아마 정확한 답을 바로 떠올리긴 힘들 것이다. 그렇다면 다음 이미지에서는 어떨까?
좌측은 엄청난 용량의 4K이미지이고, geometry는 용량차지가 거의 없는수준, texture는 엄청난 용량을 차지할 것이다. texture용량이 3D에셋의 전체용량의 99.99999%를 차지할 것이다.
아래의 경우에는 어떨까?
좌측의 3d 에셋은 geometry가 전체 용량의 대부분을 차지할 것이다. 아까는 texture의 비중이 훨씬 높았다면, 이번에는 geometry의 비중이 훨씬 높을 것이다. 그렇다. 내가 준비한 3D에셋의 용량은 geometry가 훨씬 많이 차지할수도 있고, texture가 훨씬 더 많이 차지할수도 있다.
다음은 자주쓰는 에셋들의 크기들을 분석한 표이다.
프로젝트의 목적에 따라 결과가 완전히 다르긴 하겠지만, 하나 확실한건 3D에셋의 전체크기에서, texture의 비중이 geometry보다 항상 크지도 않으며, 항상 50%를 넘지도 않는다는 것이다.
🚀파일구조(GLB vs GLTF) vs FBX
사실 이부분도 최적화보다는 기본지식에 가깝다. 나처럼 3D데이터 관련 지식이 부족하다면 한번 고려해보고 들어가면 좋을 것 같다. 프로젝트에서 사용하게 될 파일형식을 제한하게 된다면 다음과 같은 고민이 생길 것이다.
GLB를 사용할까? GLTF를 사용할까? GLB와 GLTF는 어떤 차이가 있을까? 또 3D 데이터를 보면, .fbx, .bvh 등 다양한 포맷이 있는데 어떤걸 사용하면 좋은걸까?
통상 웹에서 3D를 사용하기 위해서는 완성된
3d 모델을 사용할 것이다. 높은확률로 블렌더 등에서 이미 모델링이 완료되었을 것이다. 그렇다면 GLB, 혹은 GLTF를 사용하면 된다. .fbx
형식 등은 모델링을 위해 다양한 데이터(쉐이더, 리깅 등등)를 담고있기 때문이다. 애초에 웹에서 쉽고편하게 사용하기위해 만든게 (webGL을 만들기도 한)khronos
그룹의 GLB
, GLTF
형식인 것이다. 특별한 이유가 없다면 .glb
혹은 .gltf
형식의 데이터로 올리는것이 웹에서 빠르게 처리된다.
그렇다면 GLB
, GLTF
중에서는 어떤것을 사용하면 될까? 두 형식의 차이점을 알아보면 쉽게 생각해볼 수 있다. 결론부터말하자면, GLB
와 GLTF
형식의 차이는 없다. 정말 차이가 존재하지 않는다. 유일한 차이는 GLB
가 조금 더 용량이 적다는 것이다. 그럼 어디서 이런 차이가 오는것이며, 형식의 차이가 없다는건 어떤 뜻일까?
GLB
와 GLTF
는 완전히 동일한 형식이지만, GLTF
를 binary화 시킨것이 GLB
형식인 것이다. GLB
의 어원도 GL
+B
(binary)이다. 완전히 동일한 형식이지만 json내부의 텍스트들을 바이너리 데이터로 바꾼 것이다. GLB는 크게 다음과 같은 두가지 이점이 있다.
1.✅용량감소
바이너리데이터인 GLB를 GLTF로 변환하면 용량이 33%늘어난다. 8bit(통상적인 1byte)가 아닌 6bit를 기준으로 변환하는 base64인코딩을 통해 GLTF로 변환하게 되면, 3글자가 4글자로 변한다. 즉 ABC
라는 데이터는 QUJD
가 되고, 용량은 4/3 즉 133%가 된다. 결과적으로 기존보다 `33%`의 용량증가가 있다. 만약 어떤 3D모델을 주고받는다면, GLB가 아니라 GLTF로 보내게 되면, 전송속도가 33%나 느려지게 되는 것이다. 너무 무거운게 아니라면, 1초가 걸리나, 1.33초가 걸리나.. 사용자는 큰 차이를 못느낄수도 있다. (3D에셋을 직접 어딘가에(AWS S3, 스토리지 등)저장하고 원할때 제공해주는 서비스가 아니라면 굳이?)
2.✅로딩속도
바이너리데이터의 GLB는 GLTF보다 훨씬 더 빠르게 로딩된다. json파싱 및 외부 참조 리소스에 대한 처리를 추가적으로 하지 않아도 되기 떄문이다. 아래 그림과 같이 진행된다.
그렇다. 이미 바이너리화 되어있으므로 gpu에 바로 올리면 되는 것이다. 그 점이 단순 파일크기가 아니라 파일 로딩 관점에서도 훨씬 빠른 속도를 보장해 주는 것이다. 하지만 이도 매우 빠르게 이루어지는 작업들이다.
3.선택
그렇다면 웹상에서 3D 데이터를 조작하고, 빠르게 보여줘야 하는 상황에서는 어떻게 해야 할까? 3D 데이터 정보를 조작하고 변경해야한다? 그렇다면 json형식으로 만들어둔 gltf를 조작하고 보여주는게 더 나은 선택이 될수도 있을 것이다. 단순 특정 3D 에셋을 빠르게 보여줘야한다? 그렇다면 의심의 여지 없이 미리 만들어둔 GLB형식으로만 보여주는게 더 좋은 선택이 될 것이다. 만약 서비스가 미리 저장된 3D에셋을 제공한다면? glb로만 저장하도록 제한하는것도 좋은 선택이 될 수 있을것이다.
모바일/웹용인지, draco압축 등이 적용되어 있는지, 굳이 고해상도일 필요가 없는지, 에셋정보를 조작할거인지(모델링, texture변경 등) 까지 고민을 해나가고 적절한 범위가 결정났다면, 이런 고민이 의미없을수도 있다. 몇MB수준의 3D에셋은 충분히 빠르게 화면에 보여지기 때문이다.
🚀파일구조와 최적화: (GLB vs GLTF)
GLTF 2.0 기준으로 GLB및 GLTF는 다음 세가지 형식을 가질 수 있다. blender에서 파일을 export할 때, 다음과 같은 세가지 옵션이 뜨는것을 볼 수 있다.
GLB
GLTF (seperated)
GLTF (embedded)
그렇다면 위의 세가지 형식이 어떻게 다른지 도식도를 봐보자
그렇다. 위에서 설명한것과 완전히 동일하다. GLTF파일은 다른파일에 속해있는 geometry정보와, texture정보를 참조하고있다. 그리고 이를 하나로 합쳐둔게 GLTF(embedded)이고, 이를 binary압축해둔것이 GLB데이터인 것이다. 따라서 GLTF(seperated)와 GLTF(embedded)는 완전히 용량이 동일하고, GLB는 GLTF의 3/4배에 해당하는 용량을 가지게 된다.
다음글에서는 이 texture를 경량화시켜서 저장한 뒤, 경량화된 정보를 미리 불러오는 방식으로 lazy-loading을 구현한다.
🚀마무리 정리
오늘은 3D에셋데이터
의 간단한 형식과, three.js
에서의 3d에셋 정보들의 형식을 알아보았다. 관련 개발을 해나가다 보면 웹에서 사용자경험을 올리기위해 three.js 최적화를 고려해보았을테고, 위 지식들은 three.js 최적화 의사결정 이전에 당연히 알아야 할 정보이다. 다음글에서는 참조하는 정보만 쏙 바꿔주는 방식으로 최적화를 구현하고, 그 결과물의 차이(사용성증진)을 봐볼 것이다.
해당 부분을 고민할 때, 정보가 별로 없어서 힘들었던 기억이 있다. 추후 나와 비슷한 공부를 하게될 프론트엔드개발자에게 도움이 되길 바란다.
댓글 남기기