Instantly share code, notes, and snippets.

What would you like to do?
MonoGame RenderTarget Scaling
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
public class Game1 : Game {
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
RenderTarget2D renderTarget;
const int VIRTUAL_WIDTH = 1366;
const int VIRTUAL_HEIGHT = 768;
public Game1 ()
graphics = new GraphicsDeviceManager (this);
Content.RootDirectory = "Content";
graphics.IsFullScreen = false;
TouchPanel.DisplayHeight = VIRTUAL_HEIGHT;
TouchPanel.DisplayWidth = VIRTUAL_WIDTH;
TouchPanel.EnableMouseTouchPoint = true;
protected override void Initialize ()
spriteBatch = new SpriteBatch (graphics.GraphicsDevice);
PresentationParameters pp = graphics.GraphicsDevice.PresentationParameters;
// create a surface to draw on which is then scaled to the screen size on the PC
renderTarget = new RenderTarget2D(graphics.GraphicsDevice, VIRTUAL_WIDTH, VIRTUAL_HEIGHT, false,
SurfaceFormat.Color, DepthFormat.None, pp.MultiSampleCount, RenderTargetUsage.DiscardContents);
base.Initialize ();
protected override void Dispose (bool disposing)
if (disposing) {
renderTarget.Dispose ();
renderTarget = null;
base.Dispose (disposing);
protected override void LoadContent ()
base.LoadContent ();
protected override void Update (GameTime gameTime)
var gamePadState = GamePad.GetState (PlayerIndex.One);
var keyboardState = Keyboard.GetState ();
var touchPanelState = TouchPanel.GetState ();
if (gamePadState.IsButtonDown (Buttons.A) || keyboardState.IsKeyDown (Keys.A)) {
// do something
foreach (var touch in touchPanelState) {
if (touch.State == TouchLocationState.Pressed) {
// do something
base.Update (gameTime);
protected override void Draw (GameTime gameTime)
//Draw your stuff
graphics.GraphicsDevice.Clear (Color.MonoGameOrange);
// draw render target
float outputAspect = Window.ClientBounds.Width / (float)Window.ClientBounds.Height;
float preferredAspect = VIRTUAL_WIDTH / (float)VIRTUAL_HEIGHT;
Rectangle dst;
if (outputAspect <= preferredAspect)
// output is taller than it is wider, bars on top/bottom
int presentHeight = (int)((Window.ClientBounds.Width / preferredAspect) + 0.5f);
int barHeight = (Window.ClientBounds.Height - presentHeight) / 2;
dst = new Rectangle(0, barHeight, Window.ClientBounds.Width, presentHeight);
// output is wider than it is tall, bars left/right
int presentWidth = (int)((Window.ClientBounds.Height * preferredAspect) + 0.5f);
int barWidth = (Window.ClientBounds.Width - presentWidth) / 2;
dst = new Rectangle(barWidth, 0, presentWidth, Window.ClientBounds.Height);
// clear to get black bars
graphics.GraphicsDevice.Clear(ClearOptions.Target, Color.Black, 1.0f, 0);
// draw a quad to get the draw buffer to the back buffer
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque);
spriteBatch.Draw(renderTarget, dst, Color.White);
base.Draw (gameTime);

This comment has been minimized.

kuczmarm commented Jun 25, 2017

I don't believe the touch position accounts for the screen offset if there is a aspect ratio change. The touch panel display doesn't offset for the black bars if existent. I'm not sure how you would account for this except to manually apply dst.X and dst.Y to all touch position checks.


This comment has been minimized.

fabemish commented Jul 2, 2018

To improve on this, you can make a ScaledGame class which will give you the regular XNA calls (because ScaledGame inherits Microsoft.Xna.Framework.Game) but also scale the game when you base.Draw(gameTime). That would be a legitimate template. This code looks somewhat bloated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment