3
votes

I'm trying to figure out how to draw graphics in XNA, and someone else suggested this. But before I attempt to use this...

If I create and use this camera, and set LEFT,TOP to 0 and WIDTH=256 and HEIGHT=240, anything I render to the screen will use these coordinates? So a box with a width and height of 1, if set to 0,0 will take up space from 0,0 to 1,1?

1

1 Answers

15
votes

The function you are referring to is: Matrix.CreateOrthographicOffCenter(left, right, bottom, top, zNearPlane, zFarPlane).

This returns a projection matrix that can be used to transform a point in world space to a point in projection space.

Projection space goes from (-1,-1) in the bottom left corner of the viewport to (1,1) in the top right corner. This is the coordinate space that the GPU actually works in when rasterising.

World space is whatever you want it to be.

So let's say you create a matrix with Matrix.CreateOrthographicOffCenter(0, 256, 240, 0, -10, 10), and you used that matrix as your projection matrix with BasicEffect to draw a model of a cube. Let's say the model of the cube is centered at the origin and is of size 1 (length, width and height).

As well as basicEffect.Projection, you would set basicEffect.View = Matrix.Identity (because we don't want an additional camera transformation) and basicEffect.World = Matrix.CreateTranslation(0.5f, 0.5f, 0) to translate your model so that it exists from (0,0) to (1,1) in world space. Then draw your model using that BasicEffect.

The top face of your cube (orthographic projection means that there is no perspective) will be drawn at the top left corner of the viewport. It will take up 1/256th of the width and 1/240th of the height of the viewport (see also GraphicsDevice.Viewport).

(PS: I can't remember how backface culling is affected by this kind of projection. If you see nothing try turning it off or switching the winding order.)


Now, this being said - I get a sense from your other questions (and the fact you want to make an orthographic matrix) that you want to do 2D sprite work. BasicEffect is designed primarily for doing 3D work (although if you make your own vertex shader, not recommended for sprites, you will need a projection matrix).

You probably want to use XNA's SpriteBatch - not least of all because it's heavily optimised for drawing sprites. SpriteBatch.Begin will take a Matrix transformMatrix as an argument. This is equivalent to the World and View matrix, above, not the Projection matrix.

SpriteBatch assumes your world space is the same as client space (top left is (0,0), width and height are the size of the viewport) and handles the projection for you. (Actually it is more advanced than this - it will apply an offset for you so that sprite pixels line up with screen pixels.)

If you want to draw sprites so that world appears 256 units wide and 240 units high in the viewport, you could pass a matrix like this to SpriteBatch.Begin:

Matrix.CreateScale(viewport.Width / 256f, viewport.Height / 240f, 1f)

It is worth noting that in the new XNA 4.0 you can use SpriteBatch to draw with custom vertex shaders and so you may use arbitrary world-view-project matrices.