2D Graphics? What’s that?

dctrDon’t forget to buy Design, Code, Test, Repeat.  It’s a fun, funny, and helpful read.

I don’t see a great need to go into too much background on 2D graphics, because the implementation in hardware frame buffers and display is not of interest to most programmers.  What is interesting when you have to do some programming is your point of view and other things that you can control easily from a software standpoint.

When you’re writing code for 2D graphics, you’re usually starting with a library or graphics environment, C#, Java, OpenGL and C++, DirectX and C++, etc.  I’m going to further limit this discussion to the C#, Java, and other environment where your drawing area starts with y=0 in the upper left hand corner with y increasing as you go down the screen.  I’ve seen too many novice programmers try to get some real graphics code written without even a hint of where to go.  I’m going to keep things somewhat esoteric for this post and start with some basic concepts that might help you if you need to develop some graphics code for a particular application.

Starting with y=0 in the upper left corner is great for text applications when you want to fill the screen and add scroll bars, but for graphs and drawings it stinks.  Wouldn’t it be more convenient to have y going up, like you learned in grade school?  What about having the origin in the middle of the screen rather than a corner, so you could have negative coordinates handled naturally?  The way to do this is NOT by hacking together a bunch of offsets and monkeying with them until the picture looks good (I learned this the hard way a long time ago).  The proper and ultimately easier way is to use simple transformations to do the job.  The main way to do this is by using a window to viewport transformation.  The idea is to take your world (the stuff you want to see), look at some or all of it (like looking out of a window at the world) and putting that onto a screen (or window on your computer), which we call the viewport.  The viewport is normally defined in normalized device coordinates (referred to as NDC, they go from 0 to 1, rather than 0 to 500, or whatever your viewport size really is).  The NDC are then scaled easily to match your actual viewport size.  There’s a simple transformation that accomplishes this and there’s a reasonable explanation here: windows to viewport.  The one thing you’ll need to add is to negate the y coordinate to make y go up instead of down.

To make your entire world visible in the viewport, you simply increase the size of your window (not the computer window, the window into your world) to the size of the stuff that’s in your world.  The transformation, then reduces this to the computer’s viewport and you see everything.  If you want to zoom in, you make the window smaller.  To see other parts of your world when you zoom in, you move the window to the right, left, up, or down.  Graphics programs usually use pan and zoom tools to accomplish these actions.

I’ll add just a couple more handy concepts to help get you started on the right foot.  Most programs are best off having a set of entities stored in memory.  I know, you’re thinking, “duh”, but I’ve seen people read files from disk on every display update and it’s not pretty.  Having a set of entities in memory allows you to quickly loop through them and display them all.  Additionally, you can calculate a bounding box for all of the entities so that you can set the window to zoom to the extents of your world.

There are some other concepts, such as clipping and selection that can come in handy, but that’s for another day and for them most part, clipping is handled automatically by the graphics engine you’re using.  Selection is also handled by some engines, too, and if not, it’s easy to implement.

If there are any concepts that you’d like more detail on, let me know by sending me an email: bill at wandercoding.com.