Converting image to compressed texture (DXT1) using D3DXCreateTextureFromFileEx
Problem at hand was displaying many images as hires textures in 3D scene.
Current algorithm was using uncompressed 32-bit pixel format to render which led to the giant amount of RAM consumed for each - 2048 x 2048 x 32bit = 16 Mb.
It was not the problem when image count was low (1 to 20) but after image count hit 100, application started to consume more than 2 Gb of RAM and on x86 it had become the source of very real "out of memory" error.
The idea of solution was simple - use compressed textures.
This way, there will be a ceiling for image count but it will be high enough to satisfy most of the needs.
The main questions emerged was how to actually compress textures and which compression format should we choose?
Due to engine used, we were limited to DXT1, DXT3 or DXT5 compression formats.
Chose DXT1 as soon as it gives the best compression rate (8/1) and its limitations (1-bit alpha) are not critical for our application.
The next question, actually how to compress, took some time and in the end we had two possibilities - squish which is cross-platform or something in WinAPI (we target Win32 only).
At first, my sympathies was on squish (it's used even in NVidia Texture Tools) but the more I was looking at it, the more I found it a bit cumbersome for the cause: I had to do too many things manually.
It was not evident from the beginning, but DirectX has texture function which does almost everything in one call - it's D3DXCreateTextureFromFileEx. After call to this function, I was getting the compressed texture ready to be mapped or (my case) - saved to disk in ".dds" via D3DXSaveTextureToFile.
In short:
wstring imagePathname = "c:\\test.jpg";
Current algorithm was using uncompressed 32-bit pixel format to render which led to the giant amount of RAM consumed for each - 2048 x 2048 x 32bit = 16 Mb.
It was not the problem when image count was low (1 to 20) but after image count hit 100, application started to consume more than 2 Gb of RAM and on x86 it had become the source of very real "out of memory" error.
The idea of solution was simple - use compressed textures.
This way, there will be a ceiling for image count but it will be high enough to satisfy most of the needs.
The main questions emerged was how to actually compress textures and which compression format should we choose?
Due to engine used, we were limited to DXT1, DXT3 or DXT5 compression formats.
Chose DXT1 as soon as it gives the best compression rate (8/1) and its limitations (1-bit alpha) are not critical for our application.
The next question, actually how to compress, took some time and in the end we had two possibilities - squish which is cross-platform or something in WinAPI (we target Win32 only).
At first, my sympathies was on squish (it's used even in NVidia Texture Tools) but the more I was looking at it, the more I found it a bit cumbersome for the cause: I had to do too many things manually.
It was not evident from the beginning, but DirectX has texture function which does almost everything in one call - it's D3DXCreateTextureFromFileEx. After call to this function, I was getting the compressed texture ready to be mapped or (my case) - saved to disk in ".dds" via D3DXSaveTextureToFile.
In short:
wstring imagePathname = "c:\\test.jpg";
wstring texturePathname = "c:\\test.dds";
D3DXIMAGE_INFO imageInfo;
CComPtr<IDirect3DTexture9> spTexture;
HRESULT hResult = D3DXCreateTextureFromFileExW(spD3DDevice,
imagePathname.c_str(),
D3DX_DEFAULT,
D3DX_DEFAULT,
1,
NULL,
D3DFMT_DXT1,
D3DPOOL_MANAGED,
D3DX_FILTER_NONE,
D3DX_DEFAULT,
NULL,
&imageInfo,
NULL,
&spTexture);
if(hResult == D3D_OK)
{
hResult = D3DXSaveTextureToFileW(texturePathname.c_str(), D3DXIFF_DDS, spTexture, NULL);
}
Solved!
CComPtr<IDirect3DDevice9> spD3DDevice;
//
// initializing spD3DDevice...
//
D3DXIMAGE_INFO imageInfo;
CComPtr<IDirect3DTexture9> spTexture;
HRESULT hResult = D3DXCreateTextureFromFileExW(spD3DDevice,
imagePathname.c_str(),
D3DX_DEFAULT,
D3DX_DEFAULT,
1,
NULL,
D3DFMT_DXT1,
D3DPOOL_MANAGED,
D3DX_FILTER_NONE,
D3DX_DEFAULT,
NULL,
&imageInfo,
NULL,
&spTexture);
if(hResult == D3D_OK)
{
hResult = D3DXSaveTextureToFileW(texturePathname.c_str(), D3DXIFF_DDS, spTexture, NULL);
}
Solved!
Comments
Post a Comment