[ Moderator Edit: Pixel perfect rendering is now available on Unity Package Manager (built in) https://docs.unity3d.com/Packages/com.unity.2d.pixel-perfect@1.0/manual/index.html ] Hi, I'm trying to choose which pixel perfect method should I use. I've seen at least 3 that seems to work pretty well but I don't know which one is the best in terms of performance and final effect. The first one is a shader: https://www.reddit.com/r/Unity3D/comments/7kdmpz/pixel_art_shader/ The second one a trick with cameras: And the third one a small script used in the cameras: I don't know if you use any other method but any suggestion is helpfull, so share it with everybody ^^ Thanks for you help!
I wasn't able to look at the videos completely but my way of doing it is having a script on the camera that lets you pick a resolution (for example: 160x144, Game Boy resolution) and it will automatically display that resolution as big as possible on screen keeping the aspect ratio and only using integer scale values:
Can you share the script to see how it works? Is seems to be similar to one of the options I've posted.
After some testing the method that gives me less errror and better performance seems to be the seccond one: However, the problem that it has is that only works with one fixed aspect ratio. I've created a script to make it able to work in any aspect ratio of the screen creating more or les horizontal pixels but with a fixed number of vertical pixels. The script that I've made is this: Code (CSharp): /* * gillemp - Triunity Studios * https://twitter.com/guplem - http://www.triunitystudios.com */ #pragma warning disable 0649 using UnityEngine; [RequireComponent(typeof(Camera))] public class MainCameraLR : MonoBehaviour { private int resolutionWidith = 1; private int resolutionHeight = 144; //Height resolution of the screen private Camera cam; [SerializeField] private Camera virtualCamera; //camera that is son of the main camera [SerializeField] private GameObject virtualScreenQuad; //quad that is son of the virtual camera [SerializeField] RenderTexture defaultTexture; //Texture applied to the main camera and the material that is applied to the quad void Start () { //Get the camera component cam = GetComponent<Camera>(); //Calculate the screen ratio float ratio = ((float)cam.pixelWidth / (float)cam.pixelHeight); //Calculate the resolution widith resolutionWidith = Mathf.RoundToInt(resolutionHeight * ratio); //Set the propoer properties for the virtual camera virtualCamera.orthographicSize = Mathf.RoundToInt(resolutionHeight / 2); //Set the propoer properties for the virtual screen quad virtualScreenQuad.GetComponent<Transform>().localScale = new Vector3(resolutionWidith, resolutionHeight, 1.0f); //Set the propoer properties for the texture defaultTexture.width = resolutionWidith; defaultTexture.height = resolutionHeight; } } I hope this helps anyone in my situation.
I was thinking about making it a free asset But as there isn't that much interest It's not a priority right now. I'm developing a Game Boy style game using this script/asset so I'll probably release the asset when I release the game.
Not quite sure what you are trying to achieve exactly. A low resolution blocky pixel type of display? What I’m doing currently is using a known size render texture, render everything to it, then scale it up. That will make absolutely all rendering become blocky, but it could also introduce some cross-pixel bilinear filtering stuff. You have to also position objects at exact integer coordinates.
I tried to use this method. Unfortunately sprites begins to shake very much when they are moving. Have you encountered with a similar problem?
Yes, exactly! How are you able to choose the original resolution and after scale it up? I could not find anything on internet except what I've posted... Thanks
I make a render texture of a given size and render to it always at that resolution. If the screen resolution is different then it gets scaled down with a separate camera. Lately though I'm doing it a little differently. I have a 640x360 virtual display resolution, IF the screen is HD 16:9 ratio. Either I make a render texture this size, or I make one at an exact multiple of this like 1280x720, 1920x1080, 4k etc. These are exact multiples. If a screen resolution isn't exact multiple vertically, I keep my pixels at exact sizes e.g. 1920x1080 has 3x3 pixels per cell. On 1024x768 for example, the closet I can get is 1024x720, with 2x2 pixel cells, and then I add some black bars at bottom and top. I am keeping the pixels-per-cell a whole value/multiple at all times. For 16:9 it works perfectly, for 16:10 it has a slight black bar top and bottom, and for 4:3 or 5:4 the horizontal width is a bit less and depending on the resolution it only increases the game display in multiples of 360 pixels height. A bad example is 1680x1050 which can't quite fit 1080 so drops to 720 and has some quite thick black bars, but not many people have that resolution. I'm also targeting desktop so I'm not really optimizing for iPads or 1024x768 2048x1534 type resolutions.
I had a discussion about pixel perfection some time ago: https://forum.unity.com/threads/pixel-perfect-advice-needed.388973/ Question: Do you have the PixelBoy script mentioned in your second video? I would like to see if this thing is sharp without blurry edges.
My method of doing is to render the camera view into a render texture, and render that texture onto the screen using GUI.DrawTexture with ScaleMode.ScaleToFit. My camera's ortho size is half of the vertical resolution. With these 2 things combined, you get this effect.
I highly doubt that your approach will ever be PixelPerfect in any sense. You will still have both problems that people try to solve when refering to PixelPerfect: - 1 pixel wide jitter(EDIT: i meant Pixelmorphing) due to point filtering and movement (camera and|or objects) - blurry edges when scaling to different resolutions PixelPerfect can only be achieved if every factor is completely designed to match: - camera's orthographic size - screen resolution - PixelsPerUnit of each texture, scale on all SpirteRenderers - PointFiltering - Camera Anchor Position Snapping - Sprite Object Position Snapping (Sprite Texture-Center matters too) I took some hours and created a PixelPerfect showcase project for you guys, enjoy! Package removed: caus' no one cares :/ (small caveat, diagonal movement in ArtPxSnap is Jittery with a CharacterController, i always recommend ScreenPxSnap)
Have you seen the video or not? Pixel jitter will happen if the positions of the objects arent aligned, and blurry "edges" are fixed by point filtering. Which in my projects, I have both of those issues solved.
Hi I've spent a few weeks hammering away at this problem for my game and will be very soon releasing an Asset that does it all for you, just type in what you want and it's ready to use (still have to setup sprites properly though). I'm using the Render Texture method, which seems to be the most efficient one and gives you a lot of flexibility. I also resize so that source pixels will never fall halfways into a screen pixel; No blurring, supports non-square pixels like Amiga/Atari 2:1 and you get to put things around the resulting image (a frame, UI, a background, whatever). I managed to get rid of the jitter, which can be caused by rounding errors relative to the camera. My result is a solid image, no jitter, even for slow moving objects and camera. How much work goes into it depends on what your game will be doing: there's no jitter if the camera doesn't move or if all objects are static and aligned to pixel. At worst, you'll need to use all of the provided scripts. Can't do anything about particles though, you'll see jitter there if they move slowly. Also managed to fit in customizable screen shake that does not make you dizzy. My camera is able to track transforms with a static call that does a configurable transition, so jumping between objects is really easy. I'm working on the video right now, I'm quite happy with the results though I'm struggling to find a version of Unity where tilemaps are not broken (srslywtf) I'll update with the video link when it's done.
Thanks for responding, You might have hard edges and no Jitter between objects, but if you zoom seamlessly you WILL have Pixelmorphing, i see that in a lot of games recently and i hate it. If you don't see this effect on your approach i am seriously puzzled because as far as i understand you cannot have free resolution AND hardEdges+noJitter+noMorphing (it's physically impossible) Look at those WEBMs to see what i mean, i zoomed in screenwise to make it very noticeable, enjoy! Pixelmorphing: Continue: Spoiler: Other Effects Pixeljitter: BlurryEdges: PixelPerfect: My Approach set to Screenpixelsnapping, u can also snap to ArtworkPixels The jerkiness is the codec and my mousemovement, Download the above unitypackage to try the build. The only time where i get artifacts is during Zoom-Transitions. This is impossible to avoid but mostly not needed anyway. captured with https://github.com/TheTarkus/WebMCam/releases
Small Followup, i tried your projects, i love Top-Down shooters and i like where you are going with your projects! I also confirmed the morphing: Spoiler: Vidz I beg you to try my PixelPerfect script on the Nuclear Throne remake and set it to SnapToScreenPixel. I always got a headache because the original Nuclear Throne snapped to Artwork-Pixels, the game could have been so smooth. I would love to see it, here is my package again, if you need any help, feel free to ask me. Package removed: caus' no one cares :/
For the first yes, I didn't fix, but for the second one that will always happen if you scale out of proportion because the pixels have to go somewhere. If the screen was at its base resolution, or x2 or x3, then it wouldn't show those effects. Thats just how rendering works. Thank you for checking out my games though, I appreciate that.
Yes, this is why i argue about the morphing. If someone has 1440p instead of 1080p your game should recognize it and adapt some values. Enter the Gungeon has very informative Settings menu on that part that is totally aware of the viewport resolution, view it as the gold standard in this regard. My scripts can help to achieve that.
Really nice depiction of the problem man! Snapping to the artworks pixels is ok on games that have mostly still screens or fixed camera movement speed. E.g. Mega Man where his running (dashing, dog-flight) speed is translated 1:1 to the camera when he moves. So the cam translates a constant amount of pixels each frame which looks neat and this is what most nostalgia games did. Also the interlaced Video mode of the CRT-screens helped those games to smooth out jagged movement by virtually moving the camera only half a pixel between frames But when you have 'smooth' slow camera movements on todays 60fps screend, the pixel snapping looks really S***ty in my opinion, and a game only improves if you smooth that out. Because when you use pixel-art and achieved pixel perfection you will have a case where 1x1 artwork pixel always consists out of 2x2, 3x3, 4x4... screen pixels. I believe it is almost always better to snap to those pixels instead except if you need the camera directly sticking on an artwork-snapping character (because then the character would bounce back and forth some screen pixels while the camera pans) Have you ever played nuclear throne? I love that game, but the jagged camera behavior when you move your mouse is always giving me headaches. EDIT: Do you also have a fix for that staircase effect? You know, when you snap to diagonal movement, the camera will often perform two orthogonal movements in different frames instead of a diagonal movement once, i can see that in your video
Thanks! it's hard to convey the problem and even more in screenshots, which I'm doing now. Resizing in an image editor brings the problem back! I haven't played nuclear throne, but I know what you mean. I intended this asset for a VERY retro look, say, Gameboy or Atari or even old mode 13h with it's non-square pixels. Scrolling was what it was, definitely not attached to a mouse though. When speed and direction are constant, it looks fine. This thing allows for adding finishing touches, so you could add motion blur or bloom or something on top. I haven't tried it yet, but I designed it for tinkering (the smooth zoom, for example, is one of those tricks that runs on top of the system). I do plan to add a helper for zelda/megaman scrolling, which should be really simple with what's already included (just a trigger that queues a transition to the new center). For snapping to screen pixels I believe you just have to turn on Pixel Snap in the material, have you tried that? I never thought of the issue you mention on diagonals, being used to it as I am in old computers. That sounds difficult. Perhaps it could be solved with a movement decimator for the camera? but then you could not keep a character perfectly centered though. Hmmm. I can't think of an example of scrolling as you mention even in old games, do you have any?
Actually i just did that today, it's just a small function that delays the SnapMovement by 10% of the pixel- or snap-Width. So the diagonal snapping is prefered when moving while orthogonal moving is only delayed by 10% of a single pixel's width. But see for yourself, its cleaner diagonal movement instead of staircasing, pretty noticable, but the video codec eats a bit of the red characters jittering non diagonal movement is also smoothed (green is staircasefiltered, orange is not): However, i would not use staircaseFiltering for Artwork-snapped camera as this messes up the rate at which orthogonal movements are triggered when the factor isn't well adjusted
@Marrt Great work - true pixel perfect is much more involved and I think many just settle with some compromises. I offered unity a long time ago to work with them on a tutorial but it never happened and I am not so active anymore. I have not tested unities alpha/beta for pixel perfect, but they might be finally addressing it. Your implementation looks great, maybe you should wrap it up in a retro asset (a plan I once had) which includes things like pixel collision, advanced screen wrap, mod player, palette reduction, crt shader, etc...
Oh I get it now. Slowing down the gif is a great feature btw. You're correct in that it messes up the rate (you can see it happening already). Is this preferable for some people? When pixels are tiny, you wouldn't notice anyway so it's only an issue for big pixels. I could make it an option. BTW would you call that video artwork snapping? because I would. Just checking.
Yes, whenever you snap to the pixels of your spritetexture, i refer to it as ArtPxSnapping. When you snap to fractions of artwork-pixels (because your screen uses more than one pixel to display it), i talk about ScreenPxSnapping. But you know what, i completely forgot i can just build a WebGL Build and let you guys try it: http://marrtgames.com/playerFiles/PixelPerfectRendering/
"This repository contains samples of the 2D Pixel Perfect features to be used with Unity 2018.2b3 and newer" https://github.com/Unity-Technologies/2d-pixel-perfect
This is absolutely what I have been waiting for all along! It works super well and is a breeze to set up. Well done guys! To anyone making 2D pixelart games, I highly recommend it!
Get it using Package Manager. No need to hunt around github and PM will allow easy in-unity updating. I edited the original post for new readers.