많은분들이 물어보시는 내용 중 하나가 텍스쳐입니다. 그 중 밉맵과 필터링에 대한 내용을 정리해보고자합니다.



밉맵


텍스쳐에서 밉맵이란 텍스쳐에게 있어서 LOD같은 개념입니다. 만일 256x256짜리 텍스쳐가 화면에 그려진다고 생각을 해보죠. 이 텍스쳐가 화면에 굉장히 작은 영역으로 그려져서 실제로는 32x32픽셀만큼의 영역만 그려지는 상황이라면 굳이 256텍스쳐를 바를 필요가 없습니다. 괜히 대역폭을 낭비할 필요 없이 32텍스쳐를 가져가면 충분한 상황일 것입니다.

이런 컨셉이 바로 텍스쳐 밉맵입니다. 텍스쳐 하나 만들면 내부적으로는 여러 크기 단계의 텍스쳐를 만들어 두는 것입니다. 예를 들어서 256텍스쳐를 사용하면 내부적으로는 256,128,64,32,16,8,4,2크기의 텍스쳐를 추가적으로 생성하게 되는 것입니다. 그러고서는 런타임에서 렌더링 시 픽셀쉐이더에서 텍스쳐를 읽어들일 때 상황에 맞는 크기의 텍스쳐를 가져감으로써 실시간 대역폭을 절약하는 것입니다.

이미지 출처 : http://www.tomshardware.com/reviews/ati,819-2.html


이런식으로 하면 런타임 성능은 절약되지만 메모리는 약 30%가 늘어나게 됩니다.(정확한 수치는 아니고 통상적인 수치입니다) 따라서 메모리가 걱정된다면 밉맵을 끌 수도 있습니다. 유니티에서는 기본적으로 텍스쳐가 밉맵을 사용하도록 설정됩니다. 밉맵을 끄려면 텍스쳐별로 밉맵을 사용 안하도록 설정해줘야합니다. 텍스쳐 타입을 Advanced로 두고 Generate Mip Maps를 해제하면 됩니다. 


하지만 3D 게임에서는 특수한 상황이 아니고서는 밉맵을 끄는 것을 권장하지는 않습니다. 성능 문제도 있거니와 지글거림이 발생하여서 시각적인 문제도 발생합니다. ( 반대로 2D 게임에서는 뭉개져보이는 시각적인 문제로 밉맵을 꺼주는 것이 좋을 수도 있습니다.)

이미지 출처 : http://www.tomshardware.com/reviews/ati,819-2.html



필터링


밉맵을 이야기하면 필터링도 함께 이야기 하게될 수 밖에 없습니다. 텍스쳐 필터링은 텍스쳐 설정의 filter mode에서 변경할 수 있습니다.

  • 포인트(Point) : 필터링을 하지 않습니다. 따라서 픽셀이 블럭으로 깨져보이게 됩니다.

  • 바이리니어(Bilinear) : 텍스쳐가 필터링 됩니다. 확대필터와 축소필터 모두 적용 됩니다. 즉 원래 텍스쳐보다 확대되서 그려지든 작게 그려지든 필터링이 되는 것입니다. 

  • 트라이리니어(Trilinear) : 바이리니어가 기본적으로 작동하고, 추가적으로 밉맵 레벨이 바뀌는 구간도 필터링이 됩니다.

바이리니어와 트라이니리어간의 차이점은 밉맵 레벨이 바뀌는 구간이 필터링 되냐 아니냐의 차이입니다. 트라이리니어로 설정하면 밉맵 레벨이 바뀌는 구간도 부드러워집니다. 따라서, 바닥같은데서 시각적으로 자연스러운 렌더링이 되려면 트라이리니어를 사용해야합니다.

이미지 출처 : http://www.tomshardware.com/reviews/ati,819-4.html

또한, Anisotropic filtering을 적용하면 더욱 좋은 품질을 얻을 수 있습니다. Anisotropic은 면의 기울기를 필터링에 반영하기때문에 바닥이나 벽 등에 사용하면 좋습니다. 텍스쳐 인트펙터에서 Aniso Level을 2 이상으로 설정하면 필터링이 적용됩니다. 숫자가 높을수록 필터링이 강하게 작용하고 성능도 그만큼 필요로하게됩니다.

이미지 출처 : http://www.gamespot.com/forums/system-wars-314159282/df-issue-with-blurry-console-texture-filtering-32700608/


다만 이들은 디바이스마다 지원 여부가 다릅니다. 특히, anisotropic 필터링은 많은 기기들에서 사용이 불가능합니다. 유니티를 실행 시 로그캣으로 확인해보면 다음과 같이 기기에서 지원하는 GL 익스텐션 목록들이 출력됩니다.

ex > GL_EXT_debug_marker GL_ARM_rgba8 GL_ARM_mali_shader_binary GL_OES_depth24 GL_OES_depth_texture GL_OES_depth_texture_cube_map GL_OES_packed_depth_stencil GL_OES_rgb8_rgba8 GL_EXT_read_format_bgra GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture ...

이 목록 중 "GL_EXT_texture_filter_anisotropic" 항목이 없으면 해당 기기에서 anisotropic 필터링을 지원하지 않는 것입니다.

다만, 텍스쳐 임포트 셋팅에서 aniso level을 설정해놓아도 기기에서 지원하지 않으면 작동하지 않으므로 비정상 작동하거나 하지는 않습니다. 설정을 굳이 1로 돌려놓지 않으셔도 무방합니다. 트라이리니어 역시 마찬가지로 기기에서 지원하지 않는다면 바이리니어로 작동하므로 트라이리니어로 두셔도 비정상 작동하거나 하지는 않습니다.


밉맵 바이어스


낮은 밉맵 단계가 흐려보이는 것이 거슬린다면 낮은 밉맵 단계가 적용되는 기준을 조절해줄 수도 있습니다. 물론 성능 문제상 추천되는 방법은 아닙니다만 밉맵 바이어스를 건드리면 밉맵 레벨이 바뀌는 기준을 바꿔주실 수도 있습니다. 다만, OpenGLES에서는 작동하지 않습니다.

http://docs.unity3d.com/ScriptReference/Texture-mipMapBias.html

따라서 이 기능과 같은 결과를 만들어내시려면 쉐이더에서 건드려주시면 됩니다. tex2D함수 대신 tex2Dbias를 사용하시면 됩니다. 자세한 내용은 대마왕님의 블로그를 참고하세요 :

http://chulin28ho.tistory.com/258

다만 이 역시 기기에서 지원을 해줘야합니다. GL익스텐션 목록에 EXT_shader_texture_lod가 있다면 지원 되는 것입니다.




신고
  1. 지나가는사람 2016.04.30 00:39 신고

    글 퍼가도 될까요? 링크는 남기겠습니다.

유니티의 UI 관련하여 빈번하게 문의들어오는 것 중 하나가 UI와 3D 오브젝트들의 위치 관계에 관한 것입니다. 

일반적인 UI는 게임 씬 위에 덧그려지는 방식으로 만들어집니다. 기본적으로 유니티에서 UI 컴포넌트를 생성하면 3D 오브젝트들을 렌더링 후 UI를 렌더링 하게 됩니다. 기본적으로 이러한 방식으로 UI가 화면에 덧그려지게 되지요.

하지만 인게임 말고 로비나 생성창 등에서 UI 위에 파티클을 그린다거나 UI와 UI 사이에 케릭터를 그리는 등의 상황도 필요합니다. 이러한 구성은 어떻게 하는지 문의가 자주 들어오곤 합니다. 

구성 방법이야 여러가지가 있을 수 있겠지만, 우선은 캔버스의 렌더 모드를 스크린스페이스-카메라로 사용해주면 됩니다. 기본으로 캔버스를 생성하면 렌더 모드가 스크린스페이스-오버레이인데, 이는 씬 렌더 후 화면에 덮어서 그리는 UI를 의미합니다. 스크린스페이스-카메라는 캔버스의 깊이를 설정할 수 있어서 3D 오브젝트와의 깊이 관계를 설정할 수가 있습니다. 따라서, 위 화면과 같이 케릭터 배경 창이 있고 케릭터 위에 버튼을 그리고자 하는 경우라면, 깊이가 다른 각각의 두 캔버스를 스크린스페이스-카메라 렌더모드로 만들고, 각각의 캔버스의 평면 거리(plane distance)를 적절한 깊이로 설정한 다음, 사이에 3d 오브젝트를 배치하면 다중 UI 깊이에 대해서 렌더링을 할 수 있습니다.

샘플 프로젝트를 올려두었으니 이를 참고해보시면 도움 되실 것이라 생각합니다 : https://drive.google.com/a/unity3d.com/file/d/0B70AOyGiQJsGT3dDRW9uUldOeTg/view?usp=sharing



신고
  1. ss 2016.01.20 19:28 신고

    UI 배경 위에 3D 오브젝트 띄우고, 그 위에 UI 버튼이 있고, 버튼을 누를 때 3D 파티클 이펙트가 나오고, 그 위에 HUD UI가 있고 HUD UI를 누를 때 3D 파티클 이펙트를 출력하는데 중간에 렌더 텍스쳐를 사용 -> 7 카메라 이상

제 개인적인 생각으로는 물리기반렌더링(Physically Based Rendering/Shading, 이하 PBR,PBS)이 2016년 국내 게임 시장의 중요 키워드 중 하나가 아닐까 생각합니다.  모바일 기기의 성능들이 많이 발전하고 특히 국내에는 고사양 폰의 보급률이 높아짐에 따라 모바일에서도 PBR을 사용하는 움직임들이 많이 보이고 있습니다. 유니티에서는 스탠다드(Standard) 쉐이더를 통해서 PBR을 처리해주고 있습니다. 이 스탠다드 쉐이더는 유니티5에 적용된 인라이튼(Enlighten)과 연동하여 실시간 GI(Global Illumination) 및 물리 기반 라이팅을 표현해줌으로써 더욱 사실적이고 멋진 그래픽을 표현할 수 있도록 해줍니다. 

하지만 PBS는 복잡한 연산을 거쳐서 빛을 표현해주어야 하다보니 성능을 크게 잡아먹습니다. 물론 게임에서는 이를 나름 간략화 시켜서 사용하고, 유니티 역시 스탠다드 쉐이더에 이를 최적화하여 적용합니다. 또한, PC에서 수행하면 PC용 모드의 스탠다드 쉐이더로 수행되고 모바일 기기에서 수행하면 모바일용으로 더 최적화된 모드의 스탠다드 쉐이더로 수행됩니다. 이 역시 버전을 거듭할 수록 계속 최적화가 진행중입니다. 하지만, 기본적으로 연산 자체가 복잡하기 때문에 씬 전체를 스탠다드 쉐이더로 사용하는 것은 아이폰5, 아이패드에어, 넥서스9 급 이상의 하이엔드 기기를 타겟으로 사용하는 경우에만 권장합니다.

고사양 기기가 많이 보급되어 있긴 하지만 아직도 저사양 폰들이 시장에 많이 존재합니다. 이러한 기기들에서는 씬 전체를 스탠다드 쉐이더로 그리는 것은 무리입니다. 하지만, 스탠다드 쉐이더를 부분적으로만 사용한다면 충분히 보급형 기기에서도 이를 활용 할 수도 있습니다. 예를 들어, 케릭터에게만 스탠다드 쉐이더를 사용하고 배경에는 다른 가벼운 쉐이더를 사용하는 것입니다. 다음 이미지에서는 그러한 예시를 보여주고 있습니다. 로보트들과 드론들에게는 스탠다드 쉐이더를 사용하였고 배경에는 Mobile/Unlit (Supports Lightmap) 쉐이더를 사용하였습니다. 갤럭시 S3에서 60 이상의 FPS로 렌더링 되고 있습니다. 데모를 구글플레이에 올려두었습니다. 다운로드 받아서 확인 가능하십니다. 

링크 : https://play.google.com/store/apps/details?id=com.ozproject.demo2

사용 에셋 : Armored Golem, Sci-fi Flying Droid, Mech Robot Sci-fi, Orbital Reentry Craft - No Interior ( 제가 아트감각이라고는 빵점인 공돌이라 비쥬얼 퀄리티가 좋지 못한 점 너른 양해 부탁드립니다;; )

또한, 저사양 기기에서 스탠다드 쉐이더를 사용하기 위해서는 텍스쳐 슬롯을 가능한 아껴주는 것이 좋습니다. 사용되지 않는 텍스쳐 슬롯은 스탠다스 쉐이더가 알아서 연산을 건너뜀으로써 성능을 절약하 수 있습니다.

예를 들어 다음 우주선은 Emission 맵을 사용하지 않았습니다.

드론에게는 노말맵을 사용하지 않았습니다.

골렘 로보트에게는 Metallic맵을 사용하지 않고 수치로써 단순하게 적용하였습니다.


이러한 식으로 스탠다드 쉐이더를 선택적으로 사용하고 파라미터를 절약한다면 저사양 기기에서도 충분히 스탠다드 쉐이더를 통한 PBR을 사용할 수 있습니다. 감사합니다.


신고

+ Recent posts

티스토리 툴바