# OpenGL ES, orthographic projection and viewport

I want to make some simple 2D game on iOS to familiarize myself with OpenGL ES. I started with Ray Wenderlich’s tutorial (How To Create A Simple 2D iPhone Game with OpenGL ES 2.0 and GLKit). That tutorial is quite good, but I miss some parts of a puzzle.

Ray creates an orthographic projection using some magic numbers like 480 and 320. It is not clear to me why he took these numbers, and as far as I can see - sprites are not mapped to the iPad simulator screen one-to-one pixel. I tried to play with parameters with which the ortho matrix is created, but I cannot figure out the maths in here.

How can I calculate numbers (bottom, top, left, right, close, far) which will be parameters to the orthographic projection matrix creation and have the sprite on the screen shown in its original size?

I did a lot of experimentation with this as well. When I first learned OpenGL I also wanted pixel for pixel relationships between the graphics I create in photoshop and my placement of those on the screen. For some games you will want exactly that. I'm not classically trained in OpenGL. Instead I taught myself. So I don't know if it's normal or kosher or whatever. And I guess I don't care.

But because all OpenGL variable have a precision hint, it's actually better not to use the actual pixel values. Instead use math. Also, keep in mind that at least for another year or so we might want to support non-retina devices. So those don't have the same number of pixels. But you don't want your game to have to be coded for multiple screen resolutions. And OpenGL can do a very decent job of resizing your graphics, although it does come at a speed price.

My suggestion is to pick a scale factor for your units. 1 unit = 10 pixels or 1 unit = 100 pixels. In my games, I've chosen 1 unit = 20 retina pixels at a specific depth.

Another tip.. don't do orthographic. Go ahead and do a perspective view. Why? This will give you the opportunity to move things in Z space if/when you want to. You're just going to place your objects at a z depth that has pixel for pixel "unity" (not to be confused with the 3d game engine).

If you do use ortho though you can use this frustum:

int frustumScale = 400;

if (retina) {
frustumScale = 800;
}

matrixFrustum(-(float)backingWidth/frustumScale,(float)backingWidth/frustumScale,
-(float)backingHeight/frustumScale, (float)backingHeight/frustumScale, 40, 1000, frustProjection);


Where frustumScale is 800 for a retina screen and 400 for a non-retina screen. Then at a distance of 800 from camera (-800) the sprite is pixel for pixel the same as photoshop.

Check out this question and my answer here: In 3D camera math, calculate what Z depth is pixel unity for a given FOV

Note.. I don't use glKit. I didn't want to learn an apple specific way of doing OpenGL. Instead I wrote my own math library and engine. But the basics are probably the same in glKit.

• You can use z-sorting with an ortographic projection matrix too, no need for perspective. Commented Jan 31, 2016 at 18:25
• I'm not saying z sorting. I'm saying moving things in z space towards the camera. I do this in one of my games and it looks cool. Commented Jan 31, 2016 at 18:28
• Oh, so like one of those effects, where the background moves slower than the foreground? Commented Jan 31, 2016 at 18:31
• That's called the vertigo effect as it was popularized by that movie. No. This is just having the ability to have a pixel for pixel plane in a 3d space. But then to be able to fly objects down on to it from camera. Commented Jan 31, 2016 at 18:57

In general i don't think you will ever need to fiddle with the values inside a matrix unless you are writing a math library. So for this you should take a function that creates and orthographic projection and works (or take a math library that has everything)

The orthographic projection is like a box has two main components width and height (your magic numbers i think) and those represent the size of the view frustrum(or box in case of orthographic) in world space. That's why if you have fixed values there the picture will be the same on all screen sizes, but it will be of a different resolution because the content that fits in 480x320 units (inside your world) gets projected on a bigger/smaller surface.

So now to make rendered content size(in pixels) match the screen size you must first know how big is your world and how many pixels you are fitting inside a unit. For this i will take you are rendering one sprite with 1024x1024 pixels over 2 world units. For a device that has the resolution 1024x768 the size of the view projection will be: (2 / 1024,2 / 768)

He too those numbers, because of the same reason some people uses 800 * 600 for computers. It is one of the smallest screen size wich can be found on the market. It's just easier to handle, than something like 1600 * 900.