다음을 통해 공유


UWP(유니버설 Windows 플랫폼) DirectX 게임의 패키징

대규모 UWP(유니버설 Windows 플랫폼) 게임, 특히 지역별 자산 또는 기능 선택적 고화질 자산이 있는 여러 언어를 지원하는 게임은 벌룬을 팽창할 수 있습니다. 이 토픽에서는 고객이 실제로 필요한 리소스만 받을 수 있도록 앱 패키지 및 앱 번들을 사용하여 앱을 사용자 지정하는 방법을 알아봅니다.

Windows 10은 앱 패키지 모델 외에도 두 가지 유형의 팩을 그룹화할 수 있는 앱 번들을 지원합니다.

  • 앱 팩에는 플랫폼별 실행 파일 및 라이브러리가 포함되어 있습니다. 일반적으로 UWP 게임에는 x86, x64, Arm CPU 아키텍처에 대해 각각 하나씩 최대 3개의 앱 팩이 있을 수 있습니다. 해당 하드웨어 플랫폼과 관련된 모든 코드와 데이터는 앱 팩에 포함되어야 합니다. 또한 앱 팩에는 기본 수준의 충실도 및 성능으로 게임을 실행하기 위한 모든 핵심 자산이 포함되어야 합니다.
  • 리소스 팩에는 게임 자산(텍스처, 메시, 사운드, 텍스트)과 같은 선택적 또는 확장형 플랫폼 중립 데이터가 포함됩니다. UWP 게임에는 고화질 자산 또는 텍스처용 리소스 팩, DirectX 기능 수준 11+ 리소스 또는 언어별 자산 및 리소스를 포함하여 하나 이상의 리소스 팩이 있을 수 있습니다.

앱 번들 및 앱 팩에 대한 자세한 내용은 앱 리소스 정의를 참조하세요.

앱 팩에 모든 콘텐츠를 배치할 수 있지만 비효율적이며 중복됩니다. 각 플랫폼, 특히 사용하지 않을 수도 있는 Arm 플랫폼의 경우 동일한 대형 텍스처 파일이 각 플랫폼에 대해 세 번 복사된 이유는 무엇입니까? 좋은 목표는 고객이 다운로드해야 하는 것을 최소화하여 게임을 더 빨리 시작하고, 장치의 공간을 절약하며, 가능한 요금제 대역폭 비용을 피할 수 있도록 하는 것입니다.

UWP 앱 설치 관리자의 이 기능을 사용하려면 게임 개발 초기에 앱 및 리소스 패키징에 대한 디렉터리 레이아웃 및 파일 명명 규칙을 고려하는 것이 중요합니다. 따라서 도구와 원본이 패키징을 간단하게 만드는 방식으로 올바르게 출력할 수 있습니다. 자산 생성 또는 구성 및 도구 및 스크립트 관리 및 리소스를 로드하거나 참조하는 코드를 작성할 경우 이 문서에 설명된 규칙을 따릅니다.

리소스 팩을 생성하는 이유는 무엇입니까?

앱, 특히 많은 로캘 또는 다양한 UWP 하드웨어 플랫폼에서 판매될 수 있는 게임 앱을 생성할 때 이러한 로캘 또는 플랫폼을 지원하기 위해 여러 버전의 파일을 포함해야 하는 경우가 많습니다. 예를 들어, 미국과 일본 모두에서 게임을 릴리스하는 경우 en-us 로캘의 경우 영어로 한 개의 음성 파일 집합이 필요하고 jp-jp 로캘의 경우 일본어로 한 집합이 필요할 수 있습니다. 또는 Arm 디바이스 및 x86 및 x64 플랫폼용 게임에서 이미지를 사용하려는 경우, 각 CPU 아키텍처에 대해 동일한 이미지 자산을 3번 업로드해야 합니다.

또한 게임에 DirectX 기능 수준이 낮은 플랫폼에 적용되지 않는 고화질 리소스가 많은 경우, 기준 앱 팩에 포함하고 사용자가 디바이스에서 사용할 수 없는 많은 양의 구성 요소를 다운로드하도록 요구하는 이유는 무엇입니까? 이러한 고화질 리소스를 선택적 리소스 팩으로 분리하면 이러한 고화질 리소스를 지원하는 디바이스를 사용하는 고객은 (아마도 계량된) 대역폭의 비용으로 리소스를 얻을 수 있는 반면, 고급 디바이스가 없는 고객은 게임을 더 빠르고 낮은 네트워크 사용 비용으로 얻을 수 있습니다.

게임 리소스 팩의 콘텐츠 후보는 다음과 같습니다.

  • 국제 로캘 특정 자산(지역화된 텍스트, 오디오 또는 이미지)
  • 다양한 디바이스 배율 인수(1.0x, 1.4x, 1.8x)에 대한 고해상도 자산
  • 더 높은 DirectX 기능 수준을 위한 고화질 자산(9, 10, 11)

이 모든 내용은 UWP 프로젝트의 일부인 package.appxmanifest 및 최종 패키지의 디렉터리 구조에 정의됩니다. 새 Visual Studio UI 때문에 이 문서의 프로세스를 따르는 경우, 수동 편집할 필요가 없습니다.

중요 이러한 리소스의 로드 및 관리는 Windows.ApplicationModel.Resources* API를 통해 처리됩니다. 이러한 앱 모델 리소스 API를 사용하여 로캘, 배율 인수 또는 DirectX 기능 수준에 대한 올바른 파일을 로드하는 경우, 명시적 파일 경로를 사용하여 자산을 로드할 필요가 없습니다. 대신 원하는 자산의 일반화된 파일 이름만 리소스 API에 제공하고 리소스 관리 시스템에서 사용자의 현재 플랫폼 및 로캘 구성에 대한 리소스의 올바른 변형을 확보할 수 있도록 합니다(이러한 동일한 API를 사용하여 직접 지정할 수 있습니다).

리소스 패키징에 대한 리소스는 다음 두 가지 기본 방법 중 하나로 지정됩니다.

  • 자산 파일의 파일 이름은 동일하며, 리소스 팩 특정 버전은 명명된 특정 디렉터리에 배치됩니다. 이러한 디렉터리 이름은 시스템에서 예약됩니다. 예를 들면 \en-us, \scale-140, \dxfl-dx11입니다.
  • 자산 파일은 임의의 이름을 가진 폴더에 저장되지만, 파일의 이름은 언어 또는 다른 한정자를 나타내기 위해 시스템에서 예약한 문자열과 함께 추가되는 공통 레이블로 지정됩니다. 구체적으로, 한정자 문자열이 범용 파일 이름과 밑줄(“_”) 뒤에 추가됩니다. 예를 들어 \assets\menu_option1_lang-en-us.png, \assets\menu_option1_scale-140.png, \assets\coolsign_dxfl-dx11.dds입니다. 해당 문자열을 결합할 수도 있습니다. 예를 들어 \assets\menu_option1_scale-140_lang-en-us.png입니다.

    참고 디렉터리 이름에 단독으로 사용되기보다 파일 이름에 사용되는 경우 언어 한정자는 언어, 스케일링, 기타 한정자에 대해 리소스 조정에서 설명한 것처럼 “lang-<태그>”(예: “lang-en-us”)의 형식을 취해야 합니다.

디렉터리 이름은 리소스 패키징의 추가 특이성을 위해 결합할 수 있습니다. 그러나 중복될 수는 없습니다. 예를 들어 \en-us\menu_option1_lang-en-us.png는 중복됩니다.

디렉터리 구조가 각 리소스 디렉터리에서 동일한 경우 리소스 디렉터리에서 필요한 미예약 하위 디렉터리 이름을 지정할 수 있습니다. 예를 들어 \dxfl-dx10\assets\textures\coolsign.dds입니다. 자산을 로드하거나 참조하는 경우, 경로 이름을 일반화하여 폴더 노드 또는 파일 이름에 관계없이 언어, 크기 조정 또는 DirectX 기능 수준에 대한 한정자를 제거해야 합니다. 예를 들어 코드에서 변형 중 하나가 \dxfl-dx10\assets\textures\coolsign.dds인 자산을 참조하려면 \assets\textures\coolsign.dds를 사용합니다. 마찬가지로, 변형이 \images\background_scale-140.png인 자산을 참조하려면 \images\background.png를 사용합니다.

다음과 같은 예약 디렉터리 이름 및 파일 이름 밑줄 접두사입니다.

자산 형식 리소스 팩 디렉터리 이름 리소스 팩 파일 이름 접미사
지역화된 자산 Windows 10의 경우 가능한 모든 언어 또는 언어와 로캘 조합입니다. (폴더 이름에는 한정자 접두사 'lang-'이 필요하지 않습니다.) “_” 뒤에 언어, 로캘 또는 언어-로캘 지정자가 추가됩니다. 예를 들어 각각 “_en”, “_us” 또는 “_en-us”입니다.
인수 자산 확장 scale-100, scale-140, scale-180. 각각 1.0x, 1.4x, 1.8x UI 배율 인수에 해당합니다. “_” 뒤에 “scale-100”, “scale-140” 또는 “scale-180”이 추가됩니다.
DirectX 기능 수준 자산 dxfl-dx9, dxfl-dx10, dxfl-dx11. DirectX 9, 10, 11 기능 수준에 각각 적용됩니다. “_” 뒤에 “dxfl-dx9”, “dxfl-dx10” 또는 “dxfl-dx11”이 추가됩니다.

 

지역화된 언어 리소스 팩 정의

로캘 관련 파일은 언어의 이름을 딴 프로젝트 디렉터리에 배치됩니다(예: 'en').

여러 언어에 대해 지역화된 자산을 지원하도록 앱을 구성하는 경우, 다음을 수행해야 합니다.

  • 지원할 각 언어 및 로캘에 대한 앱 하위 디렉터리(또는 파일 버전)를 생성합니다(예: en-us, jp-jp, zh-cn, fr-fr 등).

  • 개발 중 언어 또는 로캘 간에 다르지 않더라도 모든 자산(예: 지역화된 오디오 파일, 질감 및 메뉴 그래픽)의 복사본을 해당 언어 로캘 하위 디렉터리에 배치합니다. 최상의 사용자 환경을 위해 로캘에 사용할 수 있는 언어 리소스 팩을 가져오지 않은 경우(또는 다운로드 및 설치 후 실수로 삭제한 경우) 사용자에게 경고를 표시합니다.

  • 각 자산 또는 문자열 리소스 파일(.resw)의 이름이 각 디렉터리에 동일한지 확인합니다. 예를 들어 파일의 콘텐츠가 서로 다른 언어인 경우 menu_option1.png와 동일한 이름이 \en-us 및 \jp-jp 디렉터리에 둘 다 있어야 합니다. 이 경우 \en-us\menu_option1.png 및 \jp-jp\menu_option1.png로 표시됩니다.

    참고 선택적으로 파일 이름에 로캘을 추가하여 동일한 디렉터리에 저장할 수 있습니다(예: \assets\menu_option1_lang-en-us.png, \assets\menu_option1_lang-jp-jp.png).

     

  • Windows.ApplicationModel.ResourcesWindows.ApplicationModel.Resources.Core의 API를 사용하여 앱에 대한 로캘별 리소스를 지정하고 로드합니다. 또한 이러한 API는 사용자의 설정에 따라 올바른 로캘을 결정한 다음 사용자의 올바른 리소스를 검색하므로 특정 로캘을 포함하지 않는 자산 참조를 사용합니다.

  • Microsoft Visual Studio 2015에서 프로젝트->스토어->앱 패키지 만들기...를 선택하고 패키지를 만듭니다.

배율 인수 리소스 팩 정의

Windows 10은 1.0x, 1.4x, 1.8x의 세 가지 사용자 인터페이스 배율 인수를 제공합니다. 각 디스플레이의 크기 조정 값은 화면 크기, 화면 해상도, 화면에서 사용자의 가정된 평균 거리 등 여러 가지 결합된 요인에 따라 설치 중에 설정됩니다. 사용자는 확장 요소를 조정하여 가독성을 향상시킬 수도 있습니다. 최상의 환경을 위해 게임이 DPI 인식 및 배율 인수 인식이어야 합니다. 이러한 인식의 일부는 세 가지 크기 조정 요소 각각에 대한 중요한 시각적 자산 버전을 생성하는 것을 의미합니다. 여기에는 포인터 상호 작용 및 적중 테스트도 포함됩니다.

다양한 UWP 앱 크기 조정 요인에 대한 리소스 팩을 지원하도록 앱을 구성할 경우 다음을 수행해야 합니다.

  • 지원할 각 크기 조정 요소(scale-100, scale-140, scale-180)에 대한 앱 하위 디렉터리(또는 파일 버전)를 생성합니다.

  • 개발하는 동안 배율 인수 간에 다르지 않더라도 각 배율 인수 리소스 디렉터리에 모든 자산의 배율 인수에 적합한 복사본을 배치합니다.

  • 각 자산의 이름이 각 디렉터리에서 같은지 확인합니다. 예를 들어 파일의 콘텐츠가 서로 다른 경우 menu_option1.png와 동일한 이름이 \scale-100 및 \scale-180 디렉터리에 둘 다 있어야 합니다. 이 경우 \scale-100\menu_option1.png 및 \scale-140\menu_option1.png로 표시됩니다.

    참고 다시, 선택적으로 파일 이름에 스케일링 인수 접미사를 추가하여 동일한 디렉터리에 저장할 수 있습니다(예: \assets\menu_option1_scale-100.png, \assets\menu_option1_scale-140.png).

     

  • Windows.ApplicationModel.Resources.Core의 API를 사용하여 자산을 로드합니다. 자산 참조는 일반화되어야 하며(접미사 없음), 특정 배율 변형을 제외해야 합니다. 시스템은 디스플레이 및 사용자 설정에 적절한 크기 조정 자산을 검색합니다.

  • Visual Studio 2015에서 프로젝트->스토어->앱 패키지 만들기...를 선택하고 패키지를 만듭니다.

DirectX 기능 수준 리소스 팩 정의

DirectX 기능 수준은 이전 및 현재 버전의 DirectX(특히 Direct3D)의 GPU 기능 집합에 해당합니다. 여기에는 셰이더 모델 사양 및 기능, 셰이더 언어 지원, 질감 압축 지원, 전반적인 그래픽 파이프라인 기능이 포함됩니다.

기준 앱 팩은 BC1, BC2 또는 BC3의 기준 텍스처 압축 형식을 사용해야 합니다. 이러한 형식은 저가형 Arm 플랫폼에서 전용 다중 GPU 워크스테이션 및 미디어 컴퓨터에 이르기까지 모든 UWP 디바이스에서 사용할 수 있습니다.

DirectX 기능 수준 10 이상의 텍스처 형식 지원을 리소스 팩에 추가하여 로컬 디스크 공간을 절약하고 대역폭을 다운로드해야 합니다. 이를 통해 BC6H 및 BC7 등 11에 대한 고급 압축 체계를 사용할 수 있습니다. (자세한 내용은 Direct3D 11의 텍스처 블록 압축을 참조하세요.) 이러한 포맷은 최신 GPU에서 지원하는 고해상도 텍스처 에셋에 더 효율적이며, 이를 사용하면 고사양 플랫폼에서 게임의 모양, 성능, 공간 요구 사항이 향상됩니다.

DirectX 기능 수준 지원되는 텍스처 압축
9 BC1, BC2, BC3
10 BC4, BC5
11 BC6H, BC7

 

또한 DirectX 기능 수준들은 각각 서로 다른 셰이더 모델 버전을 지원합니다. 컴파일된 셰이더 리소스는 기능 수준별로 생성할 수 있으며 DirectX 기능 수준 리소스 팩에 포함될 수 있습니다. 또한 이후 버전의 일부 셰이더 모델은 이전 셰이더 모델 버전에서 사용할 수 없는 일반 맵과 같은 자산을 사용할 수 있습니다. 이러한 셰이더 모델 관련 자산은 DirectX 기능 수준 리소스 팩에도 포함되어야 합니다.

리소스 메커니즘은 주로 자산에 지원되는 텍스처 형식에 중점을 두므로 3개의 전체 기능 수준만 지원합니다. DX9_1 및 DX9_3과 같은 하위 수준(도트 버전)용 셰이더가 별도로 필요한 경우 자산 관리 및 렌더링 코드에서 명시적으로 처리해야 합니다.

다양한 DirectX 기능 수준에 대한 리소스 팩을 지원하도록 앱을 구성하는 경우 다음을 수행해야 합니다.

  • 지원할 각 DirectX 기능 수준(dxfl-dx9, dxfl-dx10, dxfl-dx11)에 대한 앱 하위 디렉터리(또는 파일 버전)를 생성합니다.

  • 개발하는 동안 각 기능 수준 리소스 디렉터리에 기능 수준 특정 자산을 배치합니다. 로캘 및 배율 인수와 달리 게임의 각 기능 수준에 다른 렌더링 코드 분기가 있을 수 있습니다. 또한, 지원되는 모든 기능 수준의 하나 또는 하위 집합에서만 사용되는 텍스처, 컴파일된 셰이더 또는 기타 자산이 있는 경우, 해당 자산을 사용하는 기능 수준의 디렉터리에만 배치합니다. 모든 기능 수준에서 로드되는 자산은 각 기능 수준 리소스 디렉터리에 동일한 이름의 버전이 있는지 확인합니다. 예를 들어 기능 수준에 독립적인 “coolsign.dds”라는 텍스처의 경우 BC3 압축 버전을 \dxfl-dx9 디렉터리에 저장하고 BC7 압축 버전을 \dxfl-dx11 디렉터리에 저장합니다.

  • 각 자산(여러 기능 수준에서 사용할 수 있는 경우)의 이름이 각 디렉터리에서 동일한지 확인합니다. 예를 들어 파일의 콘텐츠가 서로 다른 경우 coolsign.dds와 동일한 이름이 \dxfl-dx9 및 \dxfl-dx11 디렉터리에 둘 다 있어야 합니다. 이 경우 \dxfl-dx9\coolsign.dds 및 \dxfl-dx11\coolsign.dds로 표시됩니다.

    참고 다시, 선택적으로 파일 이름에 기능 수준 접미사를 추가하여 동일한 디렉터리에 저장할 수 있습니다(예: \textures\coolsign_dxfl-dx9.dds, \textures\coolsign_dxfl-dx11.dds).

     

  • 그래픽 리소스를 구성할 경우 지원되는 DirectX 기능 수준을 선언합니다.

    D3D_FEATURE_LEVEL featureLevels[] = 
    {
      D3D_FEATURE_LEVEL_11_1,
      D3D_FEATURE_LEVEL_11_0,
      D3D_FEATURE_LEVEL_10_1,
      D3D_FEATURE_LEVEL_10_0,
      D3D_FEATURE_LEVEL_9_3,
      D3D_FEATURE_LEVEL_9_1
    };
    
    ComPtr<ID3D11Device> device;
    ComPtr<ID3D11DeviceContext> context;
    D3D11CreateDevice(
        nullptr,                    // Use the default adapter.
        D3D_DRIVER_TYPE_HARDWARE,
        0,                      // Use 0 unless it is a software device.
        creationFlags,          // defined above
        featureLevels,          // What the app will support.
        ARRAYSIZE(featureLevels),
        D3D11_SDK_VERSION,      // This should always be D3D11_SDK_VERSION.
        &device,                    // created device
        &m_featureLevel,            // The feature level of the device.
        &context                    // The corresponding immediate context.
    );
    
  • Windows.ApplicationModel.Resources.Core의 API를 사용하여 리소스를 로드합니다. 자산 참조는 기능 수준을 벗어나 일반화해야 합니다(접미사 없음). 그러나 언어 및 규모와 달리 시스템은 지정된 디스플레이에 가장 적합한 기능 수준을 자동으로 결정하지는 않습니다. 이는 코드 논리를 기반으로 결정하는 데 남아 있는 것입니다. 결정되면 API를 사용하여 OS에 기본 설정 기능 수준을 알릴 수 있습니다. 그러면 시스템은 해당 기본 설정에 따라 올바른 자산을 검색할 수 있습니다. 다음은 플랫폼에 대한 현재 DirectX 기능 수준을 앱에 알리는 방법을 보여 주는 코드 샘플입니다.

    // Set the current UI thread's MRT ResourceContext's DXFeatureLevel with the right DXFL. 
    
    Platform::String^ dxFeatureLevel;
        switch (m_featureLevel)
        {
        case D3D_FEATURE_LEVEL_9_1:
        case D3D_FEATURE_LEVEL_9_2:
        case D3D_FEATURE_LEVEL_9_3:
            dxFeatureLevel = L"DX9";
            break;
        case D3D_FEATURE_LEVEL_10_0:
        case D3D_FEATURE_LEVEL_10_1:
            dxFeatureLevel = L"DX10";
            break;
        default:
            dxFeatureLevel = L"DX11";
        }
    
        ResourceContext::SetGlobalQualifierValue(L"DXFeatureLevel", dxFeatureLevel);
    

참고 항목

코드에서 이름별로(또는 기능 수준 디렉터리의 경로) 직접 텍스처를 로드합니다. 기능 수준 디렉터리 이름 또는 접미사를 포함하지 마세요. 예를 들면 “dxfl-dx11\textures\coolsign.dds” 또는 “textures\coolsign_dxfl-dx11.dds”가 아니라 “textures\coolsign.dds”를 로드합니다.

  • 이제 ResourceManager를 사용하여 현재 DirectX 기능 수준과 일치하는 파일을 찾습니다. ResourceManagerResourceMap(또는 ResourceMap::TryGetValue)와 제공된 ResourceContext를 사용하여 쿼리하는 ResourceMap::GetValue을 반환합니다. ResourceCandidate를 호출하여 지정한 DirectX 기능 수준과 가장 밀접하게 일치하는 SetGlobalQualifierValue를 반환합니다.

    // An explicit ResourceContext is needed to match the DirectX feature level for the display on which the current view is presented.
    
    auto resourceContext = ResourceContext::GetForCurrentView();
    auto mainResourceMap = ResourceManager::Current->MainResourceMap;
    
    // For this code example, loader is a custom ref class used to load resources.
    // You can use the BasicLoader class from any of the 8.1 DirectX samples similarly.
    
    
    auto possibleResource = mainResourceMap->GetValue(
        L"Files/BumpPixelShader.cso",
        resourceContext
    );
    Platform::String^ resourceName = possibleResource->ValueAsString;
    
  • Visual Studio 2015에서 프로젝트->스토어->앱 패키지 만들기...를 선택하고 패키지를 만듭니다.

  • package.appxmanifest 매니페스트 설정에서 앱 번들을 사용 설정해야 합니다.