XNA 4 Texture2D and DXT5

Started by
4 comments, last by JacKAsterisK 10 years, 1 month ago

Hi, I'm trying to compress some PNG files to DDS with DXT5 then load them back into a Texture2D (XNA 4). I'm doing this because my game requires lots of tiled images that need to be loaded in and out constantly and PNG is turning out to be fairly slow. I'm running into a lot of problems though.

I tried using ManagedSquish, a .NET wrapper for libsquish, but it's crashing when I start the compression. I haven't even gotten to trying to set the compressed data into a Texture2D yet, even though I'm unsure if it will work. Any insight would be greatly appreciated. Here's my code thus far:


// Get texture pixels
Color[] _pixels = new Color[_texture.Width * _texture.Height];
_texture.GetData(_pixels);

// Format it as RBGA bytes
byte[] _rgbaData = new byte[_pixels.Length * 4];
for (int _pixelIndex = 0; _pixelIndex < _pixels.Length; _pixelIndex++)
{
    _rgbaData[_pixelIndex + 0] = _pixels[_pixelIndex].R;
    _rgbaData[_pixelIndex + 1] = _pixels[_pixelIndex].G;
    _rgbaData[_pixelIndex + 2] = _pixels[_pixelIndex].B;
    _rgbaData[_pixelIndex + 3] = _pixels[_pixelIndex].A;
}

// Compress using ManagedSquish [This is where it crashes]
var _compressedImage = ManagedSquish.Squish.CompressImage(
    _rgbaData, 
    _texture.Width, 
    _texture.Height, 
    ManagedSquish.SquishFlags.Dxt5
);            

// Assign data to Texture2D
Texture2D _newTex = new Texture2D(
    Graphics.Device, 
    _texture.Width, 
    _texture.Height, 
    true, 
    SurfaceFormat.Dxt5
);
_newTex.SetData(_compressedImage);

Advertisement

Why don't use built in DXT compression? If you use content pipeline you can, with image selected, chose Content Processor->Texture Format->DxtCompressed in Properties window. According to Shawn the Content Pipeline automatically chooses between DXT1 and DXT5, depending on whether your texture has an alpha channel.

I should have explained this, my bad, but I'm rendering out these images (so I can make custom normal and depth maps) and there will be a high volume of them. The content pipeline didn't seem practical for this usage. I already have this built for PNG as well, so I was hoping I could just change the compression.

There are a few problems with your code:

- _rgbaData should be indexed with [_pixelIndex * 4 + n], not [_pixelIndex + n].

- you're creating a Texture2D with mipmaps, but you're only setting data for one mip level

- you should have some sort of check that width and height are multiples of 4, since DXT compression requires that

I'm not sure why CompressImage is crashing, but you should follow up with the people who made ManagedSquish. Also, what is the exception?


I'm doing this because my game requires lots of tiled images that need to be loaded in and out constantly and PNG is turning out to be fairly slow.

Slow when loading, or slow when rendering? DXT-compressed textures with be 1) faster to load from disk (so faster loading time), and 2) faster to render with, *if* you're bottlenecked by thrashing the texture cache. What makes you think that's the case?


I should have explained this, my bad, but I'm rendering out these images (so I can make custom normal and depth maps) and there will be a high volume of them. The content pipeline didn't seem practical for this usage. I already have this built for PNG as well, so I was hoping I could just change the compression.

I'm not sure I understand your reasoning. Why would the content pipeline not be practical? In addition to what zz2 suggested, you could use a 3rd party tool to convert your pngs to dds files with DXT compression (DirectX texture tool, or the nVidia plugin for photoshop, say), then load them through the content pipeline in XNA, using NoChange for the texture format.

How are you loading your textures in game? Through the content pipeline, or via Texture2D.FromStream?

Also, the fact that you have a "high volume" of them raises a red flag regarding your performance issue. If you're drawing lots of different texture tiles during a frame, they should be part of a single texture atlas. Otherwise, your performance may be impacted by texture switching.

The indexing problem is most likely the source of the compression crash, thanks! I'll test it when I get home. "Crash" is probably the wrong word though, it was just hanging.
The performance lag was in the draw, but I'd also love to speed up load times. :)


The reason I have so many tiles is due to the size of the game environment, I'm still working on the exact tile size but texture switching is probably an issue as well.

The textures are initially rendered with RenderTarget2D and just casted into the Texture2D.

I'm loading them in through a stream so an artist can generate these images and I don't have to work programmatically with the content builder. I was also hoping an added bonus would be me packing the color, normal, and depth maps into 1 file (along with some other bits of data) so loading is more efficient.

For anyone else that runs into this issue, the problem was that ManagedSquish doesn't work on full images. You have to compress 4x4 pixel blocks at a time.

This topic is closed to new replies.

Advertisement