Code Snippets in XNA

March 5th, 2007

Do you find yourself typing the same thing over and over again? Maybe it’s the code to draw an effect (begin, end and the pass loop) or maybe you keep having to resolving a render target to a texture. Wouldn’t it be nice if you didn’t have to type all that code every time?

Enter code snippets! Visual Studio has a nice feature that will insert small bits of code for you, even allowing you to specify different fields within that code. For example, the “prop” snippet will insert the following code for you:

private int myVar;

public int MyProperty
{
get { return myVar;}
set { myVar = value;}
}

It’ll let you specify the type of the variable “int”, the name of the variable “myVar” and the name of the property “MyProperty” just by tabbing between the fields too. Go ahead, try it – open Visual Studio and type “prop”, then press enter in the intellisense popup and then enter the values you want.

Using the prop code snippet.

I could easily change it to a Vector3 type variable called position with a property name of Position.

Editing the prop code snippet.

“That’s great,” you may say, “but it doesn’t help me set up my drawing code any faster.” Fortunately, that’s not entirely true. While there isn’t a “SetUpMyDrawingCode” code snippet, you can make one! Code snippets are just XML files that define the code to insert, the variables to allow the user to edit, and a few extra things about what namespaces might need to be included and who created the snippet. You just drop these in your “Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets” (probably in your My Documents directory) and then reload Visual Studio (or add them manually via Tools -> Code Snippets Manager).

There’s plenty of information on the internet on how to create your own code snippets. There’s a nice article written by Anand Kumar at dotnetjunkies that can walk you through creating a simple code snippet. You can find it here. I’d also suggest reading the Code Snippets Documentation on MSDN. It provides a lot more information about the little nuances that you might want to explore with more complex code snippets.

I’ve written some simple XNA code snippets and put them up for download here. You can install them by unzipping them to your “Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets” and then loading Visual Studio (and if they don’t load, add the folder manually using Tools -> Code Snippets Manager in Visual Studio). This includes the following snippets:

  • DrawEffect - Sets up the effect drawing code, including the “forall passes” loop.
  • PlatformVariable - Creates a platform-dependent variable, using the method discussed in my previous post on sharing code between platforms.
  • ResolveRenderTarget - Resolves the specified render target, stores its contents in a texture, and then sets an effect parameter to the value of that texture.
  • ThreadStarter – Sets up and starts a thread containing user-defined code.

I made these pretty quick, so they don’t contain the best code in the world and they’ll probably need some references resolved for proper use, but I hope they make a good starting point for you to make your own code snippets.

One word of advice: make sure you have an XML syntax validator. Incorrectly formatted snippets won’t load at all, and there’ll be no error message telling you what’s wrong. I personally use Notepad++ with the XML Tools plugin for all of my XML editing needs. It’ll even format my XML files for me so they look nice. Visual Studio has a pretty nice XML editor too though, so use whatever you’re comfortable with.

Post some of your own code snippets here to let me know what you come up with.

Building for Xbox 360 and Windows in one project

March 1st, 2007

This is (sort of) possible! It seems that the GSE team worked on implementing this feature for the 1.0 release, but had other priorities and weren’t able to complete it. Leaf came up with a project template that will allow you to build for multiple platforms (i.e. the Xbox 360 and Windows) in one project. You should have a good deal of experience with programming for both platforms before doing this though, as the feature isn’t officially supported, and you might run into problems that will be extremely difficult to diagnose. In other words, you’ll have problems with intellisense, references and more.

There is a forum thread on this topic on the XNA Forums in which Stephen Styrchak discusses why this wasn’t included as a feature in the first release of XNA GSE. Basically, there wasn’t enough time to properly implement it and they felt it was more of an advanced feature (i.e. they expected more beginners to be using XNA GSE, and didn’t want to cause them headaches).

The safest way to do this continues to be by adding your source files as links. To do this, set up your project for one platform, then add a new project for the other platform. Create a directory structure in the new project that mirrors the old project (e.g. if you have Effects, Resources and Classes directories in the first project, create those in the second project, with the same names). Then right click on the folder you want to copy the files to (or the project, if you want to copy to the base directory), and select “Add -> Existing Item.” Then, in the “Add Existing Item” dialog box, find the file you want to add. click on the file, then click the arrow by the “Add” button, and select “Add As Link.” This way, you’ll only have one copy of the file hanging around, and you won’t have to keep copying it every time you make a change.

Adding a file as a link

I’ve started a topic on Microsoft Connect about this issue. If you’d like to see this officially supported in the next version of XNA Game Studio Pro/Express, go vote on it here.

High-Performance Code on the Xbox 360

February 26th, 2007

C# is a really nice language – it takes care of a lot of the little things for you, letting you focus on the bigger issues in your program. However, it can’t do everything – and even things it will do, it won’t necessarily do well, or when you need them. Garbage collection is the classic example. It’s nice that you don’t have to keep track of your things and clean up after yourself. The garbage collector isn’t there to take care of you though, and it’s not going to make sure your code runs nicely.

This is especially important on the Xbox 360, where creating objects is costly. The .NET Compact Framework team put together a set of pages back in December that are a must-read for anyone writing high-performance code for the Xbox 360 using XNA. They cover floating point performance, manual inlining, making the most of the multiple cores and lots on garbage collection. Unfortunately they don’t cover graphics performance, though they do mention that XNA has pretty much direct access to the graphics hardware. Go read them here and here.

Now I just need to reduce the amount of time my data-loader takes. Can anyone suggest any effective techniques for processing ~50mb of data on a per-byte basis? I’m already blocking data so it’s processed faster and I’m using value types so the heap doesn’t get nasty – any ideas?

HLSL is More Strict on the Xbox 360

February 25th, 2007

I ran into this problem recently, and I thought it would be a good point to note, especially for anyone who doesn’t have access to an Xbox but would like their code to work on one.

When writing shaders, remember that the Xbox is more strict than a PC. Make sure your input parameters match the vertex definition (and likewise, the other way around). So if you’re using a VertexPositionColor, make sure you’re looking for something like this:

VertexToPixel myVertexShader(float4 inPos : POSITION, float4 inColor : COLOR0)

Likewise, if you’re looking for a texture coordinate, don’t use the COLOR semantic, even if that’s what you’re going to be using it for. e.g., if you’re passing a VertexPositionTexture3 (a 3D texture coordinate you may have defined) but your vertex shader looks like this:

VertexToPixel myVertexShader(float4 inPos : POSITION, float3 inColor : COLOR0)

It’s not going to work…and worse yet, it’s not going to tell you why. This can be particularly troublesome if you’re developing without an Xbox on hand. Make sure your shader takes the correct parameters instead:

VertexToPixel myVertexShader(float4 inPos : POSITION, float3 inTex : TEXCOORD0)

While the former may work on a PC, it won’t work on the Xbox 360.

Play Forces

February 23rd, 2007

You should definitely play Forces. It’s written by Adam Bielinski, and while it’s not in XNA, I understand he’s working on porting it.

I’ll bet that’s going to be fun to play on the Xbox – it’s already a blast as it is!

Sharing Code Between the Xbox 360 and PC

February 22nd, 2007

Preprocessor directives!

These enable you to define what code will or won’t be compiled, throw errors or warnings during compilation and mark regions of code for better organization. Here’s a short example of what I’m talking about:

#if XBOX
myRenderTarget = new RenderTarget2D(device, width, height, 1, SurfaceFormat.Color);
#else
myRenderTarget = new RenderTarget2D(device, width, height, 1, SurfaceFormat.Vector4);
#endif

The code above will compile differently when built for the Xbox or the PC. In this example, when building for the PC, we want to use the Vector4 surface format, because of the extra precision it gives us. However, since the Xbox doesn’t support the Vector4 surface format, we will use the Color format when compiling for the Xbox. Now we can just copy this code file into our two separate projects, and everything will compile just fine for both.

The XBOX and XBOX360 symbols are defined by default in Xbox 360 projects in XNA Game Studio Express.

You can add symbols using the project properties box by right-clicking on your project and choosing “Properties” and then selecting the “Build” tab. You can also add different symbols for different project configurations, allowing you to build different code in release and debug versions, or even make your own special configurations.

#if (DEBUG && !XBOX)
Console.WriteLine(“There are {0} enemies attacking the base.”, nEnemies);
#endif

Here, I’ve specified that if I’m building in debug mode for the PC, I want the number of enemies attacking to be written to the console. You can use most of the standard conditional operators (e.g. &&, ||, ==, !=, etc.) in preprocessor directives.

You can also define your own symbols using the #define directive, and undefine symbols using the #undef directive (which will undefine the symbol for the rest of the file, or until you define it again).

#undef XBOX
#if (DEBUG && !XBOX)
WriteToMyDebug(“The target platform doesn’t matter here! I might actually be running on an Xbox!”);
#endif

Finally, The #region and #endregion directives, which are my favorites. You’ve probably noticed that you can collapse a method by pressing the little “-” next to it, allowing you to hunt around your class a little easier (or just hide the parts you’re not working on). However, you still have variables hanging around, and even the method stubs for all those methods. It’d sure be nice to hide some of that stuff – especially if you’re fully commenting your code (an excellent habit to pick up).

#region Position

///


/// The horizontal position of this entity
///

private int x;

///


/// Gets or sets the horizontal position of this entity
///

public int X
{
get { return x; }
set { x = value; }
}

///


/// The vertical position of this entity
///

private int y;

///


/// Gets or sets the vertical position of this entity
///

public int Y
{
get { return y; }
set { y = value; }
}

#endregion

You can see that just two properties in a class can take a lot of room. However, if you put region directives around the section, you can then collapse it:

| Position |

This can make your code much easier to look at and work with. In fact, my standard game class looks like this:

///


/// The game class for Super Blaster (made that name up)
///

public class SuperBlasterGame : Microsoft.Xna.Framework.Game
{
| Variables and Properties |

| Initialization |

| Update Methods |

| Draw Methods |
}

Notice how easy it would be for someone to find a section they’re looking for? They could just expand “Variables and Properties” to add a variable to this class, or expand “Initialization” and then “Constructors” if they wanted to change how some variables are initialized.

For more reading on the subject, check out the MSDN Documentation or the tutorial at C# Help.

Update: I’ve written another post on building for the Xbox and Windows in the same project. Check it out here.

Custom Vertex Formats on the Xbox 360

February 22nd, 2007

In my current project, I needed to make my own vertex format so I could pass more information to the shader. Reimer has a wonderful tutorial on the subject (and the rest of his stuff is great, too). Unfortunately, the tutorial doesn’t implement a vertex format that will work on the Xbox 360.

After some searching, I found that Ziggyware has a great tutorial on custom vertex formats. The most important thing to remember is to implement the entire interface.

Video of my cloud

February 5th, 2007

I thought a video might be a little better for demonstrating my cloud.

Granted, it’s not the best quality, but it still shows what’s going on. You can see that the cloud maintains its shape as you move around and even through it. You can also see the subtle animation.

Look what I did!

February 4th, 2007

It’s not quite amazing yet, but it’s getting there. This is a completely volumetric cloud, rendering in real-time. I’m still working out the lighting equations for it (which are kind of hard to do when your hand it broken and you can’t draw the situation on a piece of paper) and then I’ll work on making it prettier. However, I’m pretty happy with how this looks so far.

My work is loosely based on Schpok et. al,, along with some other information I’ve found scattered about the internet. Most of it is old though, and doesn’t consider the capabilities of current graphics hardware or multi-core machines. Also, Swell, the demo for the algorithm proposed by Schpok et. al, doesn’t work on my machine because of a versioning problem with OpenGL 2+. I’m getting pretty close to what they’ve done though, so I don’t think I’ll be needing it.

I’ve got to say, I’m very happy with C# and the XNA Framework. They take a lot of the low-level details away without seriously hurting performance. I’m still able to do some pretty intensive stuff using managed code. I’m sure it’d probably be a bit faster in C++, but since XNA doesn’t work with unmanaged code, I’m pretty happy using C#.

Billboarding

February 2nd, 2007

Because I chose to use Z as the up direction in my world, I couldn’t use XNA’s built-in Matrix.CreateBillboard function (since it thought that (0,1,0) was up). This meant that yet again, I had to roll my own. I thought the code might be useful for anyone trying to do their own billboarding (or doing something special with billboarding, like centering the object around a point not within the object), so I decided to post it. This is viewpoint-based billboarding, so it has to be done for each object, and could be expensive. I like the effect though, so I’ll probably come up with a way to speed it up later.

// Find the directional vector pointing from the camera to the object
Vector3 diff = Vector3.Normalize(CameraPosition – Position);

// Find the axis of rotation
Vector3 axis;
if (Vector3.UnitZ == diff) axis = Vector3.Zero;
else axis = Vector3.Normalize(Vector3.Cross(Vector3.UnitZ, diff));

// Find the degree by which to rotate
float ang = (float)Math.Acos(Vector3.Dot(Vector3.UnitZ, diff));

// Create the billboard transformation
Matrix BillboardTransformation = Matrix.CreateFromAxisAngle(axis, ang);

Basically, this rotates the object around an arbitrary axis, with the axis and amount of rotation always set up such that the object will be facing the camera. This creates true billboarding, as opposed to cheap billboarding (where all objects are aligned with the viewing plane), so it will be a little more expensive.

This is useful for some things like volume rendering using slicing planes, because you can rotate the whole volume around a central point, and have all of the planes still lined up. Also note that I’ve used Vector3.UnitZ – that is my world’s “up” direction. You could replace it with UnitY if you like, or whatever direction you like to have as up.