5
\$\begingroup\$

This question is from someone who has not written a line of code for games, but several Game Save editors and other game tools.

I'm working on a Save Editor and would like to display icons of some of the game assets in C# WPF .NET 4.0, or at least convert them to PNG in memory, so I can display them without having to make copies of them. The assets are stored as .dds texture files in BC3_UNorm.

I've trawled Google results that either use SharpDX or XNA, but all the ones I've found either do not work (as the sample code is for an old version of the library), or I just plain don't understand (in the case of XNA).

How can I load a BC3_UNorm Texture file, either in SharpDX, or XNA for conversion? Sample code would be very welcome.

Here's a sample input file.


This is the only code I could get running, but it's missing some of the RGBA channels and the output looks nothing like the original:

public static System.Windows.Media.Imaging.BitmapSource ConvertTK(string filename)
{
    try
    {
        // Create the graphics device
        using (var graphicsDevice = SharpDX.Toolkit.Graphics.GraphicsDevice.New(SharpDX.Toolkit.Graphics.GraphicsAdapter.Default, SharpDX.Direct3D11.DeviceCreationFlags.SingleThreaded))
        {
            // Load the texture
            using (var texture = SharpDX.Toolkit.Graphics.Texture2D.Load(graphicsDevice, filename))
            {
                // Copy the pixel colors into a byte array
                var bytesPerPixel = 3;
                var pixelChannel = texture.GetData<byte>();
                var pixelData = new byte[pixelChannel.Length * bytesPerPixel];

                // Where are the RGBA channels? It only has 1 byte per pixel!
                for (var i = 0; i < pixelChannel.Length; i++)
                {
                    pixelData[i * bytesPerPixel + 0] = pixelChannel[i];
                    pixelData[i * bytesPerPixel + 1] = pixelChannel[i];
                    pixelData[i * bytesPerPixel + 2] = pixelChannel[i];
                }

                // Result Image is garbage, looks nothing like original .DDS BC3_UNorm file.

                // Create a bitmap source
                var stride = texture.Width * bytesPerPixel;
                return BitmapSource.Create(texture.Width, texture.Height, 96, 96, PixelFormats.Rgb24, null, pixelData, stride);
            }
        }
    }
    catch (Exception ex)
    {

    }

    return null;
}
\$\endgroup\$
  • 2
    \$\begingroup\$ To those voting to close this as "off-topic": It's not. Check the rules. It's covered under "asset pipelines" and "game-related APIs". \$\endgroup\$ – Andrew Russell Apr 2 '14 at 13:06
6
\$\begingroup\$

Loading up DirectX (via SharpDX or XNA) to do the conversion is probably overkill.

Why not simply decode the format on the CPU? It's simple enough. There is a DXT decoder in MonoGame you might be able to borrow. (In case the file changes, the latest revision at time of writing is here.)

BC3_UNORM is equivalent to DXT5, which that will happily decode.

You'll have to read the .dds file yourself. The format is pretty simple. Here are the file format details. (Given that you're making save file editors, I'm going to assume that this is not a problem.)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.