해상도를 낮춘다는 게 정확히 무엇을 낮추는 것인가
Esc

    해상도를 낮춘다는 게 정확히 무엇을 낮추는 것인가

    –Unity최적화렌더링

    GPU 가 무거울 때 나오는 처방에 Render Scale 이 계속 등장합니다. 오버드로우를 줄일 때도, 2D 라이트가 무거울 때도 목록에 들어 있습니다.

    그런데 이게 정확히 무엇을 낮추는지는 잘 안 나옵니다. 화면 해상도를 낮추는 건지, 텍스처를 낮추는 건지, UI 글자도 같이 뭉개지는지.

    낮추는 것은 캔버스의 크기다

    URP 에셋의 Quality 항목에 있습니다. 유니티 문서의 설명이 이렇습니다.

    이 슬라이더는 렌더 타겟의 해상도를 조절합니다. 지금 기기의 해상도가 아닙니다.

    기기 화면은 그대로 1920×1080 입니다. 바뀌는 것은 게임을 그려 넣는 중간 텍스처의 크기입니다. 0.5 로 두면 960×540 짜리 텍스처에 게임을 그리고, 그걸 1920×1080 으로 늘려서 화면에 붙입니다.

    960×540여기에 그린다렌더 타겟늘린다1920×1080화면그 위에UI 는 1920×1080 그대로
    기기 해상도는 안 건드립니다. 그리는 자리만 작아집니다.

    그래서 화질이 깎이는 것은 게임 화면뿐입니다. 창 크기도, 기기 설정도 그대로입니다.

    0.8 이 왜 36퍼센트인가

    가로만 0.8 이 되는 게 아니라 가로세로가 같이 0.8 이 됩니다. 칠해야 할 픽셀은 넓이라서 스케일의 제곱으로 줍니다.

    Render Scale 픽셀 수 줄어든 양
    0.9 81% 19%
    0.8 64% 36%
    0.7 49% 51%
    0.5 25% 75%

    0.8 은 눈으로 잘 구분이 안 가는데 픽셀은 3분의 1 넘게 줄어듭니다. 저사양 기기에서 값이 싼 이유가 이 비대칭입니다.

    UI 는 안 따라 내려간다

    이게 제일 자주 놓치는 부분입니다. 문서에 이렇게 적혀 있습니다.

    게임 렌더링만 스케일합니다. UI 렌더링은 기기의 원래 해상도로 남습니다.

    0.6 으로 낮춰도 체력 숫자나 대사 텍스트는 또렷합니다. 게임 화면만 살짝 뭉개지고 읽어야 할 것은 안 뭉개집니다. Render Scale 이 모바일에서 실용적인 카드인 이유가 여기 있습니다.

    다만 이건 Screen Space Overlay 캔버스 이야기입니다. Screen Space Camera 나 World Space 캔버스는 카메라를 통해 그려지므로 같이 내려갑니다. UI 가 뭉개진다면 캔버스 모드부터 확인하면 됩니다.

    1.0 위로도 갈 수 있다

    0 에서 1 사이의 값이라고 생각하기 쉬운데 아닙니다. 인스펙터 슬라이더는 0.1 부터 2.0 까지입니다. 문서도 “성능을 위해 더 작게 그리거나, 화질을 위해 업스케일하는 데 쓰라” 고 적어 뒀습니다.

    1.0 보다 크게 두면 화면보다 크게 그린 뒤 줄여서 붙입니다. 계단이 부드러워집니다. 안티에일리어싱을 힘으로 하는 셈입니다. 1.5 면 픽셀이 2.25배가 되므로 비용도 그만큼 냅니다. 고사양 기기 옵션이나 스크린샷용으로 쓰는 자리입니다.

    늘릴 때 무엇으로 채우나

    작게 그린 것을 늘리면 중간 픽셀을 만들어 내야 합니다. 그 방법이 Upscaling Filter 입니다.

    옵션 무엇 언제
    Automatic 스케일 값과 화면 해상도를 보고 유니티가 고름 기본값
    Bilinear 이웃 픽셀을 섞어서 부드럽게 그림체가 부드러운 게임
    Nearest-Neighbor 가장 가까운 픽셀을 그대로 복사 픽셀 아트
    FidelityFX Super Resolution 1.0 선명함을 살려서 늘림 낮은 스케일에서 화질이 아까울 때
    Spatial-Temporal Post-Processing 1.0 이전 프레임 정보까지 써서 늘림 최신 옵션

    픽셀 아트에서 Bilinear 로 늘리면 선이 흐물거립니다. 도트가 살아야 하는 게임이면 Nearest-Neighbor 로 두거나, 애초에 Render Scale 을 안 건드리는 편이 낫습니다.

    FSR 과 STP 는 다른 필터와 성격이 하나 다릅니다. Render Scale 이 1.0 이어도 계속 동작합니다. 늘리는 도구가 아니라 화질을 손보는 도구에 가깝습니다.

    무엇이 안 줄어드나

    Render Scale 이 줄이는 것은 칠할 픽셀 수 하나뿐입니다.

    • 드로우 콜과 SetPass Call 은 그대로입니다
    • 스크립트, 물리, 애니메이션도 그대로입니다
    • 텍스처 메모리도 그대로입니다. 화면에 그리는 크기만 달라진 것이지 텍스처가 작아진 게 아닙니다

    그래서 진단 도구로 쓸 수 있습니다. Render Scale 을 0.5 로 내려 보고 프레임이 확 좋아지면 GPU 가 픽셀을 칠하는 데서 막힌 것입니다. 그대로면 CPU 쪽이라 배칭이나 스크립트를 봐야 합니다. 고치기 전에 어디를 볼지 정해 주는 실험이라, 값이 싼 것치고 얻는 게 큽니다.

    라이트만 따로 낮추기

    2D 라이팅을 쓰면 스케일 지점이 하나 더 있습니다. 2D Renderer Data 의 Light Blend Style 마다 Render Texture Scale 이 붙어 있습니다.

    해당 Blend Style 을 위해 만드는 내부 렌더 텍스처의 크기를 조절합니다.

    화면 전체는 1.0 으로 두고 라이트 버퍼만 저해상도로 그리는 것입니다. 빛은 원래 부드럽게 번지는 것이라 절반으로 줄여도 잘 티가 안 납니다. 문서도 큰 라이트가 많은 씬에서 성능과 메모리를 같이 아낀다고 적어 뒀습니다.

    대신 너무 낮추면 대가가 있습니다. 문서의 경고가 이렇습니다.

    너무 낮게 두면 시각적 결함이 생기거나, 화면에 움직임이 있을 때 어른거림이 나타날 수 있습니다.

    정지 화면에서 확인하고 통과시키면 안 되는 자리입니다. 캐릭터를 움직여 보면서 봐야 합니다.

    런타임에 바꾸기

    기기 등급에 따라 다르게 주고 싶으면 코드로 바꿉니다.

    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    var asset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
    if (asset != null)
        asset.renderScale = 0.8f;

    매 프레임 만지면 안 됩니다. 값이 바뀌면 렌더 타겟을 다시 잡아야 해서 그 순간이 걸립니다. 프레임이 떨어진다고 실시간으로 스케일을 밀고 당기는 동적 해상도를 직접 만들면, 줄이려던 스파이크를 스케일 변경이 대신 만들어 냅니다.

    기기 등급을 보고 시작할 때 한 번, 또는 옵션 화면에서 사용자가 바꿀 때 한 번이면 충분합니다.

    정리

    • Render Scale 은 기기 해상도가 아니라 게임을 그려 넣는 렌더 타겟의 크기입니다
    • 가로세로가 같이 줄어서 픽셀 수는 제곱으로 줍니다. 0.8 이 36퍼센트입니다
    • UI 는 기기 해상도 그대로 남습니다. 읽어야 할 것은 안 뭉개집니다. 단 Screen Space Camera 와 World Space 캔버스는 예외입니다
    • 0 에서 1 사이가 아닙니다. 0.1 에서 2.0 이고, 1.0 위는 화질을 사는 쪽입니다
    • 늘리는 방법은 Upscaling Filter 가 정합니다. 픽셀 아트는 Nearest-Neighbor 입니다
    • 줄어드는 것은 칠할 픽셀 수뿐입니다. 드로우 콜도 스크립트도 텍스처 메모리도 그대로입니다
    • 그래서 CPU 병목인지 GPU 병목인지를 가르는 실험으로 쓸 수 있습니다
    • 2D 라이팅은 Light Blend Style 의 Render Texture Scale 로 라이트 버퍼만 따로 낮출 수 있습니다. 너무 낮추면 움직일 때 어른거립니다
    • 런타임에 바꿀 수 있지만 바꾸는 순간 렌더 타겟을 다시 잡습니다. 시작할 때 한 번이면 됩니다