Before we get into too much more detail,
let's see what is involved in setting up a simple project that uses the
new rendering approach. Some of the code that we will work through here
will be unfamiliar and we will gloss over some of it for the time being
just so that we can get some code running.
1. Setting Up the Environment
We start off by creating a new XNA project, exactly
as we have always done. For simplicity, we will work in isolation of
the game framework at the moment, so don't worry about adding a
reference to it or changing the game class derivation; it can continue
to derive from Microsoft.Xna.Framework.Game for this example.
We need to add some class-level variables to the
game class to manage the scene that we wish to render. The required
declarations are shown in Listing 1.
Example 1. Variables required for the scene to be rendered
private BasicEffect _effect; private VertexPositionColor[] _vertices = new VertexPositionColor[4];
|
Next we need to set up these variables ready for them to be used by XNA. The code required for this is added to the Initialize function.
The first thing we do here is set up the projection matrix.
As you can see in Listing 2,
the screen's aspect ratio is determined by dividing the viewport width
by its height, and this ratio is one of the values used to initialize
the matrix. This ensures that objects remain square when drawn on the
screen.
Example 2. The beginning of the Initialize function, creating the projection matrix
protected override void Initialize() { // Calculate the screen aspect ratio float aspectRatio = (float)GraphicsDevice.Viewport.Width / GraphicsDevice.Viewport.Height; // Create a projection matrix Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), aspectRatio, 0.1f, 1000.0f);
|
Note how the matrix is being initialized by calling one of the shared methods of the Matrix structure. There are dozens of such methods that allow us to create all kinds of matrices, as you will see as we progress.
The next step is to create the view matrix.
This can be likened to a camera within the scene, and controls which
objects rendered are visible and where they appear on the screen. Our
example project's view matrix is created as shown in Listing 3. Once again, this will be discussed in more detail later.
Example 3. Initializing the view matrix
// Calculate a view matrix (where we are looking from and to) Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 10), Vector3.Zero, Vector3.Up);
|
Now we need to create an effect
object to tell XNA how it should render our graphics to the screen. All
rendering needs an effect of some kind, and several are provided for
the Windows Phone 7 implementation of XNA.
The effect object is passed a reference to our
graphics device when it is instantiated, and we then set a series of
properties to control how it will behave. Listing 4
shows the creation and initialization of the effect object. Note that
among the values passed are the projection and view matrices that we
have just constructed.
Example 4. Creating and initializing the effect object
_effect = new BasicEffect(GraphicsDevice); _effect.LightingEnabled = false; _effect.TextureEnabled = false; _effect.VertexColorEnabled = true; _effect.Projection = projection; _effect.View = view; _effect.World = Matrix.Identity;
|
The environment is now fully initialized. We don't
yet have anything to draw, however, so we need to take care of this
before we can render anything.
As mentioned earlier, XNA expects us to define our
objects using vertices. It can then use them to construct the solid
triangles that form the graphics we see on the screen.
Vertices can hold various pieces of information.
They will always hold a position, but in addition to that they might
contain color information, texture information, and other data that
affects the way they are drawn. XNA provides some built-in
configurations for common vertex structures, and the one we will use
here is called VertexPositionColor. As its name implies, it stores position and color information, and nothing more.
We will get our example to draw a simple square on
the screen. To tell XNA about the square, we must set up an array of
vertex objects, telling it the position and color of each. Figure 2
shows the vertices that we will be using to form this square. The
coordinate (0, 0, 0) is right in the middle of the square, and it
extends 2 units across the x and y axes (from - 1 to 1 on each axis).
Note that the z coordinate is left at 0 for all the vertices so that
the square remains flat.
The vertices are constructed within the program code by setting their coordinates into the _vertices array that we declared back in Listing 1. The code is shown in Listing 5.
Example 5. Setting the vertex positions to form a square
_vertices[0].Position = new Vector3(-1, −1, 0); _vertices[1].Position = new Vector3(-1, 1, 0); _vertices[2].Position = new Vector3(1, −1, 0); _vertices[3].Position = new Vector3(1, 1, 0);
|
Just as we used Vector2 structures for providing positions for sprites, so we now use Vector3 structures to declare positions in three-dimensional space.
The final part of our initialization is to provide a
color for each vertex. This will produce an attractive effect when it
is rendered—and also one that we could not easily achieve using sprites
without having to generate a texture containing the different colors.
The remaining vertex initialization, and the conclusion of the
Initialize function, is shown in Listing 6.
Example 6. Setting the vertex colors
_vertices[0].Color = Color.Red; _vertices[1].Color = Color.White; _vertices[2].Color = Color.Blue; _vertices[3].Color = Color.Green;
base.Initialize(); }
|