SaveToDDSFile

Dec 11, 2014 at 1:12 AM
Edited Dec 11, 2014 at 4:31 AM
Hi Folks,

I wonder whether anyone can give me a few tips on how to use this function, SaveToDDSFile. Basically, I'm trying to create a 3D texture and save it as a DDS file. I'm close to getting this working, I think...

I create the texture file and then load the bytes (each element in the volume is a set of four bytes, as indicated by the format DXGI_FORMAT_R8G8B8A8_UNORM) -- this part isn't a problem. The code I'm using to set this up is copied below. (I suspect I'm trying to make things too easy.) The type of pByteBuffer is uint8_t*.

When I step through the function SaveToDDSFile, it's clear that it wants to see an array of images and all these "slices" if i set the depth to higher than one. Right now, if I set the depth as it is below, things work out in the sense that the function seems to correctly write the DDS file, and it seems to work well in subsequent processing, but the function itself fails (SaveToDDSFile fails), which is inconvenient from a debugging point of view. It fails because the image array contains only one image.

Is this approach unworkable for a 3D texture? Any tips would be appreciated.
Image img;
img.width = NOISE_VOLUME_EDGE;/*<width of pixel data>*/
img.height = NOISE_VOLUME_EDGE;/*<height of pixel data>*/
img.format = DXGI_FORMAT_R8G8B8A8_UNORM;
img.rowPitch = 64;//1024; //64 * 4; /*<number of bytes in a scanline of the source data>*/ //16 x 4 (?)
img.slicePitch = 16384; //1024 * 16;/*<number of bytes in the entire 2D image>*/
img.pixels = pByteBuffer; /*<pointer to pixel data>*/

TexMetadata mdata;
memset( &mdata, 0, sizeof(mdata) );
mdata.width = img.width;
mdata.height = img.height;
mdata.depth = NOISE_VOLUME_EDGE;
mdata.arraySize = 1;
mdata.mipLevels = 1;
mdata.format = img.format;
mdata.dimension = TEX_DIMENSION_TEXTURE3D;
HRESULT hr = SaveToDDSFile( (const Image*) &img, (size_t) 1, mdata, (DWORD) DDS_FLAGS_NONE, (LPCWSTR) sFilePath.c_str() );
Coordinator
Dec 12, 2014 at 12:16 AM
Edited Dec 12, 2014 at 12:19 AM
Take a look at the source for ScratchImage::Initialize3DFromImages and it might make more sense to you. Also look at the helpers _DetermineImageArray, and _SetupImageArray. This is all in DirectXTexImage.cpp.
Dec 12, 2014 at 12:45 AM
Those sound like promising helpers, many thanks! I'll have a look at it tonight.
Dec 12, 2014 at 4:23 AM
Edited Dec 12, 2014 at 4:51 AM
Yes, all I really needed was to get the image array set up properly and then pass a pointer to that array as the first argument in the function SaveToDDSFile. This will be helpful to know in the future...

I'll post below the basic outline of the code I used.

I'll admit that I didn't understand how to get access to the important helper function _SetupImageArray, so I basically extracted it and reproduced it as my own helper function, but it's exactly the same (SetupImageArray).

Thanks for the help!
uint8_t* pByteBuffer; //I loaded these bytes from a separate file.
TexMetadata mdata;
memset( &mdata, 0, sizeof(mdata) );
mdata.width = NOISE_VOLUME_EDGE; //This value is 16, so iTotalBytes below is 16384
mdata.height = NOISE_VOLUME_EDGE;
mdata.depth = NOISE_VOLUME_EDGE;
mdata.arraySize = 1;
mdata.mipLevels = 1;
mdata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
mdata.dimension = TEX_DIMENSION_TEXTURE3D;

int iTotalBytes = VOLUME_MAP_EDGE*VOLUME_MAP_EDGE*VOLUME_MAP_EDGE*4;

Image images[16];
SetupImageArray(pByteBuffer, iTotalBytes, mdata, DDS_FLAGS_NONE, images, VOLUME_MAP_EDGE);

tstring sFilePath = szOutputFileName;
HRESULT hr = SaveToDDSFile( (const Image*) images, (size_t) NOISE_VOLUME_EDGE, mdata, (DWORD) DDS_FLAGS_NONE, (LPCWSTR) sFilePath.c_str() );
Marked as answer by walbourn on 12/11/2014 at 10:40 PM