Method 1
You don't have to create a solid white version of every sprite in your game manually - you could just as well automate the process at load time. In other words, you can use Texture2D.GetData()
to access the pixels of your texture (and retrieve them as a simple Color[]
), iterate over them replacing any non-transparent pixel with solid white , and then save it to a new texture using and Texture2D.SetData()
.
Method 2
I tried playing around with BlendState
but couldn't find a way to render it all white, at least not within Reach profile's limitations. But if someone knows a way let me know. What I did find, however, was a way to to do it using the stencil buffer and the built-in AlphaTestEffect
class. The idea is the following:
- Create a backbuffer that has a stencil buffer.
- Clear the stencil buffer to zero.
- Draw the sprites you'd like to tint white and whenever they pass the alpha test, set the stencil buffer at that location to 1.
- Draw a white quad covering the entire screen, but only where the value of the stencil buffer is 1.
Here's the code I used:
(Step 1) First make sure the backbuffer is being created with room for a stencil buffer:
graphics = new GraphicsDeviceManager(this) { PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8 };
(Step 2) Create a 1x1 white texture that will be scaled to fill the entire screen:
private Texture2D pixel;
pixel = new Texture2D(GraphicsDevice, 1, 1);
pixel.SetData(new[] { Color.White });
(Step 3) And now the hard part - rendering it. Well, not really hard, but requires two DepthStencilState
objects and one AlphaTestEffect
object. You should create these only once.
// 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();
And the result:
