Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Pixel Perfect problems are back

Discussion in '2D' started by neil89, Mar 14, 2015.

  1. neil89

    neil89

    Joined:
    Sep 30, 2013
    Posts:
    7
    ¡Hello! My name is Daniel and I'm using Unity for 2 years. I've learned a lot of things on this time and now I'm developing a game with two more colleagues. Our game is tiny detailed pixel perfect game.

    We faced "the pixel perfect problem" in early days. We didn't worry too much, because we thought it'd be easily solved after some googling. We're so mistaken... After weeks of googling and try lots of apparently suitable solutions, we keep getting some pixels duplication/deletion.



    With Pixel Perfect I mean every single pixel in my sprite is represented proportional in Unity, I mean, they can be scaled up or down, but all of them by the same amount. I've been trying a huge number of things:
    1. Sprites importing
      • Filter mode: Point
      • Pixels per unit: 100, 1, sprite size
      • Format color: True color, RGBA32
    2. Sprites material
      • Pixel snap checked
    3. Sprites movement
      • Pixel snap: code a function that set movement in a grid of 0.01 or 1 (depending on pixels per unit of sprites)
    4. Camera
      • Orthographic
      • Size = Screen.height / 2 * pixelsPerUnit
      • Size = Screen.height / 2 * spriteSize
      • Pixel snap: code a function that set movement in a grid of 0.01 or 1 (depending on pixels per unit of sprites)
    5. Quality settings (Rendering)
      • Texture quality: full res
      • Anisotropic textures: disabled
      • Anti aliasing: disabled
    By the way, I'm using Unity 4.6 (porting to 5). After trying all this with no results, I'm about to quit, is very frustrating... It'd be great if you guys could throw some light on this topic. Maybe a tip, a tutorial or any other stuff.

    Lots of thanks in advance,
    Daniel
     
  2. AwesomeAppDev

    AwesomeAppDev

    Joined:
    Feb 6, 2014
    Posts:
    2
    Sébastien Dubois from Amplitude Studios gave many tipps how they achieved "Pixel Perfect" for their game - have a look at his Unite 2014 talk maybe it helps to address some of your issues:
     
    neil89 likes this.
  3. rogueknight

    rogueknight

    Joined:
    Feb 16, 2014
    Posts:
    44
    I don't know if this is what your are looking for but here is what I wrote to a previous post about a similar issue:

     
    mescherskys, neil89 and theANMATOR2b like this.
  4. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    One thing that bothered me about pixel snap is that it functions on a PER-VERTEX basis. In the shader, the code which applies the pixel snap (if I understand it right), applies an adjustment to the position of the current vertex. It doesn't have any awareness of the other vertices, and the positions of the other vertices are not affected by this instance of the 'fix'. What can happen, and what I have literally seen happen, is that vertices on the left and right edges of a sprite can be 'fixed' differently, and independently. I had a spaceship sprite which, as it moved, it would `wiggle` in a slight and strange way, as if the width of the sprite were alternating between +- 1 pixel width difference. This was noticeable because I was using a special shader which made it really obvious. I believe it's somewhat to do with the inaccuracy of floating point math, whereby the result of `rounding` pixel coordinates on one vertex may produce a number that isn't quite rounded in the same way for the other vertices. So one vertex was getting shifted to the left, while the other wasn't, or vice versa. I guess that might have something to do with me using floating point coords for sprite positioning, but I also tried it with integer coordinates - and you know, floating point numbers have some trouble accurately representing exact integer values... and that very slight difference may be enough to cause numbers to sometimes round up, rather than down, adding or subtracting one pixel to the width of the sprite geometry. That is enough to make pixels appear or disappear, and can be quite noticeable. At least this is my theory, and it's especially noticeable if you are using point sampling (like I was). Maybe less noticeable with bilinear, but still, sprites shouldn't be changing their pixel width AT ALL. I think it'd be better to note use this feature, and instead have unity implement some kind of 'adjustment' at the vertex data level, as the mesh data is submitted to the gpu, rather than in the shader, so that width and height are maintained.

    I don't know if this is your problem or the only part of it, but I found this to be a problem with no easy workaround. If you don't use sprites and you create your own quad geometry you can maybe better control the exact amount of pixels that the sprite spans and reduce the issues with point sampling.
     
    neil89 likes this.
  5. neil89

    neil89

    Joined:
    Sep 30, 2013
    Posts:
    7
    @AwesomeAppDev thanks for your video! I've been following them for months and I've watched that video a couple of times too... :(

    @rogueknight thanks your your answer. My sprites already are POT. I know the plugin (I've spoken with the creator too), I think we'll have to buy it.

    @imaginaryhuman Thans a lot for your detailed answer. That's exactly the main problem! My sprites are stretched or compressed horizontally, always about 1 pixel. It looks really weird on areas like legs (compare left image with centered and right). So, what's the point? Use pixel snap? Not use it? Make a custom shader for sprites...?
     
  6. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    I dont know if there is actually a way to use pixelsnap that really works..... what was Unity's intention? Maybe you have to position the sprite at always 0.5 above an integer pixel position, or 0.25, or something, so that when things round or whatever it does so in the same way to all vertices? Worth playing around with that to see if it helps. Otherwise I guess you want to create your own procedural geometry with exact coordinates.
     
    neil89 likes this.
  7. neil89

    neil89

    Joined:
    Sep 30, 2013
    Posts:
    7
    Actually I've read about that in some thread. It's supppossed that if you place your sprite with an offset of a float point number (I don't remember how much) the pixel snap works properly. I'll try it some and if it's work I'll post here. Thanks a lot for your responses.
     
  8. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    It's crazy how much effort is needed just to get the very basic stuff needed for a 2D game. You'd think these are exactly the kind of things the engine would be automatically handling.

    I ran into many issues with 2D in Unity but through numerous experiments by myself and others shared on the forums finally got around them. The past 3 projects have went smoothly.

    Your list in the OP looks very much like what I am doing except I also take care in how I import sprite images into Unity.

    I am used to being able to just bring in an image with sprites or tiles all gridded right next to each other. However, this doesn't work with Unity. So I ended up having a 2-pixel transparent border around every sprite or tile image. For example, if my tile images are 32x32 I have 2 transparent rows before the tile images and 2 transparent columns. Then I have a 32x32 tile image. 2 transparent columns. Another 32x32 tile image. Until the end of the row and then 2 transparent columns. Another 2 transparent rows. Then same process again for this row of tiles. I use the same approach for sprite images. Otherwise you can get weird artifacts.
     
  9. neil89

    neil89

    Joined:
    Sep 30, 2013
    Posts:
    7
    Thank you very much for you answer @GarBenjamin ! Wow, that's exactly our feeling! We wish a "PixelPerfect" option exist, in the same way as 2D or 3D project, and get things working properly directly...

    About your 2 pixels border approach... Should it be exactly 2 pixels width/height? By now we're importing an individual image of idle like next image:
    player_idle.png
    Obviously "border" is wider than 2 pixels. Shouldn't it work because of that? I mean, should it be EXACTLY 2 pixels? Any other advice about the rest of configurations? They are a lot, so mixing and combining all of them is quite difficult...
     
  10. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You guys don't really understand the nature of the problem. Currently, Unity will do pixel perfect without any effort, but only if your resolution never changes. This is the same for all engines that are build on top of 3D hardware.

    If you want to support a device which has higher or lower resolution then you will incur lossy results.

    For example, you want your game to have a virtual resolution of 320x240? then you create a resolution of 320x240 and set camera to ortho with a size of 120 (half height), and all units are then 1 unit = 1 pixel. This will always be pixel perfect.

    But what if a phone has a non standard size? You can minimise this issue a fair bit by using sprite shader snap feature, and designing the resolution smaller than the target display, as at least scaling up will only add pixels as opposed to removing them because there isn't resolution to support.
     
    neil89 and theANMATOR2b like this.
  11. neil89

    neil89

    Joined:
    Sep 30, 2013
    Posts:
    7
    Hi @hippocoder , thank you for your answer. I'm afraid I'm not explaining well. I don't intend my resolution changes, since the beginning my target resolution is the default offered by Unity, 1920 x 1080. We don't intend to export this to any mobile platform. Anyway, though my resolution is static, I don't know the settings to get pixel perfect with no effort for that single resolution...

    I'm following your instructions and still my sprite is not seeing pixel perfect (actually the screenshot above was get with this settings). Am I missing something? Do you really think it deserves to use 1 ppu and multply all forces (including gravity) times 100? Sorry if this is maybe too obvious doubts, but for me this task is not so effortless :(
     
  12. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    Actually Hippocoder is right... when I had my project in the same resolution display as it was designed for the problem was pretty much gone... it was only when displaying in a different resolution that it then became a problem. This didn't really resolve it for me though, because I am working at a fixed `development resolution` of 1920x1080 and have my camera say to 540 height, so that it adjusts and scales to all resolutions the same..... this kind of setup does not work with the pixel snapping. The pixel snap will work if you are using like a 1:1 pixel mapping where, in higher resolutions, your graphics get smaller ie use the same number of pixels. So I think you can't use pixelsnap if you are scaling your graphics to fit the resolution instead of changing the camera size.
     
    neil89 likes this.
  13. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Yeah there is more to it than that. There are numerous things that need to be done. Some are obvious yes such as keeping the display a perfect 1 to 1 pixel mapping (or a scaling so things are doubled or tripled exactly). The 2D pixel work needs many different things to all be taken into account such as the OP lists as well as taking some additional consideration on the sprite images themselves when loaded in to the sprite editor.

    @neil89 if you can make a tiny project that illustrates the issue and upload it I will see if I can get it working using my current workflow / bag of tricks.

    EDIT: I should add that I use 4.6 don't plan on moving to 5 until at least another month or two. So if you can dupe the issue in a 4.6 project I will try to resolve it.
     
    neil89 likes this.
  14. neil89

    neil89

    Joined:
    Sep 30, 2013
    Posts:
    7
    Thanks to all of you, specially @GarBenjamin, I've achieved pixel perfect on Unity 4.6 following some minor tweaks:
    1. Setting up the output resolution. I was building my game on 1920x1080, though my screen max resolution is 1280x1024. So, I changed the built resolution to that one
    2. Set orthographic camera size to [ Screen height / (2 * Pixels Per Unit) ]. Since my PPU is 100, I set camera size to 5.12.
    3. Assigned sprite renderer material with Pixel snap enabled
    That was all. If I run the game on Editor, Game panel is not same resolution as my screen so camera size should be adjusted (thanks again to @GarBenjamin by set this point clear too).

    Again, thanks a lot to everybody who support me on this and try to help. I hope this help more people too. We're in touch. Regards!
     
  15. RichardKain

    RichardKain

    Joined:
    Oct 1, 2012
    Posts:
    1,261
    It's also worth noting that pixel-perfect rendering is a lot more necessary when dealing with scaled pixel art. For higher-resolution games, running native-resolution sprites, slight changes in individual pixels are much harder for the average eye to perceive.

    When you are scaling up pixel-based artwork, however, these differences become much more evident, even to the untrained eye. For cases like this pixel-perfect rendering becomes much more important.

    One method you might consider is an adjustment to the movement controller for individual sprites. In a 3D environment, improper pixel rendering often occurs because an objects position is between where a pixel difference would normally occur. A simple script could be used to adjust an objects "rendered" position based on integer values in order to keep it's rendered sprite pixel-perfect.
     
    neil89 and GarBenjamin like this.
  16. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    @RichardKain that is spot on. In my very low res pixel project all sprites are positioned to pixels. The camera is also positioned to pixels when scrolling.

    Like you said though I do think many people might not understand the issue because unless you are working with very low res pixel art the issues won't be noticeable. If you just make a 2D game using hd graphics the problems will likely not even be noticeable. But when you are working with sprites that are like 16 x 16 pixels and on screen that is essentially 256 x192 pixels these little distortions / glitches are very noticeable. The same artifact occuring on a sprite 80 x 67 pixels on a 1280 x 800 display will probably not even be noticed.
     
    Last edited: Mar 18, 2015
    neil89 likes this.
  17. RichardKain

    RichardKain

    Joined:
    Oct 1, 2012
    Posts:
    1,261
    Right. A game like, say...Rogue Legacy wouldn't really suffer from this issue all that much. It's a 2D game, sure, but it is designed from the ground up to be run at high-definition resolutions. Most of its sprites are designed to look good at HD resolutions. Any such artifacts from scaling would be much less obvious.

    However, a game like, say...Shovel Knight would have a lot more of a problem with this issue. That game is designed to emulate old-school retro pixel resolutions and graphics. Scaling artifacts for a game like that would be much more noticeable to the player, and much more distracting.
     
    neil89 and GarBenjamin like this.
  18. Douvantzis

    Douvantzis

    Joined:
    Mar 21, 2016
    Posts:
    79
    I've reading around the forum and everyone posts the same equation that I see here: Screen height / (2 * Pixels Per Unit)

    This does enable pixel perfect rendering, but changes the scale of the sprites depending on the resolution, which is undesirable. I'll paste a part of my answer from another thread.

    In order to achieve pixel-perfect rendering and render everything in the appropriate scale regardless of the screen resolution, you just need to set the camera size taking the following into account:
    • the screen resolution
    • the pixels per unit of the assets
    • a desired orthographic camera size

    I have created a simple camera script (which is free) that takes all of this into account. You can set the desired camera height (or width) and the script will find the closest pixel-perfect camera size. It works for every resolution, be it on mobile or even the arbitrary resolutions used in the editor. See it in action in this HTML5 demo.

    Also, pixel snap (as imaginaryhuman explained) corrects a sprite per vertex. This does not enable pixel-perfect rendering but just reduces the shimmering artifact. Also, as he points out, it may create another artifact if 2 vertices get corrected in a different way. So, I would avoid using that.
     
    Last edited: Jul 18, 2016
    theANMATOR2b likes this.
  19. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    Something to also keep in mind is that the graphics hardware API (OpenGL/DirectX etc) typically works using floating point math. This practically guarantees that some amount of imprecision is going to creep in somewhere. Vertex data is floating point as well. Even if you could pass exact ideal 4-vertex values to every vertex in a custom shader to have it 'correct' the positions and maintain exact sprite width and height to whole integer values, it's still going to have to deal with the fact the data is floating point and may result in a little bit of offset in terms of position.

    I particularly had an issue with pixel accuracy because I had this shader which indirectly rendered pixel colors, ie using a lookup table mapping instead of using the texture colors. It was extremely difficult to get exactly precise lookup of the exact right pixels from the indirect palette texture, without some kind of shimmering or dancing or occasional glitching of the pixels. I think the best and only way and only scenario in which this can be accomplished is when you are using as close to integer coordinates as possible in a SINGLE resolution display with exact 1:1 pixel:texture mapping, and avoiding pixel snap for the earlier stated reasons.

    I could get a rock solid display of pixel data this way at e.g. 1920x1080, at least most of the time, but as soon as the resolution changes, with the same sprite geometry size and texture data, you're practically guaranteed to see artifacts. You just can't expect to use the same texture data at a non 1:1 ratio ie at a higher or lower resolution. Any mismatch between the texture grid and pixel grid is going to present a problem. You really ideally need a custom set of sprite texture data for every resolution, hand-adjusted to look exactly how you want it, and even then that WILL mean that certain pixel-level features will differ slightly and it might be noticeable or change the character of the art.

    I really wish also it was easy to have unity NOT internally upscale non-power-of-2 texture data to power-of-2. I know it helps with speed and compatibility but this is 2016... it just introduces more blurring and other issues, and is a total no-deal if your pixel data is 'data' and not colors.
     
  20. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Well the other brothers (and some other retro titles I did for clients) came out years ago, and I have not had a single complaint or review about funny pixels. They all universally say the graphics are great. That is because the art is great. I was aware of all and any pixel problems of course but chose to completely ignore it, suspecting gamers really, really don't care (they don't care).

    Also means I can zoom.

    I think what the real solution here is, is to not care but instead apply retro antialiasing which is on asset store / in a thread someplace. That smooths out all the problems.

    All this drama is really developer centric. It's a magnifying glass operated by the developer obsessing over what they decide are important flaws.
     
    theANMATOR2b likes this.
  21. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    You're right, once objects are in motion or there's a lot going on or engagement or whatever you kind of gloss over the little issues and start to actually process what you're looking at. The only other bigger gripe for me besides per-pixel issues is in terms of ghosting on modern flatscreen displays, which is horrendous for any fast-moving 2d action game where the pixel latency is just so slow its a crime. Even apple devices have this issue, like playing robot unicorn attack on an ipad or iphone... bluuuuur.
     
  22. Douvantzis

    Douvantzis

    Joined:
    Mar 21, 2016
    Posts:
    79
    Actually the problem you describe is not because of the response time (which causes ghosting) but because of the LCSs sample and hold rendering. Even if LCD screens had the lowest possible response time, the human eye would still see blurry movement. LCD screens with LED strobing (low persistence) solve this problem. That's why even OLEDs can appear blurry. You can read more about it here.
     
  23. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    I've seen people watch 4:3 videos stretched to fullscreen on 16:9 TVs with zero S***s given, even though the correct aspect ratio was just a click of button away. So, you're probably right about gamers not caring.

    I had a thread bookmarked that I wanted to reply to, but I'd rather cross quote than necro:
    http://forum.unity3d.com/threads/is...h-more-difficult-than-3d.392529/#post-2561992
    It makes me really sad to hear that this was your experience, because you've given some of the best advice I've ever gotten on this forum. I totally understand how you must feel. I remember when my cousin asked for a recommendation on which monitor to buy. I did 2 hours of deep research on the most comprehensive monitor review site that I know, and gave my recommendation. A while later I learned that he just went to the store and bought one they had in stock anyway. Naturally it's not the only time something like that happened to me.

    I stumbled upon the thread I linked when I was already looking into doing a 2D side project. I have to agree, 3D did throw me a lot of curveballs, that I did not see coming. I hope 2D will be a little more straight forward.

    Regarding the pixel perfectness I'm still experimenting. My not-yet-implemented-and-put-to-the-test approach would be rendering to a pointfiltered rendertexture at 1/3rd of 1080p resolution, making all textures/sprites correspond 1:1 from sprite size to render pixel size, applying image effects at that resolution and then just upscaling it to final screen resolution with a second camera. I intend to try to decouple the sprite renderer positions from the logical object positions and "snap" them to the pixel grid with scripts. Same could be done for the camera, but that might possibly end up being static anyway.
    I remember you saying to expect people to run 2D games at different resolutions and I was worried a bit how I could make that work without weird stretching in places, but when you say players don't care anyway about pixel errors that's a comforting thought.
    I just wanted to thank you for all the knowledge you share, and let you know that even if the person you directly gave advice to ignores it, there's a good chance that later there are many others finding your posts while looking for related topics, and taking your advice to heart without necroing the thread to mention it.

    And some pew pew pew for good measure.
     
    theANMATOR2b and hippocoder like this.