[beta 3] Adding DDS luminance texture support [code]
by Manoel Neto · in Torque 3D Professional · 03/27/2011 (9:25 am) · 3 replies
Here's code to add support for properly loading luminance DDS formats: GFXFormatL8, GFXFormatL16, GFXFormatL8A8 and GFXFormatL4A4. These are very useful when you have pre-generated textures that don't use all 4 RGBA channels (like lookup tables, etc).
(T3D has L8 and L16 registered as proper formats, but failed loading DDS files using those formats since they don't have RGB flags).
First, we'll add L8A8 and L4A4:
In Engine/source/gfx/gfxEnums.h, in the GFXFormat enum add the lines marked with "NEW!" comments:
In Engine/source/gfx/D3D9/pc/gfxD3D9EnumTranslate.pc.cpp, in GFXD3D9EnumTranslate::init(), add these:
In Engine/source/gfx/gfxAPI.cpp, add these:
In Engine/source/gfx/gfxFormatUtils.cpp, add:
And in Engine/source/gfx/gfxStringEnumTranslate.cpp, add:
Now let's teach DDSLoader how to load them. Open Engine/source/gfx/bitmap/ddsLoader.cpp. Lines marked with "CHANGE!" were modified (check the surrounding lines to see where they are).
Before this:
And finally, let's fix a bug/limitation in Engine/source/gfx/D3D9/gfxD3D9TextureManager.cpp:
Replace this:
By this:
(T3D has L8 and L16 registered as proper formats, but failed loading DDS files using those formats since they don't have RGB flags).
First, we'll add L8A8 and L4A4:
In Engine/source/gfx/gfxEnums.h, in the GFXFormat enum add the lines marked with "NEW!" comments:
// 8 bit texture formats... GFXFormatA8 = 0,// first in group... GFXFormatL8, GFXFormatA4L4,//<--- NEW!
// 16 bit texture formats... GFXFormatR5G6B5,// first in group... GFXFormatR5G5B5A1, GFXFormatR5G5B5X1, GFXFormatA8L8,//<--- NEW! GFXFormatL16,
In Engine/source/gfx/D3D9/pc/gfxD3D9EnumTranslate.pc.cpp, in GFXD3D9EnumTranslate::init(), add these:
GFXD3D9TextureFormat[GFXFormatR32F] = D3DFMT_R32F; GFXD3D9TextureFormat[GFXFormatA8L8] = D3DFMT_A8L8; //<--- NEW! GFXD3D9TextureFormat[GFXFormatA4L4] = D3DFMT_A4L4; //<--- NEW! GFXD3D9TextureFormat[GFXFormatA8] = D3DFMT_A8;
In Engine/source/gfx/gfxAPI.cpp, add these:
{ GFXFormatR5G5B5X1, "GFXFormatR5G5B5X1" },
{ GFXFormatA8L8, "GFXFormatA8L8" }, //<--- NEW!
{ GFXFormatA4L4, "GFXFormatA4L4" }, //<--- NEW!
{ GFXFormatA8, "GFXFormatA8" },In Engine/source/gfx/gfxFormatUtils.cpp, add:
GFXFormatInfo::Data( 1, false, false, false ), // GFXFormatL8 GFXFormatInfo::Data( 1, true, false, false ), // GFXFormatA4L4 <--- NEW! // 16 bit texture formats... GFXFormatInfo::Data( 2, false, false, false ), // GFXFormatR5G6B5 GFXFormatInfo::Data( 2, true, false, false ), // GFXFormatR5G5B5A1 GFXFormatInfo::Data( 2, false, false, false ), // GFXFormatR5G5B5X1 GFXFormatInfo::Data( 2, true, false, false ), // GFXFormatA8L8 <--- NEW! GFXFormatInfo::Data( 2, false, false, false ), // GFXFormatL16
And in Engine/source/gfx/gfxStringEnumTranslate.cpp, add:
GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatR5G5B5X1 ); GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatA8L8 ); //<--- NEW! GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatA4L4 ); //<--- NEW! GFX_STRING_ASSIGN_MACRO( GFXStringTextureFormat, GFXFormatA8 );
Now let's teach DDSLoader how to load them. Open Engine/source/gfx/bitmap/ddsLoader.cpp. Lines marked with "CHANGE!" were modified (check the surrounding lines to see where they are).
enum DDSPixelFormatFlags
{
DDPFAlphaPixels = 0x00000001,
DDPFFourCC = 0x00000004,
DDPFRGB = 0x00000040, // <--- CHANGE
DDPFLUMINANCE = 0x00020000 // <--- NEW!
};if(!(ddpfFlags & (DDPFRGB | DDPFFourCC | DDPFLUMINANCE))) //<--- CHANGE!
{
Con::errorf("DDSFile::readHeader - incoherent pixel flags, neither RGB nor FourCC!");
return false;
}Before this:
if(ddpfFlags & DDPFRGB)Add this:
// New luminance code!
if(ddpfFlags & DDPFLUMINANCE)
{
mFlags.set(RGBData);
mBytesPerPixel = pfBitCount / 8;
bool hasAlpha = ddpfFlags & DDPFAlphaPixels;
mHasTransparency = hasAlpha;
// Try to match a format.
if(hasAlpha)
{
// If it has alpha it is one of...
// GFXFormatA8L8
// GFXFormatA4L4
if(pfBitCount == 16)
mFormat = GFXFormatA8L8;
else if(pfBitCount == 8)
mFormat = GFXFormatA4L4;
else
{
Con::errorf("DDSFile::readHeader - unable to match alpha Luminance format!");
return false;
}
}
else
{
// Otherwise it is one of...
// GFXFormatL16
// GFXFormatL8
if(pfBitCount == 16)
mFormat = GFXFormatL16;
else if(pfBitCount == 8)
mFormat = GFXFormatL8;
else
{
Con::errorf("DDSFile::readHeader - unable to match non-alpha Luminance format!");
return false;
}
}
}And finally, let's fix a bug/limitation in Engine/source/gfx/D3D9/gfxD3D9TextureManager.cpp:
Replace this:
if ( dds->getSurfacePitch( i ) != lockedRect.Pitch )
{
Con::errorf( "GFXD3D9TextureManager - pitch mismatch on DDS load" );
surf->UnlockRect();
surf->Release();
return false;
}By this:
if ( dds->getSurfacePitch( i ) != lockedRect.Pitch )
{
AssertFatal( dds->mSurfaces.size() > 0, "Assumption failed. DDSFile has no surfaces." );
// Do a row-by-row copy
U32 srcPitch = dds->getSurfacePitch( i );
U32 srcHeight = dds->getHeight();
U8* srcBytes = dds->mSurfaces[0]->mMips[i];
U8* dstBytes = (U8*)lockedRect.pBits;
for (U32 i = 0; i<srcHeight; i++)
{
dMemcpy( dstBytes, srcBytes, srcPitch );
dstBytes += lockedRect.Pitch;
srcBytes += srcPitch;
}
surf->UnlockRect();
surf->Release();
return true;
}(This is the correct way to handle pitch mistmatch).About the author
Associate Tom Spilman
Sickhead Games