Simply RenderTargets

May 26, 2009 at 6:39 pm (Other Stuff, XNA) (, , )

Somebody in the #xna IRC channel just asked how to use RenderTargets to only draw a portion of the screen. Here’s my answer.

I guessed from his brief description he might have a game scene which didn’t look like this

 

background

And the result he wanted, was something almost like … this ?

pieview

What you see here is the game scene drawn, with a triangle portion visible and the rest not so much. My favourite way to achieve this is to use 2 RenderTargets, A VERY simple Effect(shader) and good old SpriteBatch. So what do we use all this for?

First we need to draw the game scene. There is a way around this but to make things easier to understand we will draw this to a RenderTarget. Simply put, a RenderTarget is an imaginary “screen” to draw to which you can specify the size of. Then once done, you can use the texture like any normal Texture2D you might load from the Content Pipeline.

To draw the scene we first want to set the correct RenderTarget, then use spritebatch just like you would to draw any other sprite. Like this.


            GraphicsDevice.SetRenderTarget(0, _gameRT);
            //Clear the RT screen
            GraphicsDevice.Clear(Color.Black);
            spriteBatch.Begin();
            //Draw the game
            spriteBatch.Draw(
                _gameBackground,
                Vector2.Zero,
                Color.White);

            spriteBatch.End();

Simple uh?

Now we need to create another RenderTarget, and Draw a triangle to it. This will never be displayed in the final scene. Although with the RenderTarget it allows you to if you so desire, maybe for debugging purposes?


	    
            GraphicsDevice.SetRenderTarget(0, _lightRT);
            //Clears the screen transparent.
            GraphicsDevice.Clear(Color.TransparentBlack);
            spriteBatch.Begin();
            
            spriteBatch.Draw(
                _triangle,
                Vector2.Zero,
                Color.White);

            spriteBatch.End();

This code is almost identical to the last except we draw the _triangle Texture which looks like this.

triangle

And we use the color transparent black.

The final thing we need to do now is draw it to the scene.

If we just draw the triangle on top of the game scene you will see the game scene with a white triangle on top. This isnt what we want. So we use a shader to take the game scene, and change the alpha channel corresponding to the white triangle. Wherever there is a solid non transparent color pixel, this will be set to a fully non transparent pixel in the game result, however, a transparent pixel in the triangle image will result in a completely transparent pixel in the final result. Resulting in you not being able to see that pixel. The final result is like this.

pieview

 

The shader code is very simple. It is a pixel shader which takes a AlphaTexture parameter which is the texture taken from the triangle RT. It takes the alpha from that texture, and sets the coresponding pixel on the final image to be the same.


float4 PixelShader(float2 texCoord: TEXCOORD0) : COLOR
{
	float4 Color = tex2D(ScreenS, texCoord);
    float alphaLayerAlpha = tex2D(AlphaSampler, texCoord).a;
	Color.a=alphaLayerAlpha;
    return Color;  
}

Cool?

To use this we just create a new Effect variable and load it in LoadContent. Call Begin/End in the appropriate places, set the parametar and hey presto. A RESULT!!!


_myEffect.Parameters["AlphaTexture"].SetValue(_lightRT.GetTexture());
spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
_myEffect.Begin();
_myEffect.CurrentTechnique.Passes[0].Begin();
spriteBatch.Draw(_gameRT.GetTexture(),
    Vector2.Zero,
    Color.White);

_myEffect.CurrentTechnique.Passes[0].End();
_myEffect.End();
spriteBatch.End();

To get a better grasp of the code you can download the sample project here.

DOWNLOAD

As I said, Someone in IRC literally just asked. So I knocked this up. Apologies for the rushed post 🙂 BACK TO SBARG!!!

Permalink 2 Comments