XNA ContentPipelineを使用して、完全なXNA GSのないマシンでファイルをエクスポートする


9

私のゲームは、実行時にコンテンツパイプラインを使用してスプライトシートをロードします。ゲームのアーティストから変更されたスプライトシートが送られてきました。マシンでビルドを行い、更新されたプロジェクトを彼に送ります。そのため、彼が完全なXNA Game Studioをインストールしなくても、彼のマシンでxnbファイルを生成する方法(これはコンテンツパイプラインの出力です)を探しています。

1)私のアーティストにVS + Xnaをインストールしてほしくない(VSの無料バージョンがあることは知っているが、チームに人を追加するとこれは拡張されない)。2)Xboxでこのエディター/ツールを実行することに興味がないので、Windowsのみのソリューションが機能します。3)MSBuildオプションは知っていますが、完全なXNAが必要です

私はShawnのブログを調査したところ、Msbuild Sampleを使用するオプション、またはXNA 4.0の新しいオプションを使用するオプションを見つけましたが、ここでは有望に見えますが、同じ制限があるようです:ContentPipelineはXNA redistの一部ではないため、完全なXNA GSをインストールする必要があります。

だから誰かがこれの回避策を見つけましたか?

回答:


11

これに対する正しい答えは、ContentPipelineをスキップし、Texture2D.FromStreamを使用して実行時にテクスチャをロードすることです。この方法はPCで正常に機能し、パフォーマンスが少し低下しても、リリース日に近づいたら最適化できます。現時点では、エディターとゲームの両方のコンテンツを動的に変更する機能が必要です。コンテンツがフリーズしたら、ContentPipelineに戻ってこれを最適化できます。

このルートを選択したので、次のTexture2D.FromStream2つの理由で実際に使用するほど簡単ではないことを警告します。

問題#1-乗算済みアルファサポートの欠如

XNA4は、デフォルトであらかじめ乗算されたアルファ形式の色を持つテクスチャーを処理するようになりました。コンテンツパイプラインを通じてテクスチャをロードすると、その処理は自動的に行われます。残念ながらTexture2D.FromStream、同じことは行わないため、ある程度の透明度を必要とするテクスチャは、ロードされて正しくレンダリングされません。以下は、問題を説明するスクリーンショットです。

ここに画像の説明を入力してください

したがって、正しい結果を得るには、自分で処理を行う必要があります。これから紹介する方法では、GPUを使用して処理を行うため、かなり高速です。この素晴らしい記事に基づいています。もちろんSpriteBatch、古いNonPremultiplyAlphaモードでレンダリングするように指示することもできますが、実際にそれを行うことはお勧めしません。

問題#2-サポートされていない形式

コンテンツパイプラインは、よりも多くの形式をサポートしていますTexture2D.FromStream。特に、Texture2D.FromStreampng、jpg、gifのみをサポートしています。一方、コンテンツパイプラインはbmp、dds、dib、hdr、jpg、pfm、png、ppm、tgaをサポートしています。あなたはを通してusuported形式をロードしようとした場合Texture2D.FromStream、あなたは買ってあげるInvalidOperationExceptionわずかな追加情報を。

エンジンでbmpサポートが本当に必要だったので、その特定のケースでは、問題なく動作するように見える回避策を見つけました。他のフォーマットについては知りません。私の方法の難点は、System.Drawingアセンブリへの参照をプロジェクトに追加する必要があることです。Image.FromStreamこれは、よりも多くの形式をサポートするGDIを使用するためですTexture2D.FromStream

bmpのサポートを気にしない場合は、ソリューションのその部分を簡単に削除して、乗算済みアルファ処理を実行できます。

ソリューション-シンプルバージョン(遅い)

まず、bmpのサポートを気にしない場合の最も簡単な解決策を次に示します。この例では、処理段階はすべてCPUで行われます。以下に示す代替案よりも少し遅いですが(両方のソリューションのベンチマークを行いました)、理解しやすくなっています。

public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream)
{
    Texture2D texture = Texture2D.FromStream(graphicsDevice, stream);
    Color[] data = new Color[texture.Width * texture.Height];
    texture.GetData(data);
    for (int i = 0; i != data.Length; ++i)
        data[i] = Color.FromNonPremultiplied(data[i].ToVector4());
    texture.SetData(data);
    return texture;
}

bmpに関心がある場合は、最初にGDIを使用して画像を読み込み、次に内部的にPNGに変換してからに渡しTexture2D.FromStreamます。これを行うコードは次のとおりです。

// Load image using GDI because Texture2D.FromStream doesn't support BMP
using (Image image = Image.FromStream(stream))
{
    // Now create a MemoryStream which will be passed to Texture2D after converting to PNG internally
    using (MemoryStream ms = new MemoryStream())
    {
        image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        ms.Seek(0, SeekOrigin.Begin);
        texture = Texture2D.FromStream(_graphicsDevice, ms);
    }
}

ソリューション-複雑なバージョン(高速)

最後に、私のプロジェクトで使用するアプローチは、代わりにGPUを使用して処理を行うことです。このメソッドでは、レンダーターゲットを作成し、いくつかのブレンドステートを適切に設定し、SpriteBatchでイメージを2回描画する必要があります。最後に、RenderTarget2Dは揮発性であり、バックバッファーサイズの変更などの影響を受けないので、RenderTarget2D全体を調べて、コンテンツを別のTexture2Dオブジェクトに複製します。コピーを作成する方が安全です。

面白いことに、これらすべてを使用しても、私のテストでは、このアプローチはCPUアプローチよりも約3倍高速でした。そのため、各ピクセルを調べて色を自分で計算するよりも断然高速です。コードは少し長いので、私はそれをペーストビンに入れました:

http://pastie.org/3651642

そのクラスをプロジェクトに追加し、次のように簡単に使用します。

TextureLoader textureLoader = new TextureLoader(GraphicsDevice);
Texture2D texture = textureLoader.FromFile("Content/texture.png");

注:TextureLoaderゲーム全体に対して1つのインスタンスを作成するだけで済みます。また、私はBMP修正を使用していますが、必要がなく、一連のパフォーマンスを得るか、needsBmpパラメーターをfalseのままにしておく場合は、それを削除できます。


わあ、これはすごい!それは私をとても助けてくれます:)デービッドに感謝します、感謝します。
krolth

+1実際にはFromStream、他の例と同じように、32ビットのビットマップ(pngに保存)を含むメモリストリームを使用していましたが、この方法では、あらかじめ乗算されたテクスチャは作成されませんでした。おかげで、各色を明示的に事前乗算することでうまくいきました。
Groo、2015

3

ほとんどのチームはxnbの変更(実際にはすべての変更、xnbを含む)をsvnサーバー(無料で設定できます)にコミットし、他の人(アーティストなど)が自分の作業コピーを更新できるようにすると思います。

実際、これはアーティストが元の(pre xnb)アートをバージョン管理するための優れたメカニズムです。彼はそれに変更をコミットし、あなたはそれの作業コピーを更新し、それをビルドし(プロセス内でxnbにします)、変更をコミットし、彼はあなたの作業の作業コピーを更新し、そして誰もがすべての変更を持っています。(あなたは最新の生のアートワークを持っています、彼はxnb(s)を持っています。

これも非常によくスケーリングします。


あなたはそれができるとは思わないと言っているのですか?あなたの提案は、XNBとスプライトにバージョン管理を追加することです。すでにそれを行っています。しかし、私は彼らのボトルネックになるので、私はそれが好きではありません。私はすでに彼らがアニメーションを編集するためのツールを書いており、彼らはゲームでそれらを試すことができます。しかし、スプライトシートに変更を加えた場合、表示される前に私が作成するまで待つ必要があります。あなたが想像するように、彼らが間違いを犯した場合、彼らはもう一度それを行う必要があります。
krolth 2012年

@krolthプロジェクトで作業するためのセットアップの一環として、アーティストにVS ExpressとXNAを入手させるのはそれほど大きなことですか?この時点で、アーティストが自分の作品をエンジンで見ることができないため、ガイドを作成してそれを通して人々を助ける必要があるというトレードオフは、現在失っている生産性をはるかに上回ると思います。プロセスを合理化するには、ダブルクリックしてIDEを開かなくてもすべてを再コンパイルできる.BATファイルを提供します。そしてもし彼らがOS Xだけを走らせているなら、まあ、大変なことだ。ゲーム開発者へようこそ。彼らはスプライトをコミットし、次にコミットされたXNBを待つことができます。
michael.bartnett 2012年

それはそれほど大したことではなく、ただの痛みです。しかし、私はそれがしなければならないだろうと思います。あなたの答え/コメントをみんなに感謝します!
krolth 2012年

1

私はこれを調査し続け、同じ質問を持つ誰かのためにこれを投稿します。

これに対する正しい答えはContentPipelineをスキップして使用することがあるように思えるTexture2D.FromStreamを実行時にテクスチャをロードします。この方法はPCで正常に機能し、パフォーマンス少し低下しても、リリース日に近づいたら最適化できます。

現時点では、エディターとゲームの両方のコンテンツを動的に変更する機能が必要です。コンテンツがフリーズしたら、ContentPipelineに戻ってこれを最適化できます。


これを正しくテストしましたか?私の経験Texture2D.FromStreamだけでは十分ではありません。その理由は、バージョン4のXNAが事前に乗算されたアルファテクスチャで動作し、コンテンツパイプラインがこの処理を自動的に処理する一方で、Texture2D.FromStream透明性のあるスプライトを描画するときに問題が発生しないためです。よろしければ、実用的なソリューションを投稿できます。
David Gouveia

また、コンテンツパイプラインが行うファイルのTexture2D.FromStream読み込みはサポートしていません.BMP。これは、.BMP以前にアセットを使用してからに切り替えた場合、おそらくあなたを失いますTexture2D.FromStream。その制限に対する回避策もあります。先に進んで投稿します。
David Gouveia

0

このプロジェクトをチェックしてください

これにより、アーティストは、デフォルトのXNAコンテンツパイプラインがサポートするほぼすべてのものからXNBを作成できます。アーティストにはVisual Studioは必要ありませんが、XNAフレームワークの再頒布可能パッケージは引き続き必要です。


ポインタをありがとう。コードを見ると、私が参照したMicrosoftサンプルへの変更のように見えます。XNA Game Studioが完全にインストールされているかどうかに依存します(ContentBuilder.csを参照)。なぜそうではないと思いますか?
krolth 2012年

そうではないと思います。コンテンツパイプラインを使用する場合は、完全なゲームスタジオが必要です。ただし、このプロジェクトでは、アーティストがVisual Studioを使用する必要がなくなります。他の唯一の代替手段は、コンテンツパイプラインを書き換えることです。
ClassicThunder 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.