Search code examples
androidscreenopengl-es-2.0screen-resolutionaspect-ratio

Android Screen Ratios


I'm using OpenGL ES 2.0 on Android and I and I initialise my display like so:

float ratio = (float) width / height;
Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);  //Using Orthographic as developing 2d

What I'm having trouble understanding is this:

Let's say my app is a 'fixed screen' game (like Pac-Man ie, no scrolling, just the whole game visible on the screen).

Now at the moment, if I draw a quad at -1 to +1 on both x and y I get something like this:

enter image description here

Obviously, this is because I am setting -ratio, ratio as seen above. So this is correct.

But am I supposed to use this as my 'whole' screen? With rather massive letterboxing on the left and right?

I want a rectangular display that is the whole height of the physical display (and as much of the width as possible), but this would mean drawing at less that -1 and more than +1, is this a problem?

I realise the option may be to use clipping if this was a scrolling game, but for this particular scenario I want the whole 'game board' on the screen and to be static (And to use as much of the available screen real estate as possible without 'stretching' thus causing elongation of my sprites).

As I like to work with 0,0 as the top of the screen, basically what I do is pass my draw method something like so:

quad1.drawQuad (10,0);

When the drawQuad method get's this, it basically takes the range from left to right as expressed my openGL and divide the the screen width (so, in my case -1.7 through +1.7 so 3.4/2560 = 0.001328125). And say I specify 10 as my X (as above), it will say something like:

-1.7 + (10*0.001328125) = -1.68671875

It then plots the quad at -1.68671875.

Doing this I am able to work with normal co-ords (and I just subtract rather than add for y axis so I can have 0 at the top).

Is this a good way to do things?

Because with this method, at the moment, if I specify a 100,100 square, it isn't a square, it's rectangle. However, on the plus side, I can fill the whole physical screen by scaling the quad by width x height.


Solution

  • You are drawing a 1x1 quad, so that is why you see a 1x1 quad. Try translating the quad 0.25 to the right or left and you will see that you can draw in that space too.

    In graphics, you create an object, like a quad, in your case you made it 1x1. Then you position it wherever you want. If you do not position it, then it will be at the origin, which is what you see.

    If you draw a wider shape, you will also see you can draw outside this area on the screen.

    By the way, with your ortho matrix function, you aren't just specifying the screen aspect ratio, you are also specifying the coordinate unit size you have to work with. This is why a 1x1 is filling the height the of the screen, because your upper and lower boundaries are set to 1 and -1. Your ratio is a little more than one, since your width is longer than your height, so your left and right boundaries are essentially something like -1.5 and 1.5 (whatever your ratio happens to be).

    But you can also do something like this;

    Matrix.orthoM(mProjMatrix, 0, -width/2, width/2, -height/2, height/2, 3, 7);

    Here, your ratio is the same, but you are sending it to your ortho projection with screen coordinates. (Disclaimer: I don't use the same math library you do, but these appears to be a conventional ortho matrix function based on the arguments you are passing to it).

    So lets say you have a 1000x500 pixel resolution. In OpenGL your origin of 0,0 is in the middle. So now your left edge is at (-500,y), right edge at (500,y) and your top is (x,250). So if you draw your 1x1 quad, it will be very tiny, but if you draw a 250x250 square, it will look like your 1x1 quad in your previous ortho projection.

    So you can specify the coordinates you want, the ratio, the unit size, etc for how you want to work. Personally, I dont't like specifying coordinates as fractions between 0 and 1, I like to think about them in the same sense as the screen pixels.

    But whether or not you choose to do this, hopefully you understand what you are actually passing to these matrix functions.

    One of the best ways to learn is draw an object to the screen and just play around with different numbers you send to your modelview and projection matrices so you can see what it is they are actually doing.