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:
- 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. - Group the sprites into batches where the
Effect
should be the same, then draw each batch in its ownBegin() / End()
pair. A little more work, and it might be a pain to get the draw order right, but also doable. - Encode information in the
Color
passed to the shader function via the call toSpriteBatch.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.