Taking damage and a new background

I implemented a quick pixel shader to make characters flash when they take damage. See it in action, along with a slightly less dopey background image, here:

On my first pass, I was trying to toggle parameters on the shader multiple times during every round of the SpriteBatch Begin() / End() lifecycle, as in the following illustration:

_spriteBatch.Begin(0, null, null, null, null, effect);
foreach ( IGameEntity ent in _entities ) {
    effect.Parameters["MyParam"].SetValue(ent.ParamValue);
    ent.Draw(_spriteBatch, _camera);
}
_spriteBatch.End();

That doesn’t work — all drawn entities flash at the same time, because they all end up with the same shader parameters. This makes sense when you actually stop to think about what a SpriteBatch is and how it has to function. Essentially, the graphics card doesn’t do any work, and therefore no shader functions are called, until SpriteBatch.End(). So no matter how many times you tweak Effect parameters in between Begin() and End(), only the last one will take effect, and do so globally.

There are at least two solutions to this problem and possibly a third that I haven’t tried:

  1. Just draw each sprite in its own Begin() / End() pair. This has performance constraints, but for a small number of sprites it’s perfectly doable. This is what I’m doing at the moment.
  2. Group the sprites into batches where the Effect should be the same, then draw each batch in its own Begin() / End() pair. A little more work, and it might be a pain to get the draw order right, but also doable.
  3. Encode information in the Color passed to the shader function via the call to SpriteBatch.Draw(). This should enable you two switch between different modes of operation multiple times in the same draw batch — although I haven’t tried this yet.

This effect will be used pretty extensively in the game, with different colored silhouettes forming an important element of the visual style.

Leave a Reply