2D Rendering - 1 - Normalised Device Coordinates
Normalised Device Coordinates
If you are anything like me, you are probably used to rendering to a screen which has a standard resolution, such as 720p
(1280px x 720px), where the origin (0,0)
is at the top left-hand corner and x
increases towards the right and y
increases towards the bottom of the screen. Well, hold onto your hats, as this is one of first differences you will most likely encounter during your transition from XNA to libGDX.
OpenGL uses Normalised Device Coordinates
(NDC) to allow it to address any screen, whatever its size, shape or resolution. The image below depicts NDC:
As you can see, the extents of both the x
and y
axes range from -1
to 1
, with zero in the middle.
NDC maintains these extents, regardless of the size, shape or resolution of the screen that is being rendered to, as shown by the images below:
If you think about it, the last two images reflect exactly what happens when you rotate a smart phone to change the view from landscape to portrait and vice versa.
Plotting a Triangle
To plot a triangle in the middle of our screen, we could use the following coordinates:
- (0, 0.5)
- (-0.5, -0.5)
- (0.5, -0.5)
If we join the dots, we would get something like:
“What’s with the triangle? I only want to know about drawing sprites!” I hear you say. Well, triangles play an extremely important part within OpenGL (as they do in DirectX), so I’ll be harping on about them for a while yet! Bare with me, as future tutorials will reveal that there is method to my madness.
Show/Hide juicy details
These sections are entirely optional. Read them if you want to know more details than is actually necessary to follow my tutorials.
Below is an image, which represents a 720p screen. I thought that it would be good to cover ways that we could map XNA-style pixel coordinates to NDC and vice versa.
So, if we compare the positions that I have marked on the image, you should see that we have the following mappings:
- (0,0) => (-1,1)
- (0,719) => (-1,-1)
- (1279,0) => (1,1)
- (1279,719) => (1,-1)
- (639,359) => (0,0)
Google led me to the following formulas for converting NDC positions to pixel positions:
For example, if we take a NDC x coordinate of 1, we would expect the result of plugging it into the appropriate formula to be 1279. So, let’s give it a go:
Hurrah, it worked! You can now sleep safely at night knowing this information.
So, what about going from a window coordinate to a NDC coordinate? Well, Google failed me on that one, but we can use some algebra to rearrange the formulas above:
and, without going through all of that rigmarole again, we can work out the formula for the y coordinates, by using our Noggins:
Now to test this fancy formula! If we take a window x coordinate of 1279, we would expect the result of plugging it into the appropriate formula to be 1. So, let’s give it a go:
Cor blimey guvnor, it worked! Throw those comfort blankets out with the trash…
Right, back to being serious again. Please don’t get hung up on any of the information given above. You will not need to remember any of this, or any the Math that I have used. OpenGL will be performing all of the calculations for you, using something called a Projection Matrix. More on that soon 😉
Coming up next…
I think we are about ready to start writing some code to make use of those pesky NDCs!
JK