Geeks With Blogs
Bob Taco Industries Blogging Division

I’ve been slowly creating a new WP7 game over these past few months. In the process, I began experimenting with Dxt compression. It’s a very nice feature, especially on the phone where high DPIs make Dxt’s artifacts less visible. One thing I didn’t like, though, was the way that XNA’s default Texture Processor handles resizing to power of two.

When using Dxt compression with the Reach graphics profile, you need to use textures that are power of two sized (e.g. 32x64). Dxt itself requires that the dimensions be divisible by four (it breaks up your image into 4x4 chunks of data in order to compress it), but it’s easier for graphics cards with limited power (such as on netbooks and mobile devices) to process them when the dimensions are restricted to being a power of two as well.

XNA’s built-in Texture Processor has an option to resize your images to power of two dimensions. Unfortunately, the way it does so is by scaling your image. This can produce both odd stretching effects and also a blurry look to the result even when you compensate for the stretching. So I’ve created a quick Content Pipeline extension that resizes the image by padding it rather than by scaling it. I’m quite satisfied with the result and so I thought I’d share it with all of you to make do with as you see fit. The code is licensed under the terms of the Microsoft Public License. You can also instead use it under the terms of the MIT License (a copy of which is included in the zip file) if that works better for you.

I’ve extended the dual licensing to nearly all of my samples and have updated the ones that are affected to include a copy of both licenses. I learned recently that for some people I know the MIT License is more convenient and I like to be as accommodating as I can. If you fit in to that group, feel free to re-download any samples you are interested in to make sure the MIT License is included (my only known exclusion was for a back-port I did of a code sample that was licensed exclusively under the Ms-PL).

To use the Convert To Dxt Processor, build it, and add a reference to it to your game’s content project. Then set your image files to use the Convert To Dxt Processor. You can do this via Solution Explorer by right-clicking on the image file(s) and choosing “Properties” then changing the Content Processor from “Texture – XNA Framework” to “Convert To Dxt Processor”. If your image was not previously a “power of two” sized image, you will need to use an overload of SpriteBatch.Draw that takes a sourceRectangle parameter and use as a source rectangle something like: “new Rectangle(0, 0, width, height)” where width and height are the original width and height of the image. The sample game that is included shows this in more detail.

Without further ado, the samples:



And just so you can see the difference, a sample screenshot:


The left hand column (both rows) is the original image without any Dxt Compression or other adjustment. The middle column is the XNA Framework Texture processor. The right hand column is the custom processor I developed. The top row illustrates the images without any scaling or source rectangles used. The bottom row illustrates the XNA Framework processor’s results with scaling applied to obtain the original size and my custom processor with a source rectangle used to clip the image to its original size.

The text along the bottom shows the resulting XNB size for the Windows version using a Release configuration. The comments in the code explain why the size differences appear here and the different way in which they would manifest themselves in a WP7 build. Note that for Debug configuration the Dxt XNBs will be the same size (32.18 KB) and the original XNB will be 143.93KB. The image in question is 160x230 such that it winds up being a 256x256 XNB with power of two adjustment. So even with jumping from 36800 pixels to 65536 pixels, we still wind up with compression such that the image will only occupy 22.36% of the memory that the non-Dxt image does and we end up with reasonably good savings in storage space (for comparison, the original PNG is 43KB). So definitely consider using Dxt compression for your XNA games (both WP7 and PC/Xbox). The memory savings are quite good without much loss in quality.

Posted on Monday, August 1, 2011 10:24 AM xna , wp7 | Back to top

Comments on this post: Dxt Conversion Content Pipeline Extension Sample

# re: Dxt Conversion Content Pipeline Extension Sample
Requesting Gravatar...
The problem with padding content in a content processor is that the texture's dimensions and aspect ratio change. You need a way to ensure that the original dimensions are accessible when you load the texture at run-time.
Left by Kevin Gadd on Aug 01, 2011 2:11 PM

# re: Dxt Conversion Content Pipeline Extension Sample
Requesting Gravatar...
True, but that already happens with XNA's built-in Texture Processor.

The easy thing to do would have been to create a runtime class derived from Texture2D along with a suitable writer and reader and to then just the appropriate source rectangle to the XNB file. But unfortunately the classes that are involved in writing out TextureContent/Texture2DContent are all marked internal which makes that impossible.

My goal was to avoid the scaling distortion. It's easy enough to modify the processor to have it output transparent black for the padded pixels such that they would be completely invisible. The reason I didn't do that is that unless the edge pixels of the original texture are divisible by 4, you could wind up distorting the edges of the original image.

Still, if you don't mind the chance of the right and bottom edges looking a bit sloppy, it's a matter of changing twelve lines of code. You'd also wind up with overdraw with that solution and on the phone you've only got a max fill rate of somewhere between 2 and 3 before your framerate starts to plummet.
Left by MikeBMcL on Aug 01, 2011 8:32 PM

Comments have been closed on this topic.
Copyright © Michael B. McLaughlin | Powered by: