After reading and going through the code in "Learning XNA 4.0" by Aaron Reed, I created a few minor test programs to play with some basic rendering techniques while learning more of the XNA framework. In each of these programs, I used simple models to test against (cubes, spheres, and a curved surface in one case).
The first of the rendering techniques was doing per-pixel lighting manually instead of using BasicEffect's PerferPerPixelLighting property. The development of this program was straight forward and there wasn't anything of note.
After that I went onto normal mapping. There are plenty of tutorials online for normal mapping, so I'm not going to go into the details of the algorithm. The only hang up I had in this program was getting the binormal and tangent. There are also plenty of tutorials online on how to compute those. But, in XNA it turns out you don't need to do so manually. I didn't see this mentioned in the various references on normal mapping, so thought I'd mention this little detail here. After you add the model to your content project, expand the "Content Processor" property for that model and set "Generate Tangent Frames" to "True". This way the XNA framework's model processor takes care of computing the binormal and tangent which will then be available to your shaders. This was just a lesson in explore your tools.
I found "Learning XNA 4.0" by Aaron Reed to be a good introduction to XNA. However, I also think the main thing it is lacking is that it does not cover the content pipeline. While it covers a large variety of topics in XNA and provides good detail, the content pipeline is a big part of using XNA beyond the BasicEffect rendering mechanism. Even to use XNA's SkinnedEffect renderer, a custom model processor is needed. Luckily, Microsoft's App Hub has the Skinned Model example that covers creating the relevant model processor. From analyzing it, I think it's a good example to learn from. It shows some additional classes/structs to help with loading, and shows that an additional library is needed to actually allow the serialized data to accessible to the content pipeline and the game at runtime.
For the purposes of playing with skeletal animation, I also wrote my own vertex and pixel shaders for rendering an animated test model that was just basically 3 joined cubes with 3 bones. To help with debugging both the computation of the bone matrices and the shaders, I switched the program between using the custom shaders and XNA's SkinnedEffect renderer. In the course of debugging the program, I was surprised to find out that the content pipeline automatically took care of interpolating the keyframes. The test model only had 2 keyframes in the fbx file, but after loading there were 104 keyframes.