XNAスプライトフラッシュ効果


8

私はスプライトのすべての不透明なピクセルを白でレンダリングする方法を探しています(プレーヤーがダメージを受けたときにスプライトを白に「フラッシュ」するためなど)。これはWindows Phone 7にあります。

XNA 3.1でこれを行うために非常にシンプルなカスタムシェーダーを使用していましたが、WP7はこれらをサポートしておらず、代替の証明が難しいことを発見しました。

ヘルプや提案をいただければ幸いです。ただし、ゲーム内のすべてのスプライトの真っ白なコピーを手動で作成する必要はありません。


1
わかりました、私は方法を見つけましたが、それはきれいではありません。少し整理して、回答を更新します。
David Gouveia

回答:


9

方法1

ゲーム内のすべてのスプライトの純白バージョンを手動で作成する必要はありません。ロード時にプロセスを自動化することもできます。言い換えれば、を使用Texture2D.GetData()してテクスチャのピクセルにアクセスし(そしてそれらを単純なものとして取得するColor[])、それらを反復してすべての不透明なピクセルを純白で置き換え、次にとを使用して新しいテクスチャに保存できTexture2D.SetData()ます。

方法2

私はいろいろ試してみましBlendStateたが、少なくともReachプロファイルの制限内ではなく、すべて白にする方法が見つかりませんでした。しかし、誰かが方法を知っているなら私に知らせてください。しかし、私が見つけたのは、ステンシルバッファーと組み込みAlphaTestEffectクラスを使用してそれを行う方法でした。アイデアは次のとおりです。

  1. ステンシルバッファーを持つバックバッファーを作成します。
  2. ステンシルバッファをゼロにクリアします。
  3. 白く着色したいスプライトを描画し、それらがアルファテストに合格するたびに、その位置のステンシルバッファーを1に設定します。
  4. 画面全体をカバーする白い四角形を描画しますが、ステンシルバッファーの値は1です。

これが私が使ったコードです:

(ステップ1)最初に、ステンシルバッファー用のスペースを備えたバックバッファーが作成されていることを確認します。

graphics = new GraphicsDeviceManager(this) { PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8 };

(ステップ2)1x1の白いテクスチャを作成し、画面全体に拡大縮小します。

private Texture2D pixel;
pixel = new Texture2D(GraphicsDevice, 1, 1);
pixel.SetData(new[] { Color.White });

(ステップ3)そして今、難しい部分-それをレンダリングします。まあ、それほど難しくはありませんが、2つのDepthStencilStateオブジェクトと1 つのオブジェクトが必要AlphaTestEffectです。これらは一度だけ作成する必要があります。

// Clear stencil buffer
GraphicsDevice.Clear(ClearOptions.Stencil, Color.Black, 0f, 0);

// Prepare the alpha test effect object (create it only once on initilization)
AlphaTestEffect alphaTestEffect = new AlphaTestEffect(GraphicsDevice)
{
    DiffuseColor = Color.White.ToVector3(), 
    AlphaFunction = CompareFunction.Greater, 
    ReferenceAlpha = 0, World = Matrix.Identity, 
    View = Matrix.Identity, 
    Projection = Matrix.CreateTranslation(-0.5f, -0.5f, 0) * 
    Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 0, 1)
};

// Prepare the first DepthStencilState (create only once, or put it in a static class)
DepthStencilState beforeDepthStencilState = new DepthStencilState
{
    StencilEnable = true, 
    StencilFunction = CompareFunction.Always,
    StencilPass = StencilOperation.Replace, 
    ReferenceStencil = 1
};

// Draw your sprites using the structures above
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, beforeDepthStencilState, null, alphaTestEffect);
spriteBatch.Draw(sprite, new Vector2(300, 150), Color.White);
spriteBatch.End();

// Prepare the second DepthStencilState (create only once, or put it in a static class)
DepthStencilState afterDepthStencilState = new DepthStencilState
{
    StencilEnable = true, 
    StencilFunction = CompareFunction.Equal, 
    ReferenceStencil = 1
};

// Draw a full screen white quad with the structure above
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, afterDepthStencilState, null);
spriteBatch.Draw(pixel, GraphicsDevice.Viewport.Bounds, Color.White);
spriteBatch.End();

そしてその結果:

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


すごい!デビッド、これに多くの努力を払ってくれてありがとう。残念なことに、もっと簡単な解決策はありませんが、これでうまくうまくいくはずです。
Ryan McD 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.