Archive for the 'CSharp' Category

HLSL is More Strict on the Xbox 360

Sunday, 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.

Sharing Code Between the Xbox 360 and PC

Thursday, 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

Thursday, 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

Monday, 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!

Sunday, 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

Friday, 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.

Almost at 0.2!

Friday, November 3rd, 2006

It’s been a while since my last post – October was ridiculously full of midterms, assignments, etc. I haven’t just been sitting around though, I’ve pretty much made it to version 0.2 of the engine! Here’s what I’ve done:

The entire input namespace has been updated to version 0.2 (minus a mouse component), and I’ve almost finished removing the 0.1 artifacts. The new input manager supports WasPressed along with IsPressed, and brings the ability to set up named key mappings. For example, you can now just check if IsPressed(“Attack”), without having to worry about what button attack is mapped to.

I’ve also been working on cleaning up some of our vector problems. Namely, when changing the velocity of a movement component, you couldn’t just say Movement.Velocity.X = 5; – that would produce a compile error, since you are using the get accessor for the Velocity vector instead of accessing it directly. I solved this by creating a Vector2 handle which allows you to access and change X and Y as if it were a variable. Unfortunately, since C# doesn’t have operator=, you can’t directly set the handle equal to a vector. Oh well…

I’ve also added text! We a text component in version 0.1, but the engine didn’t really have the kind of support we needed for text at that time, so it was very slow at changing text. Now the engine is very capable of displaying text. It loads a font from an xml file creating using BMFontGen.  Then, changing the Text string on the component will update the shape coordinates list in a visual component, mapping letters to shape coordinates.  These can be manipulated in exactly the same way as other visual components, allowing scaling, rotation, etc.

The engine is coming along nicely.  It’s time to update it for the XNA Framework Beta 2, along with adding sound, and then it’ll be ready for a 0.3 release.

Moving in the right direction

Friday, September 22nd, 2006

I made a ton of progress in the last week. Along with the Visual Engine mentioned in my last post, I finished the Movement Engine. Considering those were my major goals this week, along with cleaning up the last bits of the engine (which I’m doing tonight/tomorrow), I’d say I’ve made great progress.

I made a major push in the last few days and completely recoded the movement engine. I implemented (then reimplemented, then optimized) a QuadTree and implemented the Separating Axis Theorem for arbitrary convex polygons (defined by a list of vertices). It was a beast to get all of the vectors pointing in the right directions at the right times. It was even worse trying to hunt down errors. I ended up recoding a lot just to fix some problems (and made things more efficient in the process).

For example, at one point everything was bouncing as if I were using simple axis-aligned bounding boxes. I wasn’t, so it was kind of confusing. After hunting around the collision detection code for a while (tons of breakpoints >.<) I still couldn’t find it. I took a bit of a break and came back to it later, where I found out that some of the optimizations I had performed ended up biting me.

When I check for collisions, I only check objects that have moved. I take that list of objects and query the Quadtree. I’ve slightly optimized the Quadtree query so it’ll only return objects where the object’s bounding box intersects (or is contained within) the query rectangle. To make a long story short, my collision detection was always returning true, but the Quadtree query was working fine – so it looked like bounding box collisions. To make a long story short, I fixed it and it works great! Off to entity management!

Moving to 3D rendering

Friday, September 15th, 2006

I’m part of a University team working with XNA and building a 2D engine around it to support projects in a course. It’s been a lot of work, but it’s also been pretty interesting. XNA is pretty much Managed DirectX redesigned for C#. This includes garbage collection, automatic references and all of the rest of the features of C#. Along with the language move, XNA removes a ton of the annoyances of working with Manged DirectX. Having worked a little bit with MDX in the last couple of years, I definitely am liking XNA.

Over the last week I’ve been considering moving to 3D-based rendering (along with many other engine cleanup tasks). The easy method of 2D rendering in XNA is to use a SpriteBatch. Once you’ve loaded your texture (which is a single line of code), the code to render it looks like this:

spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
spriteBatch.Draw(myTexture, new Rectangle(spriteX, spriteY, 50, 50), Color.White);
spriteBatch.End();

You basically tell it what texture to render and where (even specifying tint), and it draws it. This is great, and you could probably make tons of 2D games using it. However, having dipped my feet in the world of 3D a couple semesters ago (CptS 442), I’ve seen the power of transformations, and wished to harness it for my engine. As it turns out, linear algebra was actually one of the most useful math courses here. It took a lot of work, but I’m now convinced that moving to 3D was a great idea.

Behind the interface of a visual component (how our visual information is stored) is a set of vertices with corresponding texture coordinates, a scale transformation and a translation. When the visual manager goes to draw everything for the frame, it sorts visual components by texture, then loads the first texture into memory. It places each object by multiplying the matrices together:

DrawTransformation = Scale * Translation * View * Projection;

Best of all, since every visual component using the same texture is drawn in a batch, there are only as many draw calls to the gpu as there are textures! Depth is even handled by the depth-buffer (I’ve specified a depth value for visual components that roughly cooresponds to a Z-value).

Now, if I want to add a rotation to an object, or perhaps even add a world translation (similar to camera position – useful for side-scrollers), all I have to do is add another tranformation matrix to the positioning call. Sure, I could have just used the SpriteBatch and done most of this that way, but using 3D allows me to use lighting and other 3D-effects if I want to in the future.

Finally, the way I’ve set up my View and Project matrices, world coordinates translate almost directly to screen coordinates (i.e. pixels). By default, placing an object at (20,20) will place it 20 pixels from the left and top of the drawing window. This makes it extremely easy when programming a game to make sure things are placed correctly.

I’m not sure if the other engines do this or allow it, but I think it’s much better than just blitting to the screen, and you should at least consider looking into transformations on your points if you plan to make anything other than a static-screen game.