Metodo 1
Non è necessario creare manualmente una versione bianca completa di ogni sprite nel gioco : è possibile anche automatizzare il processo al momento del caricamento. In altre parole, è possibile utilizzare Texture2D.GetData()
per accedere ai pixel della trama (e recuperarli come semplici Color[]
), scorrere su di essi sostituendo qualsiasi pixel non trasparente con bianco solido, quindi salvarlo su una nuova trama utilizzando e Texture2D.SetData()
.
Metodo 2
Ho provato a giocare con BlendState
ma non sono riuscito a trovare un modo per renderlo tutto bianco, almeno non entro i limiti del profilo Reach. Ma se qualcuno conosce un modo fammelo sapere. Quello che ho trovato, tuttavia, è stato un modo per farlo usando lo stencil buffer e la AlphaTestEffect
classe integrata . L'idea è la seguente:
- Creare un backbuffer che ha un buffer di stencil.
- Cancella lo stencil buffer a zero.
- Disegna gli sprite che desideri tingere di bianco e ogni volta che superano il test alfa, imposta il buffer dello stencil in quella posizione su 1.
- Disegna un quadratino bianco che copre l'intero schermo, ma solo dove il valore del buffer di stencil è 1.
Ecco il codice che ho usato:
(Passaggio 1) Assicurarsi innanzitutto che il backbuffer venga creato con spazio per un buffer di stencil:
graphics = new GraphicsDeviceManager(this) { PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8 };
(Passaggio 2) Crea una texture bianca 1x1 che verrà ridimensionata per riempire l'intero schermo:
private Texture2D pixel;
pixel = new Texture2D(GraphicsDevice, 1, 1);
pixel.SetData(new[] { Color.White });
(Passaggio 3) E ora la parte difficile: renderizzarla. Bene, non proprio difficile, ma richiede due DepthStencilState
oggetti e un AlphaTestEffect
oggetto. Dovresti crearli solo una volta.
// 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();
E il risultato: