I’m porting and expanding my simple pixel game made in XNA to MonoGame. Porting was fast and now I’m adding new features.
The game is low res and is upscaled to screen size with resolution/matrix class I found online.
I draw textures with SamplerState.PointClamp. Game looks good up untill I wanted to try out rotating textures… they are ugly when I upscale them
If I play the game in real resolution without upscaling, it looks nice and oldschool.
Gif of rotating pixels in real resolution:
Gif on screen upscaled to 1920x1080:
As you can see the upscaled has rotated pixels instead of squares. How can I fix this? I tried googling and finding help but I didn’t find anything.
My current setup:
MonoGame 3.5 (I didn’t go with 3.6 yet ), Visual Studio 2015 Community, Windows 10, cross-platform template project.
I don’t use shaders because I have no experience and knowledge how they work or how to use them
Can you post a link to the resolution/matrix class you’re using?
You work around this if you draw to a low res rendertarget and only upscale the final image
I understand you want to rotate the sprite, but want the pixels inside to stay unangled (horizontal alignment).
This is super trivial to do and the easiest solution is to upscale after drawing the whole image.
For that you can use rendertargets (if you need help let me know).
Otherwise you can use a custom shader that uses some form of quantization for the pixel shader texture read. (Again I could help you with that, but make sure solution one doesn’t work for you first). That’s not trivial to implement into the default spritebatch.draw() pipeline and you’d have to make some adjustments to either monogame itself or make a custom spritebatch implementation.
This should be it https://gist.github.com/DJLink/1089892#file-resolution-cs
I have made few changes to it, like functions for my Camera system.
Yes I want to rotate the texture without having “rotated look” on the pixels.
About rendertargets, I have read about them but haven’t used them, because I read that they use lot of performance and memory(?).
If I use them, should I create new rendertarget for each frame? Or should I make one large rendertarget and clear it each frame before drawing new stuff on it?
Neither performance nor memory should be a concern if you use one rendertarget (or just a few)
You should create one rendertarget as a field somewhere
private RenderTarget2D _renderTarget;
Then you need to initialize the rendertarget at the beginning of your game
public void Initialize(...)
_renderTarget = new RenderTarget2D(graphicsDevice, width, height);
The width, height is what you want your ideal (low resolution) to be.
Then you render everything as usual, but tell the GPU to render to _renderTarget
done! Now render the result to the screen:
_graphicsDevice.SetRenderTarget(null); // Backbuffer
_spriteBatch.Draw(_renderTarget, ... final size etc.)
As you can see you can treat the rendertarget just like any other sprite/texture.
I got rendertargets work to a point.
For some reason rendertarget draws only top left corner of my game. and no matter what size the rendertarget is, there is just black after certain point. With smaller size the black begins earlier…
And because it shows only the top left corner of game area (not the camera area), the game is unplayable because player cannot see
Maybe its just that current resolution independence and camera system aren’t suited for rendertargets
rendertargets work exactly the same way as your normal “non-rendertarget” state (backbuffer).
In fact, the backbuffer is just another rendertarget.
So the problem must be somewhere inside the code.
What is your screen resolution? You must draw the rendertarget to the complete window!
_spriteBatch.Draw(_renderTarget, new Rectangle(0,0, WindowWidth, WindowHeight), Color.White);
Problem is not that the image/rendertarget is small compared to screen. Problem is that the image/rendertarget is literally just the corner of my game because when I render the game, rendertarget is at zero point.
Is it possible to set rendertarget’s position before drawing, so that currently visible area is rendered to it? That should fix my problem.