Displaying exact pixels with SpriteManager

Any recommendations on how to display sprites with SpriteManager so that the sprite pixels correspond exactly with the screen pixels?

I’m making a 2D game in which the orthographic camera never moves, so right now I’m just calculating the approximate world size for a sprite so that it looks about right. However it’s a little blurry because it’s not the perfect size. How are other people doing this? Thanks!

set the orthographic size to 160 and put it in position 0, 0, -160

Then you have a full 1:1 pixel - 3d size/coord relation

1 Like

Legend.

Also, if your sprites are going to scale at all, they can still become blurry if you are using mip mapping. There are tradeoffs to using mipmaps, but you may want to try disabling mipmaps in your import settings for that texture. Also, if your sprites will ALWAYS display 1:1, pixel for pixel, then you should be able to safely turn off mipmapping. It will save you memory since you don’t have all those extra versions of the texture.

Dary.

dreamora – this isn’t working for me. I put the camera at 0,0,-160 like you said. Ortho size is 160. But when I place assets in the scene, the range of values for the Y coordinate is from 0 to 1 (i.e. .5 is at the midpoint). Similar for the X coordinate, although .5 is past the middle (it’s a portrait orientation game).

Am I doing this wrong? It would be fantastic to have the X and Y coordinates match the actual pixel coordinates of the display.

OK here is the generalized formula one for portrait and landscape:

Ortographic size: Screen Height / 2 (-> 160 or 240)
Camera z: -ortographic size (-> -160 or -240)
All objects are placed in z = 0 plane

(alternatively cam is at z = 0 and all objects are placed at z = ortographic size)

Thats it

The 0,0 position of the coordinate system is in the middle of the screen with positive directions to right and up

Actually, the depth (z position) of the camera and your objects is irrelevant in orthographic projection (unless your objects are beyond clipping). The critical settings are:

orthographicSize → “half of the vertical size of the viewing volume”

camera position → just center it on the x-y plane; x:240 y:160 (landscape) or x:160 y:240 (portrait)

That should give you a 1:1 pixel:texel relationship and a 1 unit → 1 pixel coordinate system with +z looking into the scene (“back” in scene view). So, move your camera into the -z direction, and your objects toward the +z to place them in front of the camera.

NOTE: The SpriteManager puts itself (and thereby your mesh and sprite depth) at the origin in Awake by default; in my game, I changed this so that it leaves the z-position alone so that you don’t get sorting problems with multiple SpriteManagers at different depths.

I’ve gone ahead and attached an example. If you want the origin at the center instead of low-left, just put the camera at (0,0,z)

171455–6171–$testortho_212.zip (522 KB)

Thanks to you both. I’m still not getting that result.

The background sprite is at (0,0,-1). The bird sprite in this screenshot is at (.5,.88,0). I tried the camera at (0,0,0), (0,0,-240) and (160,240,-240).

Ah, I thought you were using SpriteManager!

GUITextures are placed from 0.0 to 1.0 by definition (so the layout of GUITextures is maintained over multiple resolutions)

If you want pixel-exact placement of a GUITexture, put the position at 0,0,z and use the pixel inset x y values exclusively.

The z value is used for inter-GUITexture depth.

Incidentally, you will not be able to parent GUITextures as you would with normal GameObjects due to their special transformations. But why don’t you use SpriteManager for all of your sprites? Each GUITexture generates its own quad, resulting in its own draw call. SpriteManager maintains a single discontinuous mesh for all your sprites, generating only one draw call for potentially hundreds of sprites.

If all black is non rendered then you didn’t choose iphone tall as screen, as the aspect ratio is incorrect. In that case the sprite manager positioning will be affected.

But I just realized that I forgot a small part of the setup that affects the positiooning

The x position that you throw in needs to be multiplied by 0.75f (in landscape) or height / width, to handle the aspect ratio correctly.

Here is an example of that, a scrolling background class using the spritemanager:

using UnityEngine;
using System.Collections;

public class ScrollingBackground : MonoBehaviour 
{
	public SpriteManager spriteMan;
	public GameObject handle;
	public Vector2 scrollSpeed;
	public Vector2 size;
	public Vector2 position;
	public float depth;
	
	private GameObject scroller;
	private Sprite s;

	// Use this for initialization
	void Start () 
	{
		Vector2 lowerLeft = new Vector2(0,1);
		Vector2 imageSize = new Vector2(1,1);
		scroller = (GameObject)Instantiate(handle, new Vector3( position.x * 0.75f, position.y - 100, depth ), Quaternion.identity);
		s = spriteMan.AddSprite(scroller, // The game object to associate the sprite to
								size.x, 		// The width of the sprite
								size.y, 		// The height of the sprite
								lowerLeft,
								imageSize,
								false);		// Billboarded?
		scrollSpeed = spriteMan.PixelSpaceToUVSpace(scrollSpeed);
	}
	
	void Update()
	{
		s.lowerLeftUV += scrollSpeed*Time.deltaTime;
		
		
	}

}

@dreamora

The black in the screenshot is simply the background color of the editor game panel. He, in fact, does have the viewport set correctly.

The aspect ratio of the view would not affect the coordinate system anyway; the offset you are referring to is simply camera position relative to the origin. If you check the SpriteManager example I uploaded above, you will see that the world units are 1:1 with the display pixels.

If you start multiplying position values of sprites by floats (as in your example), you will rarely get a 1:1 texel to pixel relationship due to rounding error; it is not a good idea if you are using sprites for the UI.

Also, if you look at his screenshot and the previous post, you will see that he is not using SpriteManager, but a GUITexture.

That is the reason he has positioning values from 0.0 - 1.0. This is because Unity is not an iphone-only engine and placement of UI elements often need to maintain their relative positioning for different screen resolutions.

If you want pixel-exact placement with a GUITexture, you simply place it at the origin and set the x y pixel insets to offset the GUITexture in pixels on the screen.

sorry to bump an old thread
i was wondering by setting the mesh plane, to a 1:1 like this, if i have a plane with a size of 1024 unit (that means 1024 meters right ?).

Is there gonna be a performance hitch because of a large scale object like this ?

thanks a lot in advance :smile:

No, there shouldn’t be since the “physical” size of the image, in terms of its worldspace extents could be 1x1 just as easily as 1024x1024 and it wouldn’t make any difference performance-wise.

Now I’ll try to keep this as clear as possible, but it’ll get a little technical, so bear with me. The only way for the “size” (in terms of its worldspace extents) to make a performance hit would be through increased fillrate use. That is, if you make the graphic bigger on the screen (meaning it actually occupies more area on the screen when rendered), it requires that more pixels be drawn each frame, and therefore you’re eating up fillrate. But the “size” of the sprite isn’t the only thing that determines how much screen area is occupied. That is also determined by your ortho size. So let’s say you have an ortho size of 1, then a sprite of size 1x1 would fill half the screen. If, on the other hand, you had an ortho size of 160, then a sprite of size 10x10 would fill a much, much smaller portion of the screen.

Now in the case of a 1024x1024, and assuming you have a 1:1 screen pixel-to world unit ratio, then your sprite of 1024x1024 will more than fill up the screen - in fact only 480x320 of it would be capable of being displayed at a time on the iPhone (the size of the iPhone’s display). Now that’s perfectly alright, just as long as you don’t have a lot of sprites like that filling the whole screen, forcing the iPhone to re-draw the entire screen area multiple times each frame.

But the size itself won’t cause any problem.

Oh, by the way, since this thread has been resurrected, I thought I’d mention that I’m working on a new Sprite system that will have a “pixel perfect” option you can select in the inspector that, if you are using an orthographic camera, will automatically calculate the sprite’s dimensions for you so that it displays 1:1, pixel-for-pixel.

You can read some preview info on it here:
http://www.anbsoft.com/middleware

Awesome Brady !!
thanks a lot for the detail explanation.
btw, looks like Sprite Manager 2 is gonna be a kickass addons 8)

I had a long fight with pixel perfection. I took the mipmaps off and no compression. Did all the correct stuff with ortho camera sizing being half the screen height and so on and so on. I also tried various “in the middle of the texel/pixel”-tryouts with no success.

Eventually it was down to one simple thing: Use only power of two textures.

(I’m using iphone basic 1.7)

edit: I’m not using spritemanager, just plain unity (very sorry for hijacking the thread)

First, is the issue that the sprite isn’t sized correctly, or are you just not getting the clarity you’re looking for?

If the former, you may simply be facing the Unity issue where it doesn’t provide the correct viewport size information in edit-mode. Just try clicking “Play” and then stop it immediately and it should be sized correctly. It should always appear the correct size at runtime (just make sure it isn’t scaled and that it has the correct render camera assigned).

If the latter, any generated atlas should already be a power-of-2. So the only time it might not be is if you’re using a Sprite component, supplying your own atlas.

I’m very sorry for hijacking the SpriteManager thread and stealing your time to reply me. I’m not actually using SM but just plain Unity.

The reason I posted, was that this is one of the threads that you stumble upon, when you google “unity pixel perfect”. I was pulling my hair trying to make it work, and would like to point out the power-of-2 thing to someone who was in similar position. I didn’t notice the thread was SM specific. Too much coffee I guess.

Yes, if you don’t use power-of-2 textures, Unity will give you somewhat “altered” results. :slight_smile: