Skip to content

Instantly share code, notes, and snippets.

@Jjagg
Created January 15, 2018 22:05
Show Gist options
  • Save Jjagg/727d94a86e09efc9f557f97d44424e64 to your computer and use it in GitHub Desktop.
Save Jjagg/727d94a86e09efc9f557f97d44424e64 to your computer and use it in GitHub Desktop.
MonoGame sample for using AlphaTestEffect
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace AlphaTestSample
{
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private int _circleOffsetLimit = 100;
private int _circleSpeed = 3;
private int _circleOffset;
private int _circleOffsetDir = 1;
private Texture2D _circle;
private RenderTarget2D _renderTarget;
private AlphaTestEffect _alphaTestEffect;
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
_spriteBatch = new SpriteBatch(GraphicsDevice);
// This is the circle we'll be drawing on our render target.
_circle = new Texture2D(GraphicsDevice, 100, 100);
var circleData = new Color[100 * 100];
for (var x = 0; x < 100; x++)
for (var y = 0; y < 100; y++)
{
// this just checks if pixels are inside the circle and fills them with new Color(0, 0, 0, 0) if they are
// or Pink if they aren't (doesn't matter what color, because it won't be drawn anyway)
var dx = x - 50;
var dy = y - 50;
var inside = dx * dx + dy * dy < 50 * 50;
circleData[y * 100 + x] = inside ? new Color(0, 0, 0, 0) : Color.Pink;
}
_circle.SetData(circleData);
// this is the rendertarget we'll be clipping the circle out of
_renderTarget = new RenderTarget2D(GraphicsDevice, 200, 200);
// AlphaTestEffect lets you compare the alpha value with a reference value and only
// draw the pixel if some condition is satisfied.
// In this case we want to draw the transparent pixels to the render target, so
// we set the CompareFunction to Equal and the Reference value to 0.
// Now only pixels with an alpha value of 0 will be rendered.
_alphaTestEffect = new AlphaTestEffect(GraphicsDevice);
_alphaTestEffect.Projection = Matrix.CreateOrthographicOffCenter(0, 200, 200, 0, 0, 1);
_alphaTestEffect.AlphaFunction = CompareFunction.Equal;
_alphaTestEffect.ReferenceAlpha = 0;
}
protected override void Update(GameTime gameTime)
{
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// just a nice animation so we can see the effect is updated every frame.
UpdateCircleOffset();
base.Update(gameTime);
}
private void UpdateCircleOffset()
{
_circleOffset += _circleOffsetDir * _circleSpeed;
if (_circleOffsetDir > 0)
{
if (_circleOffsetLimit < _circleOffset)
_circleOffsetDir = -1;
}
else
{
if (_circleOffset < -_circleOffsetLimit)
_circleOffsetDir = 1;
}
}
protected override void Draw(GameTime gameTime)
{
// first make the render target all black
GraphicsDevice.SetRenderTarget(_renderTarget);
GraphicsDevice.Clear(Color.Black);
// render the circle to the render target
// we set blendstate to opaque so the destination is replaced with the source color
// and use the alpha test effect so only the transparent colors are drawn.
_spriteBatch.Begin(blendState: BlendState.Opaque, effect: _alphaTestEffect);
_spriteBatch.Draw(_circle, new Vector2(50f + _circleOffset, 50f), Color.White);
_spriteBatch.End();
// render the result to the backbuffer
GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.CornflowerBlue);
_spriteBatch.Begin();
_spriteBatch.Draw(_renderTarget, new Vector2(100f), Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment