Thursday, July 26, 2012

XNA4.0 – 01 – Intro

Hey, working on my time management, last day before of packing and stuff, tomorrow I am leaving on holiday, not done packing, so obviously I must find time to push out an XNA intro post. Obviously!

From now on I'll be coding in C# and will be relying on XNA (and hopefully a lot of GPU hardware based processing to compensate for the relative slowness of C# whenever possible). Of course I won't be able to just pick up the project where I left of and cut out some of the dwarf related stuff, I need to port over tons of code from C++ with Irrlicht to C# with XNA. Now while Irrlicht has quite a few problems and I have developed a personal grudge against it, that won't stop me from giving praise where praise is due: Irrlicht really does not shit around making you write glue code, lengthy resource and window setup procedures or anything. After a short setup sequence (that you may wish to rewrite and encapsulate in a more reusable component that you can use from project to project), you are free to get down and dirty immediately. And as far as I can tell, XNA maintains this "sit down and code" "no hassle" setup. DirectX, even with DXUT needs a lot of glue code to reduce the hassle. This was the primary reason I couldn't hammer out a to the point base from where to present the real shaders and code I wanted. 

So while I am porting my code, I need to find time and present XNA a little for the initiated. You will need a few tools before you get started, but luckily these tools are free. First you will need Visual C# 2010 Express | Microsoft Visual Studio. The free version is not quite as feature rich as the commercial one, but unless you are a pro familiar with the full experience, you won't miss these features. Then you need Microsoft XNA Game Studio 4.0. This will install the required XNA support in Visual C# Express. There is also a Game Studio 4.0 Refresh. I don't know what this one is about and I think that it is meant to bring XNA to Windows phones. I won't be using that one for now so don't grab it. I have nothing against Windows phones and making your games more portable is always a plus, but Windows phone has like a 2% market share. Until they don't reach at least 15% I will pretentiously disregard their effort as "cute".

So after both tools (and a lot of prerequired packages which hopefully these setups have taken care of for you), you can launch Visual Studio (that's what I'll be calling C# Express from now on, VS for short) and create a new project. You should be greeted by the following dialog (with more options available if you installed more languages than C#):

You can click on the "XNA Game Studio 4.0" sub category so you can find what you are looking for more easily:

Here you will select "Windows Game" as a project type (don't worry, I'm sure the Mono guys are hard at work porting Mono over to Linux so you can run your game there once Linux gets proper and rock-solid hardware support for your GPU (and resurrected female clone Hitler saves us from the flying shark attack apocalypse using a fire hose, duck tape an a a few million hamsters interested in philosophy) lisp).

I renamed the "Game1" class to "Game" (VS will prompt you if you want to replace all references, click "yes") and after you can run the project and almost instantly the game window should appear. Alternatively, if you are running on a very old or budget integrated GPU, you might be greeted by this window:

XNA has two profiles to tackle the challenge of a very diverse landscape of PCs out there and let me tell you: two is not enough! It is very easy to wind up in between the two. If this is the case, you need to go to project options:

The two profiles are HiDef and Reach. HiDef is default and if your machine can't handle that, you can switch to Reach:

In case you are curious, here is the breakdown of the differences between the two profiles, using a link that will surely never go away. Translating that into things you might care about, using Reach you are stuck with pixel shader 2.0, which means no pretty shadow mapping (basic one should work fine), just a few lights, no multiple lights normal/parallax mapping (you may be able to cheat this with leeloo multipass) and a few more main limitations, like 16 bit index buffers and no multiple render targets. And combining multiple techniques that work fine on their own with PS2.0 becomes a lot harder.

And finally, here we see the game window:

Glorious, just glorious!


  1. "to compensate for the relative slowness of C# whenever possible"

    Out of curiosity, what are you basing this off of? Do you actually have hard numbers to back that up or are you just going off the 'general hype' that C# is slower than C/C++. Because it turns out that in a good majority of cases, the .NET's JIT can make code run just as fast if not faster than the usual C++ code.

    1. Hello JP! Sorry for the delay, just got back from Greece!

      I have some very specific concerns related to speed and a few generic ones.

      But first, let me define the concept of fast code the way I see it, because it is not the same as most see it. I define fast code as code that executes fast due to good algorithm, inherently fast containers/other run of the mill helpers and is well written, pretty and easy to understand. So I have added the way the program is written to the notion of execution speed. Am I crazy? Maybe. I just disregard very obtuse and full of hacks code that works very fast as a last measure when you really need to optimize. Otherwise, if you choose a good algorithm and you wrote it out straight forward, it should be reasonably fast and if it is not, there is something wrong with you language or runtime.

      Second, my C++ is faster and more elegant than "normal" C++, because I shun archaic C language constructs and the standard C++ library. I code using U++. So even if C# beats C++, it probably won't beat U++.

      To give a somewhat unrelated example using Java, a while ago I created and experiment. It was a simple algorithm that used an indexable container to store integers and do some calculations with it. In U++ I used the generic vector template with an int parameter. Extraordinarily straight forward. In Java I did the same thing. Yet it ran 10 to 20 times slower. Why? Java has no real generics and it can't fit primitive types in it, so it was boxing/unboxing my ints to Integer. So the straightforward method with out of the box classes has failed. I could have used a specialized container that manager an int vector behind the scenes, there is probably even a built in one, but still this violates the straight forwardness principle. In short I would have had to jump trough a hoop to get things done.

      Now C# fares much better here and I have only minor concerns.

      The main one is that I want to write heavily procedural engine. This means that most of the CPU time will be spent on creating and updating vertex buffers. This is my main concern, since C# has an added cost in accessing buffers. Those out of bounds exceptions don't come for for free. When I activate bounds checking in my C++ code, vector heavy code gets 2-3 time slower and I expect this to be the case for C#.