XNA Sprite Flash Effect


8

Я ищу способ визуализации каждого непрозрачного пикселя в спрайте сплошным белым цветом (чтобы «высветить» спрайт белым, когда игрок получает урон и т. Д.). Это на Windows Phone 7.

Я использовал очень простой пользовательский шейдер, чтобы сделать это в XNA 3.1, но WP7 не поддерживает их, и найти альтернативу оказалось сложно.

Буду признателен за любую помощь или предложения. Я бы предпочел не создавать вручную сплошную белую копию каждого спрайта в моей игре.


1
Хорошо, я нашел способ, но это не красиво. Дай мне немного почистить, и я обновлю свой ответ.
Дэвид Гувея

Ответы:


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) А теперь самое сложное - рендеринг. Ну, не очень сложно, но требует двух DepthStencilStateобъектов и одного 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();

И результат:

введите описание изображения здесь


Удивительно! Большое спасибо за то, что приложили столько усилий, Дэвид. Жаль, что нет более простого решения, но это должно хорошо сработать.
Райан МакД
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.