안 보이는 픽셀을 몇 번 칠하고 있나
Esc

    안 보이는 픽셀을 몇 번 칠하고 있나

    –Unity최적화렌더링

    드로우 콜도 줄였고 SetPass Call 도 낮습니다. 라이트도 정리했습니다. 그런데 저사양 기기에서 여전히 느립니다.

    같은 픽셀을 여러 번 칠하고 있어서 그럴 수 있습니다.

    오버드로우

    배경 (풀스크린) 타일맵 안개 오버레이 (풀스크린) 캐릭터와 이펙트 UI 딤 (풀스크린) 1회 2회 3회 4회 5회 이 픽셀 하나를 한 프레임에 다섯 번 칠합니다 1080p 화면 전체가 이렇다면 초당 6억 픽셀이 넘습니다 불투명이면 깊이 테스트가 뒤를 걸러 주지만, 반투명은 뒤를 봐야 색이 섞이므로 전부 칠합니다.
    드로우 콜은 다섯 개뿐입니다. 그런데 GPU 가 하는 일은 다섯 배입니다.

    3D 에서는 앞에 있는 불투명 오브젝트가 뒤를 가려 주면 뒤쪽 픽셀을 안 칠합니다. 깊이 테스트가 걸러 주기 때문입니다.

    2D 는 그게 잘 안 됩니다. 스프라이트는 대개 반투명으로 그려지고, 반투명은 뒤에 있는 색과 섞여야 하니까 뒤쪽도 반드시 칠해야 합니다. 그래서 겹친 층 수가 그대로 곱해집니다.

    얼마나 되는지

    층 수가 그대로 배수 입니다. 여기가 요점입니다. 스프라이트를 아무리 아틀라스로 합치고 드로우 콜을 줄여도 이 곱셈은 안 줄어듭니다. 칠하는 픽셀 수는 CPU 가 명령을 몇 번 보내느냐와 무관합니다.

    어떻게 보나

    Scene View 의 Draw Mode 를 Overdraw 로 바꾸면 겹친 만큼 밝아지는 화면이 나옵니다. 새하얗게 뜨는 자리가 범인입니다. 에디터에서 바로 되고 설정도 필요 없습니다.

    숫자로 재려면 모바일 GPU 프로파일러가 필요합니다. Android 는 Android GPU Inspector 나 Arm Performance Studio, iOS 는 Xcode 의 GPU 프레임 캡처입니다. Unity 프로파일러의 GPU 항목은 에디터에서 0 으로 나오는 경우가 많아서 실기 빌드에 붙여야 의미가 있습니다.

    줄이는 방법

    하나. 풀스크린 반투명을 센다. 화면 전체를 덮는 반투명 한 장은 그 자체로 오버드로우 1회입니다. 안개, 비네트, 딤, 색보정 오버레이가 각각 한 장씩입니다. 넷이 겹쳐 있으면 배경을 안 그려도 이미 4겹입니다. 셋 이상 쌓이면 셰이더 하나로 합치는 것을 봅니다.

    둘. 스프라이트 메시를 타이트하게. 스프라이트 임포터의 Mesh Type 을 Tight 로 두면 사각형이 아니라 알파를 따라 잘라 낸 다각형으로 그립니다. 투명한 여백을 안 칠하게 됩니다. 나뭇가지나 이펙트처럼 알파 여백이 큰 스프라이트에서 효과가 큽니다. 대신 정점이 늘어서 다이나믹 배칭 쪽에는 불리합니다. GPU 가 병목이면 Tight, CPU 가 병목이면 Full Rect 입니다.

    셋. 안 보이는 것을 끈다. 카메라 밖의 레이어, 메뉴 뒤에 가려진 게임 화면, 꺼야 하는데 알파만 0으로 둔 오브젝트. 알파 0 은 그리기를 건너뛰지 않습니다. 여전히 칠합니다. 정말 안 보여야 하면 SetActive(false) 나 렌더러를 끄는 쪽입니다.

    넷. Render Scale 을 낮춘다. 칠할 픽셀 수 자체를 줄이는 가장 직접적인 방법입니다. 0.8 로만 낮춰도 픽셀 수가 36퍼센트 줄어듭니다. 2D 는 선이 뭉개지면 티가 나므로 픽셀 아트라면 조심해야 하지만, 그림체가 부드러운 게임이면 저사양 기기에서 쓸 만한 카드입니다.

    이건 CPU 문제가 아니다

    정리하면 오버드로우는 앞의 글들과 축이 다릅니다.

    배칭, 아틀라스 오버드로우
    무엇이 비싼가 CPU 가 명령을 만드는 시간 GPU 가 픽셀을 칠하는 시간
    무엇에 비례하나 상태 변경 횟수 픽셀 수 × 겹친 층 수
    해상도를 낮추면 안 변합니다 그만큼 줄어듭니다

    그래서 진단 순서가 중요합니다. 해상도를 반으로 낮췄을 때 프레임이 확 좋아지면 GPU 문제 이고, 그대로면 CPU 문제입니다. 이 실험 하나로 어디를 봐야 할지가 정해집니다.