Almost two years ago now I was working on a short ebook XNA 3D Primer (now in Kindle flavor). A year after the book came out XNA 4.0 was released, and breaks all of the examples in the book. The examples have always been free to download without getting the book, so I have updated all the examples to with with XNA 4.0. You can get the updated examples on my Google Code site.
In moving the code from 3.1 to 4.0, the following changes were made:
- Removed many Begin/End calls, as XAN 4.0 only needs Apply called for an Effect
- Removed Vertex Declarations, as these are not needed in 4.0
- Removed the custom shader and replaced it with the SkinnedEffect that comes with 4.0
- Setup a Game Library project to share a single content project across all examples
- Changed the method of creating the shadow
Some explanation on that last one. In the original book I add some shadows to a simple 3D object created from a triangle strip. The shadows are there to provide a visual reference so you can see the camera in action. To create the shadow I use the Matrix.CreateShadow method, followed by the BasicEffect default lighting to color the object black. In 3.1 this worked, but in 4.0 this will throw an error "The current vertex declaration does not include all the elements required by the current vertex shader. Normal0 is missing."
What’s going on: When you calculate the effect of light on a vertex you need a normal to know which way the light should reflect off the vertex (the angles between the light, vertex, and normal provide this information). In the example however, no normal are provided. I had expected XNA to assume the vertex was also the normal (or can be calculated by normalizing the vertex) and this is why the model is centered at 0,0,0. This expectation partly came from the fact the polygon surface normals have a magic default as well, based upon the order of the vertices that make up the polygon.
It turns out this is not the case, as Shawn Hargreaves points out. XNA was passing the data down to the graphics drivers without change. The graphics drivers were then adding in the expected normals (and this must be pretty common as both nVidia and ATI cards I ran the example on behaved as expected). This isn’t a good thing however, as it means things could break on one system and be fine on another, so in 4.0 an error is thrown.
I really don’t want to discuss all this at the point in the book I use shadows. The truth is in any 3D game more advanced than an example, you will be using 3D modules and the 3D modeling software will take care of all of this. It’s useful information to know, but it’s more advanced than I wanted to cover in the book. So instead of using lighting to color the model black, I just create a second object and set all the color values to black to achieve the same effect. (A second reason for this approach is XNA 4.0 does not have a VertexPositionColorNormal, and creating you own vertex data format is really beyond the scope of the second example in the book!).
The purpose of the the XNA 3D Primer was to cover 3D concepts for someone just getting started. It’s really a list of things I had to learn. When I first started, I didn’t know enough about 3D to even know how to ask a question (without being the "why does my model look wrong" guy). I’ve now created a second example with a similar purpose. This example is a complete 2D game, small yet big enough to give an idea how the pieces of a game come together in XNA.
The game is XNA Invaders From Space, and is a simple clone of the classic Space Invaders. The code for this game is also available on my Google Code site. The code is fairly fresh, so I’m still tweaking it as I present it to various groups, but soon I hope to create a written and video tutorial around the code.
Both the XNA 3D Primer and XNA Invaders from Space will be used for my sessions at DevLINK 2011. DevLINK is being held August 17-19th in Chattanooga, Tennessee. If you’re going (and it’s a great conference) be sure to make time for some of the XNA sessions by myself, Chris Gardner, and Chris Williams.