Способ 1
Вам не нужно создавать сплошную белую версию каждого спрайта в вашей игре вручную - вы также можете автоматизировать процесс во время загрузки. Другими словами, вы можете использовать Texture2D.GetData()
для доступа к пикселям вашей текстуры (и извлекать их как простые Color[]
), перебирать их, заменяя непрозрачный пиксель сплошным белым, а затем сохранять его в новой текстуре, используя и Texture2D.SetData()
.
Способ 2
Я пытался поиграться, BlendState
но не смог найти способ сделать все это белым, по крайней мере, в рамках ограничений профиля Reach. Но если кто-то знает способ, дайте мне знать. Однако я нашел способ сделать это, используя буфер трафарета и встроенный AlphaTestEffect
класс. Идея заключается в следующем:
- Создайте буфер с буфером трафарета.
- Очистите буфер трафарета до нуля.
- Нарисуйте спрайты, которые вы хотите подкрасить белым, и всякий раз, когда они проходят альфа-тестирование, установите буфер трафарета в этом месте на 1.
- Нарисуйте белый квадрат, покрывающий весь экран, но только там, где значение буфера трафарета равно 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();
И результат: