336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
Posted by ozlael
,
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

버텍스 트랜스폼 (Vertex Transform)


버텍스 데이터들은 GPU 메모리에 저장되어 있습니다.렌더링을 수행해야하는 시점이 되면 GPU는 메모리로부터 버텍스 정보들을 가져옵니다. 그리고 적절한 위치에 그려주기 위해서 위치 변환 즉 트랜스폼(transform)을 수행해주게 됩니다. (명사형으로 트랜스포메이션(Transformation)이라고 표현하기도 합니다.)


저장되어 있는 버텍스 데이터는 특정 위치가 반영된 데이터가 아닌 메시 형태만 반영되있는 데이터입니다. 하나의 메시가 여러 오브젝트 즉 인스턴스에서 사용되고 인스턴스마다 위치가 다릅니다. 또한 매번 위치가 바뀌기 때문에 원본 메시 데이터에 3D 공간상의 위치를 반영해놓을 수는 없고, 3D 공간의 특정 위치가 반영되지 않는 원점 기준의 메시 모델에 대한 위치 데이터만 가지고 있는 것입니다. 이러한 데이터를 로컬 스페이스(local space)에 존재한다고 표현합니다.





이를 3D 공간상의 특정 위치에 위치시켜줘야 합니다. 만일 오브젝트의 인스펙터에서 트랜스폼 컴포넌트의 position이 -4.5,0.7,3 으로 설정되어 있고 rotation y가 55으로 되어있다면 메시 데이터를 -4.5,0.7,3으로 위치시켜주고 y축으로 55도 회전시켜줘야합니다.

이러한 식으로 월드 스페이스(world space) 혹은 월드 좌표계(world coordinates)로 변환시켜주는 것을 월드 트랜스폼(world transform)이라고 표현합니다.

이 월드 트랜스폼 시에는 메시의 모든 버텍스의 위치와 노멀(Normal)(경우에 따라서 탄젠트(Tangent) 및 바이노멀(Binormal) 데이터 포함)을 월드 트랜스폼 시켜줍니다. 즉, 모든 버텍스의 위치와 노멀 정보가 로컬 스페이스에서 월드 스페이스로 변환되는 과정이 월드 트랜스폼인 것입니다.




월드 스페이스로 변환을 해준 뒤에는 카메라 스페이스(Camera Space)로 또 변환을 해줘야 합니다. 월드 트랜스폼을 거쳐서 모든 오브젝트의 버텍스들이 원래 있어야 할 위치로 위치하게 되었지만 , 이 오브젝트들은 카메라를 통해서 디스플레이가 됩니다. 카메라는 원점(x:0,y:0,z:0)에만 있는 것이 아니고 카메라 역시 고유의 위치와 방향을 가지고 있습니다. 그렇기 때문에 오브젝트의 버텍스들을 카메라에 상대적인 위치로 변환을 해줘야 합니다. 이러한 공간을 카메라 스페이스(Camera Space) 또는 뷰 스페이스(view space)라고 부르고, 뷰 스페이스로 변환하는 과정을 뷰 트랜스폼(view transform)이라고 합니다.




오브젝트들은 3차원 공간에 있지만 최종적으로 오브젝트가 렌더링되어 디스플레이 되는 공간은 2차원입니다. 3D 공간을 2D상의 위치로 매칭시켜주는 과정을 프로젝션(투영,projection)이라고 합니다. (빔프로젝터에서 빛을 쏘아서 스크린에 투영시키는 모습을 연상하면 됩니다.)


이러한 프로젝션 트랜스폼 과정에서는 원근법도 적용이 됩니다. 사람이 세상을 볼 때 멀리 있는 것은 작게 보이고 가까이 있는 것은 크게 보입니다. 또한 거리가 멀어질 수록 많은 사물들이 시야에 들어오게 됩니다. 카메라를 통해서 볼때도 이 역시 마찬가지며 유니티 카메라에서는 뷰 영역을 나타내는 프라미드 볼륨을 확인할 수 있습니다. 이를 뷰 프러스텀(view frustum)이라고 합니다.


이러한 투영을 퍼스펙티브 프로젝션(원근 투영, perspective projection)이라고 부릅니다.

cam_pers.png


또한, 원근법이 적용 된 퍼스펙티브 프로젝션 외에도 원근법이 제거 된 오쏘그래픽 프로젝션(orthographic projection, 직교 투영)도 존재합니다. 카메라와의 거리와는 무관하게 시각적으로 크기의 변화가 없이 보여집니다.

cam_ortho.png


카메라 투영에 관한 설정은 다음 비디오에서 자세하게 확인할 수 있습니다 : https://youtu.be/52g_3CX7avo?t=4m2s



유니티의 쉐이더를 작성할 시 UNITY_MATRIX_MVP 변수는 이러한 변환을 의미합니다. UnityShaderVariables.cginc 파일에 기술되어 있습니다.


더 많은 내용은 "유니티 그래픽스 최적화 스타트업"을 참고하세요








Posted by ozlael
,
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


ASTC(Adaptive Scalable Texture Compression)


ASTC(Adaptive Scalable Texture Compression)는 ARM에서 개발하고 2012년에 크로노스 그룹에서 OpenGL ES에 표준으로 지정되었습니다. ASTC는 PVRTC나 ETC와 마찬가지로 손실 블록 기반 텍스처 압축 알고리즘입니다.


ASTC는 용량과 품질에 대한 트레이드오프(Trade-off)가 가능합니다. ETC나 PVRTC는 bpp가 한정되어 있는 반면,  ASTC는 8bpp에서 0.86bpp까지 품질을 향상시킬 수 있습니다. 이러한 조절이 가능한 것은 가변 블록 크기를 사용하기 때문입니다. ETC와 PVRTC는 압축되는 블럭의 크기가 4x4로 고정되어 있습니다. 반면, ASTC는 압축되는 기준 블럭의 크기를 4x4에서 12x12 블럭으로 다양하게 선택을 할 수 있습니다. ASTC는 블럭 당 128비트를 사용합니다. 128비트를 4x4블럭에 할당하면 128/16=8bpp가 되는 것이고, 12x12 블럭에 할당하면 128/144=약0.89bpp가 되는 것입니다.

아래 이미지는 좌측으로부터 각각 8bpp, 3.56bpp, 2bpp의 결과를 보여주고 있습니다.

<이미지 출처 : 위키피디아 >


유니티에서도 텍스쳐 압축 포맷을 ASTC로 선택할 수 있고, 4x4에서 12x12까지 블록 크기를 선택할 수 있습니다.


텍스처의 중요도나 복잡도에 따라서 블럭의 크기를 개별적으로 선택할 수 있습니다. 예를 들어거 캐릭터의  텍스쳐같은 경우는 4x4를 선택하고,


파티클같이 이미지가 많이 뭉개져도 상관 없는 경우는 12x12를 선택함으로써 용량을 절약할 수 있습니다.


ASTC는 ETC보다 더 복잡한 인코딩 과정을 거칩니다. 그러다보니 압축 시간이 조금 더 걸리지만 결과적으로는 ETC보다는 ASTC가 일반적인 품질이 좋습니다.

< 이미지 출처 : developer.arm.com>


ASTC는 안드로이드폰과 iOS폰 모두에서 지원하기 때문에 같은 텍스처 압축 포맷을 사용함으로써  퀄리티와 용량에 대한 유지 보수를 한결 더 수월하게 할 수 있습니다.


물론, 문제는 지원 기기의 범위입니다.


안드로이드의 경우는 OpenGL 3.2 이상 혹은 OpenGL ES 3.1 + AEP(Android Extension Pack)이 지원되어야합니다. 삼성 갤럭시 S6 혹은 LG G5 이상의 기기들이 이에 해당합니다. 안드로이드의 경우에는 기종이 정말 다양하게 존재하기 때문에 반드시 주 타겟 기기에서 지원 여부를 직접 테스트해보아야합니다.


iOS는 A8 processor를 사용하기 시작하는 기종부터 사용이 가능합니다. iPhone 6, iPad mini 4가 이에 해당합니다.


따라서, 그 이하의 구형 기종도 지원해야하는 게임이라면 ASTC를 사용하기가 애매할 수도 있습니다. 하지만, 그렇지 않은 경우에는 ASTC를 사용하는 것이 품질과 용량을 모두 절약할 수 있는 좋은 방법이 될 수도 있습니다. 그러한 이유로 최근에 출시하는 많은 3D 게임에서 ASTC를 사용하기 시작하고 있습니다.


관련 참고 링크 :

https://developer.nvidia.com/astc-texture-compression-for-game-assets



더 많은 내용은 "유니티 그래픽스 최적화 스타트업"을 참고하세요

Posted by ozlael
,
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


SRP(Scriptable render pipeline)

유니티 2018부터 스크립터블 렌더 파이프라인(Scriptable render pipeline, 이하 SRP)이라는 기능을 제공합니다. SRP는 유니티의 렌더링 처리 방식을 C# 스크립트로 제어할 수 있는 기능입니다. 이를 통해서 라이팅 처리 방식을 포함한 전반적인 렌더링 루프를 직접 구성할 수 있습니다. 그렇게 함으로써 기존에 유니티에서 고정해놓은 방식대로만 렌더링하는 것이 아니라, 직접 렌더링 루프를 커스터마이징함으로써 원하는 방식으로 렌더링을 구성할 수 있습니다. 예를 들어서, 새로운 렌더링 기술을 직접 적용할 수도 있고, 특정 하드웨어에 맞게 최적화를 할 수도 있습니다.

유니티의 로우 레벨 렌더링 파트는 유니티가 C++로 구현해놓았습니다. 그리고, 이러한 기능들을 C# 스크립트로 사용하고 제어할 수 있도록 되어 있습니다. 유니티를 사용하는 개발자는 C# 스크립트로 자신만의 렌더 루프를 만들 수 있습니다. 하지만, SRP로 렌더 파이프라인을 직접 구성한다는 것은 많은 지식이 요구되고 많은 작업이 필요합니다. 대신, 유니티는 유니티에서는 SRP를 이용하여 HDRP(HD Render Pipeline)와 LWRP(Lightweight Render Pipeline)을 만들어두어 제공하고 있습니다. SRP로 직접 렌더 파이프라인을 구성하지 않고 HDRP나 LWRP를 이용하여 프로젝트를 진행할 수 있습니다.


HDRP(High Definition render pipeline)

HDRP는 하이엔드 PC나 콘솔등을 고려해서 고품질의 비주얼을 구현하는데 적합한 파이프라인입니다. 유니티의 빌트인에 구현되어있는 디퍼드나 포워드보다 발전되고 개선된 렌더링 기법이 적용되어있습니다. (주석 : Clustered tiled lighting, Fine pruned tiled lighting) 또한, Anisotropy, Subsurface 등 더 많은 재질 표현이 가능합니다.

하지만, HDRP는 기본적으로 요구되는 하드웨어 스펙들이 존재하기 때문에 성능이 낮은 플랫폼에서는 작동하지 않습니다. 즉, 모바일 게임 개발용으로는 적합하지가 않습니다.


LWRP(Lightweight Render Pipeline)

대신, 모바일을 위해서 LWRP라는 파이프라인이 제공됩니다. LWRP는 퍼포먼스에 최적화되어 있고, 모바일이나 VR이나 AR처럼 성능에 민감한 환경에서 높은 성능을 보여줍니다.

LWRP는 기존 파이프라인에 비하여 성능을 위한 특징들이 존재합니다. 이를 통해서 라이팅과 쉐이딩 관련하여 단점들을 해결하여 성능 제약이있는 플랫폼에서 최적화 된 실시간 렌더링 퍼포먼스를 제공합니다.


Multi light Single pass

그 중 가장 큰 특징은 실시간 라이팅들이 싱글패스로 처리된다는 점입니다. 앞서 설명하였듯이 포워드 렌더링에서는 실시간 라이트를 여러개를 처리하기 위해서는 그만큼 덧그리게 됨으로써 드로우콜이 늘어납니다. (주석:이를 멀티 라이트 멀티 패스(Multi light Multi pass)라고 표현됩니다.)

LWRP는 유니티에 기본으로 구현된 포워드 렌더링과는 달리, 여러개의 실시간 라이트를 한번의 패스로 처리하도록 만들어져 있습니다. (주석 : 즉, 멀티 라이트 싱글 패스(Multi light Single pass)입니다. ) 오브젝트를 렌더링 할 때 오브젝트에 영향받는 실시간 라이트들을 쉐이더에 전달해줍니다. 쉐이더에서는 한번에 여러 라이트들을 모두 처리해줌으로써 별도의 드로우콜이 발생하는 것을 방지합니다. 이러한 과정을 통해서 기존의 포워드 렌더링과 비교하여 드로우콜이 줄어들게 설계되어있습니다.


관련 참고 자료 링크 : 


더 많은 내용은 "유니티 그래픽스 최적화 스타트업"을 참고하세요

Posted by ozlael
,
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

텍스쳐의 Read/Write Enabled


텍스쳐의 임포트 셋팅 중 Read/Write Enabled 플래그도 메모리에 영향을 미칩니다. 이 플래그가 활성화되어 있다면 텍스쳐 데이터가 CPU 메모리에 상주하게 됩니다. 원래 텍스처 데이터는 GPU에서 사용할 수 있도록 GPU 메모리에 상주합니다. 하지만, 이 플래그가 활성화가 되면 추가적으로 CPU 메모리에도 상주하게 됨으로써 메모리 사용량이 두 배가 되는 것입니다.

이 플래그는 유저 스크립트에서 Texture.GetPixel 혹은 Texture.SetPixel 등의 코드를 통해 텍스쳐의 읽기 및 쓰기가 가능한지의 여부를 의미합니다. 만일 런타임이나 로딩타임동안 스크립트에서 텍스쳐의 데이터에 접근할 필요가 있다면 이 플래그가 활성화되어야 합니다.

하지만, 대부분의 경우에는 렌더링에 사용되는 텍스처가 스크립트에서 변경될 일이 없으므로 이 플래그를 비활성화 시켜야 메모리를 절약할 수 있습니다. 때문에, 기본적으로는 비활성화되어되어있습니다.


더 많은 내용은 "유니티 그래픽스 최적화 스타트업"을 참고하세요


Posted by ozlael
,