OpenGL & 2D

SO i've been reading a few tutorials on OpenGL. I want to learn it to render some basic 2D stuff. The problem is all the different coordinate spaces are confusing me. object space, view space, screen space, world space, eye space, clip space. I have a feeling that most of these don't matter for 2D rendering.

I guess my question is, how do I tell OpenGL to render something at a specific pixel offset in the window? From what I gather I have to convert the window coordinates to normalized device coordinates and give it to the fragment shader. How do I make a window coordinate, say 300,300, into a normalized device coordinate in the range -1,1?
The ultimate goal is NDC space (normalized device coordinate space).

Y axis: -1 is bottom of screen, +1 is top
X axis: -1 is left side of screen, +1 is right

If you want an ortho view (no "depth" -- which is fine for 2D) then you don't have to care about Z or W. Just have Z=0 and W=1 for all your vertexes.


NDC space is then scaled to your screen res by OpenGL. So if your screen is 800x600... then X=-1 becomes X=0... and X=+1 becomes X=800. Etc.


If you don't care about full matrix calculations... this means you have to do 2 things.

#1 You have to offset your vetexes based on where the "camera" is.
#2 You have to "translate" your pixel coordinates to NDC coordinates.


#1 is up to you how you want to do it. Assuming you have a camera X,Y position... it might be as simple as this:

 
finalposition = vertex - camera;



#2 is just a matter of scaling [0,windowsize.X] to [-1,+1]

 
scale = (1.0 / (windowsize * 0.5)) - 1.0;


So it ends up being:

 
finalposition = scale * (input_vertex - camera);



EDIT:

note that this will make (0,0) the bottom left corner of your screen and not the top-left like you might be used to.

Also note that using the camera value directly like this is not the best approach because if you have large worlds, you start seeing floating point rounding errors.
Last edited on
Thanks alot. That is exactly what I wanted to know. One more question though. In windows it appears I have to access modern OpenGL by using extensions. Most functions just aren't available until I use wglGetProcAddress. Do you happen to know if there is another way to use the core profile by default, or am I stuck using GLEW?

Also, could you please explain this:

scale = (1.0 / (windowsize * 0.5)) - 1.0;

If I do scale * X(window coord) it is way outside the range of -1,1. So what is that achieving?
Last edited on
Most functions just aren't available until I use wglGetProcAddress. Do you happen to know if there is another way to use the core profile by default, or am I stuck using GLEW?


I use glload which is a lib that's part of the unofficial SDK. It basically redefines all the functions as macros/function pointers and loads them at runtime.

Just a single call to glload::LoadFunctions(); at startup and then you can use any and all gl functions normally.


If I do scale * X(window coord) it is way outside the range of -1,1. So what is that achieving?


Whoops, apparently I screwed that formula up.

The formula works for scaling back [0,screenres] coords down to [-1,+1] coords, but it doesn't work as a multipliable 'scale' value. The - 1.0 is what throws it off there.

So it'd actually be this:

1
2
3
scale = 1.0 / (windowsize * 0.5);
//...
finalposition = scale * (input_vertex - camera) - 1.0;


if windowsize.x is equal to 800... then this puts scale at 1/400

so then the final position would be this:

1
2
3
4
5
6
7
8
9
10
   (assuming 'camera' is 0)
finalposition = scale * (input) - 1.0

   (assuming 'scale' is 1/400)
finalposition = input/400 - 1.0


input=0  :    0/400 - 1.0   =    -1      (left side of screen)
input=400:  400/400 - 1.0   =     0      (center side of screen)
input=800:  800/400 - 1.0   =     1      (right side of screen)
Thanks again, you have been most helpful!
Topic archived. No new replies allowed.