Friday, September 21, 2007

Window System for XNA - New Release

Just to let everybody know that there should be a new release within the next week, basically when my internet connection is back up. The reason for the sudden release is because I've finally managed to fix the GUI rendering, with correct alpha values. The most important impact is that anti-aliased SpriteFont will be used from now on, and the old XNAExtras stuff is to be removed.

Project Site

If anyone is interested in what the problem was, and how I fixed it, then read on.

In the old system, every control was rendered to its own texture using render targets. Each child control would have its texture combined with those of the other children, to make up the texture of the parent control (after drawing itself). It was quite efficient because only the top level controls (generally windows) actually get their textures drawn to the screen, with the textures only redrawn when necessary, such as when the mouse hovers over a button, and a different image must be displayed. Render targets were also an easy way to perform clipping of child controls within their parent, and allowed the alpha value of a control to affect all children as well.

The problem with render targets was that control textures had to be drawn to a transparent texture, causing incorrect colour and alpha values to be produced during the alpha blending operation. In practical terms, it means that the edges of sprites with partial transparency and anti-aliased text would be mixed with white (or any other colour depending on the clear colour of the render target). This made either anti-aliased text unreadable, or made the edges of some controls the wrong colour. The reason I couldn't use SpriteFont, was because it created anti-aliased fonts. With XNAExtras I could make a simple font bitmap with colour keyed transparency, which made the text problem go away.

After playing with render states and pre multiplied alpha for a long time, I finally got fed up and tried to find another way to get it working. I was advised to draw directly to the screen, and use scissor rectangles to handle clipping. This worked great, except performance was abysmal. With just 4 complex windows on the screen, the framerate would start to drop. That was without any game running in the background! The reason for the poor performance was because scissor rectangles must be the same until SpriteBatch.End() is called. This means that I had a SpriteBatch.Begin() and End() call for every single control!

Next I decided to implement my own texture clipping, which all worked great, but there wasn't an obvious way to clip text. When using scissor rectangles for just text, the performance was still really bad. The final method was to use a hybrid approach. I would clip sprites on the CPU, and render text to textures which would be cached to allow fast draw calls. The text texture can then be clipped in the same way as the rest of the GUI sprites. Of course there was still the problem of partial alpha pixels being blended with the transparent texture colour. Basically I set the render states to draw with pre multiplied alpha, and set the background clear colour of the texture to the text colour, with the alpha channel set to 0. This means that the blending still takes place, but it produces the correct results. The performance is good once again!

So yeah, the project isn't dead, I've just had some big problems to deal with. Now that this is working, I will go back to adding more features like Xbox 360 support, and more widgets.

Monday, September 3, 2007

CodePlex Hosting and the Future

Hi guys. I've finally got full project hosting set up, but I decided to go with CodePlex in the end. It seemed well suited to my needs, and is already home to other XNA projects. I will not be using the current temporary forum anymore, but the discussions feature on CodePlex instead.

http://www.codeplex.com/wsx

I have updated the first new release by changing the name of the project, adding a license, and cleaning up the directory structure. The new name is Window System for XNA, instead of XNA Window System. It may seem like an unnecessary change, but it means that XNA is no longer in the official title, as Microsoft doesn't approve of that. I decided on the New BSD license, which is more permissive than the other open source licenses. Finally, the projects now reference binary DLLs, instead of requiring all projects to be included in the solution.

I have been working on fixing the current bugs, and have decided to make some rather large changes along the way. The GUI will no longer be drawn with render targets, because I couldn't get premultiplied alpha values to work correctly, which screwed up font rendering. The font support provided in XNA Refresh will now be used instead of XNAExtras. I will also be adding joypad support for the Xbox 360 controller as well as regular Windows controllers. Support for the Xbox 360 will be added in the longer term (when I find somebody with an Xbox 360 to implement it). These and many other changes will be added over the coming months. You can keep up to date with the project by using the source control feature of the CodePlex project.

Please consider helping with the project, either by contributing code, working on documentation, artwork, or by submiting bugs and helping out in discussions.