ユニバーサル Windows プラットフォーム (UWP) DirectX ゲームをパッケージ化する

大規模なユニバーサル Windows プラットフォーム (UWP) ゲーム(特に、リージョン固有のアセットを持つ複数の言語をサポートするゲーム、またはオプションの高解像度アセットを備えたゲーム)は、大きなサイズに簡単に吹き出すことができます。 このトピックでは、アプリ パッケージとアプリ バンドルを使用して、顧客が実際に必要なリソースのみを受け取るようにアプリをカスタマイズする方法について説明します。

Windows 10 では、アプリ パッケージ モデルに加えて、次の 2 種類のパックをグループ化するアプリ バンドルがサポートされています。

  • アプリ パックには、プラットフォーム固有の実行可能ファイルとライブラリが含まれています。 通常、UWP ゲームには、x86、x64、Arm CPU アーキテクチャ用にそれぞれ 1 つずつ、最大 3 つのアプリ パックを含めることができます。 そのハードウェア プラットフォームに固有のすべてのコードとデータをアプリ パックに含める必要があります。 また、アプリ パックには、忠実性とパフォーマンスのベースライン レベルでゲームを実行するためのコア アセットもすべて含まれている必要があります。
  • リソース パックには、オプションまたは拡張されたプラットフォームに依存しないデータ (ゲーム アセット (テクスチャ、メッシュ、サウンド、テキスト) など) が含まれています。 UWP ゲームには、高解像度アセットまたはテクスチャ用のリソース パック、DirectX 機能レベル 11 以上のリソース、言語固有のアセットとリソースなど、1 つ以上のリソース パックを含めることができます。

アプリ バンドルとアプリ パックの詳細については、「アプリ リソースの定義を参照してください。

すべてのコンテンツをアプリ パックに配置できますが、これは非効率的で冗長です。 同じ大きなテクスチャ ファイルがプラットフォームごとに 3 回レプリケートされているのはなぜですか。特に、それを使用しない可能性がある Arm プラットフォームでは、 良い目標は、顧客がダウンロードする必要のあるものを最小限に抑え、ゲームのプレイを早く開始し、デバイスの領域を節約し、測定帯域幅のコストを回避できるようにすることです。

UWP アプリ インストーラーのこの機能を使用するには、ゲーム開発の早い段階でアプリとリソースのパッケージ化のディレクトリ レイアウトとファイルの名前付け規則を検討することが重要です。これにより、ツールとソースがパッケージ化を簡単にする方法で正しく出力できるようになります。 資産の作成と管理のツールとスクリプトを開発または構成するとき、およびリソースを読み込んだり参照したりするコードを作成する場合は、このドキュメントに記載されている規則に従ってください。

リソース パックを作成する理由

アプリ 、特に多くのロケールで販売できるゲーム アプリ、またはさまざまな UWP ハードウェア プラットフォームを作成する場合は、多くの場合、それらのロケールまたはプラットフォームをサポートするために、複数のバージョンの多くのファイルを含める必要があります。 たとえば、米国と日本の両方でゲームをリリースする場合は、en-us ロケール用に英語の音声ファイルのセットと、jp-jp ロケール用の日本語の 1 つのセットが必要になる場合があります。 または、Arm デバイスと x86 および x64 プラットフォームのゲームでイメージを使用する場合は、CPU アーキテクチャごとに同じイメージアセットを 3 回アップロードする必要があります。

さらに、DirectX 機能レベルが低いプラットフォームに適用されない高解像度リソースがゲームに多数ある場合、それらをベースライン アプリ パックに含め、デバイスで使用できない大量のコンポーネントをユーザーにダウンロードするようユーザーに要求するのはなぜですか? これらのハイデフ リソースをオプションのリソース パックに分離すると、高遅延リソースをサポートするデバイスをお持ちのお客様は、(場合によっては従量制課金の) 帯域幅で取得できますが、ハイエンド デバイスを持たないユーザーは、ゲームをより迅速かつ低いネットワーク使用コストで取得できます。

ゲーム リソース パックのコンテンツ候補は次のとおりです。

  • 国際ロケール固有のアセット (ローカライズされたテキスト、オーディオ、または画像)
  • さまざまなデバイス スケーリング 要因 (1.0 倍、1.4 倍、1.8 倍) の高解像度アセット
  • より高い DirectX 機能レベル (9、10、11) の高解像度アセット

このすべては、UWP プロジェクトの一部である package.appxmanifest と、最終的なパッケージのディレクトリ構造で定義されます。 新しい Visual Studio UI のため、このドキュメントの手順に従う場合は、手動で編集する必要はありません。

重要: これらのリソースの読み込みと管理は、Windows.ApplicationModel.Resources\* API によって処理されます。 これらのアプリ モデル リソース API を使用してロケール、スケーリング ファクター、または DirectX 機能レベルの正しいファイルを読み込む場合、明示的なファイル パスを使用して資産を読み込む必要はありません。代わりに、必要な資産の一般化されたファイル名のみをリソース API に提供し、リソース管理システムがユーザーの現在のプラットフォームとロケール構成のリソースの正しいバリアントを取得できるようにします (これらの同じ API で直接指定することもできます)。

リソース パッケージのリソースは、次の 2 つの基本的な方法のいずれかで指定されます。

  • 資産ファイルは同じファイル名を持ち、リソース パック固有のバージョンは特定の名前付きディレクトリに配置されます。 これらのディレクトリ名はシステムによって予約されています。 たとえば、\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-<tag>" (たとえば "lang-en-us") という形式にする必要があります。

ディレクトリ名を組み合わせて、リソース パッケージの特定性を高めることができます。 ただし、冗長にすることはできません。 たとえば、\en-us\menu_option1_lang-en-us.png は冗長です。

各リソース ディレクトリでディレクトリ構造が同じである限り、リソース ディレクトリの下に必要な予約されていないサブディレクトリ名を指定できます。 たとえば、\dxfl-dx10\assets\textures\coolsign.dds とします。 アセットを読み込むか参照するときは、パス名を一般化し、言語、スケール、または DirectX 機能レベルの修飾子を削除する必要があります。これらはフォルダー ノード内にある場合でも、ファイル名内にある場合でも削除されます。 たとえば、バリアントの 1 つが \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.0 倍、1.4 倍、および 1.8 倍の 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.Resources および Windows.ApplicationModel.Resources.Core の API を使用して、アプリのロケール固有のリソースを指定して読み込みます。 また、これらの API はユーザーの設定に基づいて正しいロケールを決定し、ユーザーの適切なリソースを取得するため、特定のロケールを含まない資産参照を使用します。

  • Microsoft Visual Studio 2015 では、[プロジェクト]->[ストア]->[アプリ パッケージの作成] の順に選択して、パッケージを作成します。

スケーリング ファクター リソース パックの定義

Windows 10 には、1.0x、1.4x、1.8x の 3 つのユーザー インターフェイススケーリング要素が用意されています。 各ディスプレイのスケーリング値は、画面のサイズ、画面の解像度、画面からのユーザーの想定される平均距離など、さまざまな要素に基づいてインストール時に設定されます。 ユーザーは、読みやすさを向上させるためにスケール ファクターを調整することもできます。 ゲームは、可能な限り最高のエクスペリエンスを実現するために、DPI 対応とスケール ファクター対応の両方にする必要があります。 この認識の一部は、3 つのスケール ファクターごとに重要なビジュアルアセットのバージョンを作成することを意味します。 これには、ポインターの相互作用とヒット テストも含まれます。

さまざまな 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) ごとにアプリ サブディレクトリ (またはファイル バージョン) を作成します。

  • 開発中は、各機能レベルのリソース ディレクトリに機能レベル固有の資産を配置します。 ロケールやスケーリング要因とは異なり、ゲーム内の機能レベルごとに異なるレンダリング コード ブランチが存在する場合があり、テクスチャ、コンパイル済みシェーダー、またはサポートされているすべての機能レベルの 1 つまたは一部でのみ使用されるその他のアセットがある場合は、対応するアセットを、それらを使用する機能レベルのディレクトリにのみ配置します。 すべての機能レベルにわたって読み込まれる資産の場合は、各機能レベルのリソース ディレクトリに同じ名前のバージョンがあることを確認します。 たとえば、機能レベルに依存しない "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);
    

Note

コードで、名前 (または機能レベル ディレクトリの下のパス) でテクスチャを直接読み込みます。 機能レベルのディレクトリ名またはサフィックスは含めないでください。 たとえば、"dxfl-dx11\textures\coolsign.dds" や "textures\coolsign_dxfl-dx11.dds" ではなく、"textures\coolsign.dds" を読み込みます。

  • 次に、 ResourceManager を使用して、現在の DirectX 機能レベルに一致するファイルを見つけます。 ResourceManager は、ResourceMap::GetValue (または ResourceMap::TryGetValue) と指定された ResourceContext を使用してクエリを実行するを返します。 これにより、 ResourceCandidate SetGlobalQualifierValue を呼び出すことによって指定された DirectX 機能レベルに最も近い値が返されます。

    // 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 マニフェスト設定でアプリ バンドルを有効にしていることを確認します。