MoonWorks-docs/content/Graphics/Resources/RenderTarget.md

3.1 KiB

title date weight
Render Target 2021-01-26T17:59:45-08:00 5

When you write rendering code, you might intuitively think we are just drawing to the screen, but you would be wrong! In MoonWorks, we are always drawing to an object called a render target. You can think of a render target like a canvas. It can be whatever size we want and whatever color format, and we can composite them together to get our final render.

To create a render target, we need a texture slice. We can also optionally provide a multisample count.

Multisampling is a technique which can produce higher-quality images at a processing cost. You can read more about multisampling elsewhere if you're interested. If you don't want multisampling, simply use SampleCount.One or omit the sample count argument.

var myMultisampleRenderTarget = new RenderTarget(
    GraphicsDevice,
    myTextureSlice,
    SampleCount.Four
);

var myRegularRenderTarget = new RenderTarget(
    GraphicsDevice,
    myTextureSlice
)

When we use a texture slice to create a render target, we say that the render target is "backed" by the texture slice. This code will create a render target that is backed by myTextureSlice. In order to use a texture as a backing texture, you need to make sure you create it with the TextureUsageFlags.RenderTarget flag.

A lot of the time you will be creating render targets and textures at the same time. We have a nice shortcut for that.

var myRenderTarget = RenderTarget.CreateBackedRenderTarget(
    GraphicsDevice,
    1280,
    720,
    TextureFormat.R8G8B8A8,
    false
);

This code creates a 1280x720 color render target, and creates the backing texture alongside it.

Another important kind of render target is a "depth buffer". Depth buffers are used so that the graphics card can know to skip rendering on pixels that will be obscured by other objects. This can be a major optimization.

To create a depth buffer, you must use one of the depth texture formats.

var textureCreateInfo = new TextureCreateInfo
{
    Width       = 1280,
    Height      = 720,
    Depth       = 1,
    Format      = TextureFormat.D32,
    IsCube      = false,
    LevelCount  = 1,
    SampleCount = SampleCount.One,
    UsageFlags  = TextureUsageFlags.RenderTarget
};

var depthTexture = new Texture(GraphicsDevice, textureCreateInfo);

var depthBuffer = new RenderTarget(
    GraphicsDevice,
    new TextureSlice(depthTexture)
);

This sets up a 1280x720 32-bit depth buffer. We can also use our above-mentioned method to do the same thing.

var depthBuffer = RenderTarget.CreateBackedRenderTarget(
    GraphicsDevice,
    1280,
    720,
    TextureFormat.D32,
    false
);

One last thing to note - depth buffers can also contain a "stencil buffer". Stencil buffers provide a much more nuanced way to cull pixels from rendering in particular cases. You should read more about that if you're interested.

var depthStencilBuffer = RenderTarget.CreateDepthStencilBuffer(
    GraphicsDevice,
    1280,
    720,
    TextureFormat.D32S8,
    false
);