Here's my way of adding transparent holes in your background. It uses a simple pixel shader that subtracts the values. I'm not sure this is the best way, there may be some tricks possible simply by using a custom BlendState and the Subtract function.
What I did was create two rendertargets. One holding your dirt. This could just be a large texture, however, to get it tiling dynamically, rendertargets was a good choice.
First I prepare them in the LoadContent override.
...
// Prepare the dirt layer.
this.earthRenderTarget = new RenderTarget2D(this.GraphicsDevice, 1280, 720);
this.GraphicsDevice.SetRenderTarget(this.earthRenderTarget);
this.GraphicsDevice.Clear(Color.Black);
this.spriteBatch.Begin();
for (var x = 0; x < (1280 / this.earth.Width) + 1; x += 1)
for (var y = 0; y < (720 / this.earth.Height) + 1; y += 1)
this.spriteBatch.Draw(this.earth, new Vector2(x * this.earth.Width, y * this.earth.Height), Color.White);
this.spriteBatch.End();
// Prepare the "hole" layer, with 100 random holes.
this.maskRenderTarget = new RenderTarget2D(this.GraphicsDevice, 1280, 720);
this.GraphicsDevice.SetRenderTarget(this.maskRenderTarget);
this.GraphicsDevice.Clear(Color.Transparent);
this.spriteBatch.Begin();
var random = new Random();
for (var i = 0; i < 100; i += 1)
this.spriteBatch.Draw(this.chunkMask, new Vector2(random.Next(1280), random.Next(720)), Color.White);
this.spriteBatch.End();
...
Here's the pixelshader code I used. It just subtracts the individual color components.
texture Mask;
sampler textureSampler : register(s0);
sampler maskSampler = sampler_state
{
Texture = <Mask>;
};
float4 MaskFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
float4 color = tex2D(textureSampler, texCoord);
float4 mask = tex2D(maskSampler, texCoord);
return color - mask;
}
technique MaskTechnique
{
pass MaskPass
{
PixelShader = compile ps_2_0 MaskFunction();
}
}
And finally, I combine the two rendertargets in the Draw override like this:
...
this.GraphicsDevice.SetRenderTarget(null);
this.GraphicsDevice.Clear(Color.CornflowerBlue);
this.maskEffect.Parameters["Mask"].SetValue(this.maskRenderTarget);
this.spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, this.maskEffect);
this.spriteBatch.Draw(this.earthRenderTarget, Vector2.Zero, Color.White);
this.spriteBatch.End();
...
You can see it in action here.
Now, you'll need to implement a rendertarget swapper to further edit the "hole" rendertarget, but I'll leave that as a challenge for you.