==OP==
Back in the DX9 days before texture arrays, loading a texture was as simple as Texture2D.FromFile(). Now for DX11, things have become vastly more complicated. I've been googling this issue and I've been seeing various contradictory information that indicates that certain convenient helper functions have gone legacy. I looked at the way the rastertek multitexturing tutorial does it, and I am totally confused by it. It seems to load bitmap files directly into shader resource views and makes an array of shader resource views and that's the texture array... In any case I can't find the same functions in the latest version of SharpDX. I've seen some examples of texture loading with WIC, but nothing for texture arrays.
My question is, what would be the proper way as of today, 5/28/2013, to load a series of png files into a single texture array with automatically generated mipmaps? Is there a simple way to do that or are we talking about a thousand lines of code before we can pass this to a shader?
======
Here is my solution:
public static class TextureUtilities
{
public static Texture2D LoadTextureArray(string[] names)
{
ImagingFactory factory = new ImagingFactory();
List<BitmapSource> bitmaps = new List<BitmapSource>();
foreach (string name in names)
{
BitmapSource bitmap = LoadBitmap(factory, name);
bitmaps.Add(bitmap);
}
Texture2D texArray = new Texture2D(Game.GraphicsDevice, new Texture2DDescription()
{
Width = bitmaps[0].Size.Width,
Height = bitmaps[0].Size.Height,
ArraySize = names.Length,
BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget,
Usage = SharpDX.Direct3D11.ResourceUsage.Default,
CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None,
Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm,
MipLevels = CountMips(bitmaps[0].Size.Width, bitmaps[0].Size.Height),
OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.GenerateMipMaps,
SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
});
int stride = bitmaps[0].Size.Width * 4;
for(int i=0;i < bitmaps.Count; ++i)
{
var buffer = new DataStream(bitmaps[0].Size.Height * stride,true,true);
bitmaps[i].CopyPixels(stride, buffer);
DataBox box = new DataBox(buffer.DataPointer, stride, 1);
Game.GraphicsDevice.ImmediateContext.UpdateSubresource(box, texArray, Resource.CalculateSubResourceIndex(0, i, CountMips(bitmaps[0].Size.Width, bitmaps[0].Size.Height)));
buffer.Dispose();
}
ShaderResourceView view = new ShaderResourceView(Game.GraphicsDevice, texArray);
Game.GraphicsDevice.ImmediateContext.GenerateMips(view);
view.Dispose();
return texArray;
}
public static BitmapSource LoadBitmap(ImagingFactory factory, string filename)
{
var bitmapDecoder = new SharpDX.WIC.BitmapDecoder(
factory,
filename,
SharpDX.WIC.DecodeOptions.CacheOnDemand
);
var result = new SharpDX.WIC.FormatConverter(factory);
result.Initialize(
bitmapDecoder.GetFrame(0),
SharpDX.WIC.PixelFormat.Format32bppPRGBA,
SharpDX.WIC.BitmapDitherType.None,
null,
0.0,
SharpDX.WIC.BitmapPaletteType.Custom);
return result;
}
private static int CountMips(int width, int height)
{
//lifted from SharpDX Toolkit
int mipLevels = 1;
while (height > 1 || width > 1)
{
++mipLevels;
if (height > 1)
height >>= 1;
if (width > 1)
width >>= 1;
}
return mipLevels;
}
}