Thursday, November 3, 2011

Rendering to a texture

    Sometimes it is required to render to something else than the screen. This can be useful if we want to generate our own textures, save a screenshot or create shadows using shadow maps. After we render the image we can then use it as any other regular texture in our shaders. In this application we will replace the texture of the bottom-right corner of the image from the crate texture to a scene of the same cube on the main part of the screen only on a different color background.




Backreferences:


You can download the starting source code from here. It already draws both the cube and the square, this way you only have to concentrate on how to render to a texture and how to set it up.
First of all, the rendering pipeline has a target, it’s the matrix of pixels that it draws too, this is usually our screen (viewport actually). So in order to draw to something else we will need to link the rendering pipeline to a different object. But what will this object be? In XNA we will use a simple object called RenderTarget2D, so just declare one somewhere at class level.

    RenderTarget2D target;

Now we have to instantiate our object, the constructor I’m going to use is going to require the current GraphicsDevice and the size of the render target. For the size I’ll use the viewport size. We don’t actually need a resolution so big because we are going to draw this texture to only a quarter of the screen, but for simplicity I’ll just set them to the viewport size. Add the following line of code in the initialize function.

    target = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);

To use this render target we will have to set it as the current render target for our graphics device, we do this by calling the SetRenderTarget method of our GraphicsDevice object with our render target as the parameter. Insert this line of code at the beginning of the Draw method, this way we can render the texture before the scene.

    GraphicsDevice.SetRenderTarget(target);

At this point our GPU will render to our texture, so all we have to do is call the draw function normally (don’t forget to call clear). Add these 2 lines of code in Draw right after the one above.

    GraphicsDevice.Clear(Color.White);
    RenderCube();

After we have finished rendering to our texture we should reset the rendering target to the viewport, we do this by setting a null render target. After rendering the cube add this line of code:

    GraphicsDevice.SetRenderTarget(null);

Almost there, we have our texture, the shader was already written from the simple texturing tutorial, now all we have to do is set the effect texture to our render target just before drawing our square, just go ahead and add this line of code after RenderCube() but before RenderSquare() in the Draw method.

    simpleTextureEffect.Parameters["tex"].SetValue(target);

As you can see, this is very easy, you can also set different properties for the RenderTarget2D (like format & usage) but more on that later.
For now you should have a look at the finished render to texture source code. Your application should look like this right now:


1 comment:

  1. I'd like to talk to you about your XNA articles, do you have a public email or contact form?

    ReplyDelete