Added functions to scattertable tool to write out atmospheric scattering

tables as half float textures in .dds files.
sensor-dev
Chris Laurel 2010-07-02 00:08:40 +00:00
parent 672682b380
commit dc32eedc9c
1 changed files with 275 additions and 2 deletions

View File

@ -78,7 +78,6 @@ static Vector3f RayleighScatteringCoeff(float n, float N)
}
class Atmosphere
{
public:
@ -171,7 +170,14 @@ static inline float toMu(float u)
// Map a unorm to the cosine of the sun angle
static inline float toMuS(float u)
{
return (-1.0f / 3.0f) * (log(1.0f - u * (1.0f - exp(-3.6f))) + 0.6f);
// Original version from Bruneton paper:
//return (-1.0f / 3.0f) * (log(1.0f - u * (1.0f - exp(-3.6f))) + 0.6f);
// Modifier version has a wider range, allowing more negative angles. This
// eliminates the faint but persistent illumination that appears even
// when the sun is far below the horizon. Even the adjusted function may
// still not be adequate when very large scale heights are used.
return (-1.0f / 2.0f) * (log(1.0f - u * (1.0f - exp(-2.6f))) + 0.6f);
}
@ -347,6 +353,12 @@ Atmosphere::computeInscatterTable() const
unsigned int index = (i * ViewAngleSamples + j) * SunAngleSamples + k;
inscatter[index] << rayleigh.cwise() * rayleighCoeff,
mie * mieCoeff;
if (i == HeightSamples - 1 && k == 0)
{
cout << acos(muS) * 180.0/M_PI << ", "
<< acos(mu) * 180.0/M_PI << ", "
<< inscatter[index].transpose() << endl;
}
#if 0
// Emit warnings about NaNs in scatter table
@ -537,6 +549,7 @@ bool parseCommandLine(int argc, char* argv[])
typedef unsigned int uint32;
typedef unsigned short uint16;
union Uint32
{
@ -550,6 +563,210 @@ union Float
float f;
};
union FloatInt
{
float f;
uint32 u;
};
// Convert a single precision floating point value to half precision
uint16 floatToHalf(float f)
{
FloatInt fi;
fi.f = f;
uint16 half = 0;
uint16 signBit = uint16((fi.u & 0x80000000) >> 16);
if (f > 65504.0f)
{
// overflow
return 0x7c00;
}
else if (f < -65504.0f)
{
// overflow
return 0xfc00;
}
int exponent = int((fi.u >> 23) & 0xff) - 127 + 15;
uint32 significand = fi.u & 0x007fffff;
if (exponent < -9)
{
// Value is too small even to represent as a subnormal
return signBit;
}
else if (exponent <= 0)
{
// Convert to a subnormal
return signBit + (significand >> (13 - exponent));
}
else if (exponent + 127 - 15 == 0xff)
{
// Special values: infinities and NaNs
if (significand == 0)
{
// Infinity
return signBit + 0x7c00;
}
else
{
// NaN - preserve bits, but make sure that we don't
// make the significand zero, as that would indicate
// an infinity, not a NaN
uint16 nanBits = uint16(significand >> 13);
if (nanBits == 0)
{
nanBits = 1;
}
return signBit + 0x7c00 + nanBits;
}
}
else if (exponent > 30)
{
// Overflow; return infinity
return signBit + 0x7c00;
}
else
{
// Normal value
return signBit + (exponent << 10) +
((significand + 0x00001000) >> 13); // round
}
}
struct DDSPixelFormat
{
DDSPixelFormat() :
dwSize(0),
dwFlags(0),
dwFourCC(0),
dwRGBBitCount(0),
dwRBitMask(0),
dwGBitMask(0),
dwBBitMask(0),
dwABitMask(0)
{
}
uint32 dwSize;
uint32 dwFlags;
uint32 dwFourCC;
uint32 dwRGBBitCount;
uint32 dwRBitMask;
uint32 dwGBitMask;
uint32 dwBBitMask;
uint32 dwABitMask;
};
// Header for Microsoft DDS file format
struct DDSHeader
{
DDSHeader() :
dwSize(sizeof(DDSHeader)),
dwFlags(DDSD_PIXELFORMAT),
dwHeight(0),
dwWidth(0),
dwLinearSize(0),
dwDepth(0),
dwMipMapCount(0),
dwCaps(0),
dwCaps2(0),
dwCaps3(0),
dwCaps4(0),
dwReserved2(0)
{
for (unsigned int i = 0; i < sizeof(dwReserved1) / sizeof(uint32); i++)
{
dwReserved1[i] = 0;
}
}
static const uint32 CAPS_COMPLEX = 0x000008;
static const uint32 CAPS_MIPMAP = 0x400000;
static const uint32 CAPS_TEXTURE = 0x001000;
static const uint32 CAPS2_VOLUME = 0x200000;
static const uint32 CAPS2_CUBEMAP = 0x00000200;
static const uint32 CAPS2_CUBEMAP_POSITIVEX = 0x00000400;
static const uint32 CAPS2_CUBEMAP_NEGATIVEX = 0x00000800;
static const uint32 CAPS2_CUBEMAP_POSITIVEY = 0x00001000;
static const uint32 CAPS2_CUBEMAP_NEGATIVEY = 0x00002000;
static const uint32 CAPS2_CUBEMAP_POSITIVEZ = 0x00004000;
static const uint32 CAPS2_CUBEMAP_NEGATIVEZ = 0x00008000;
static const uint32 DDSD_CAPS = 0x1;
static const uint32 DDSD_HEIGHT = 0x2;
static const uint32 DDSD_WIDTH = 0x4;
static const uint32 DDSD_PITCH = 0x8;
static const uint32 DDSD_PIXELFORMAT = 0x1000;
static const uint32 DDSD_MIPMAPCOUNT = 0x20000;
static const uint32 DDSD_LINEARSIZE = 0x80000;
static const uint32 DDSD_DEPTH = 0x800000;
static const uint32 D3DFMT_A16B16G16R16 = 36;
static const uint32 D3DFMT_A16B16G16R16F = 113;
static const uint32 D3DFMT_DXT1 = 0x31545844;
static const uint32 D3DFMT_DXT3 = 0x33545844;
static const uint32 D3DFMT_DXT5 = 0x35545844;
static const uint32 FOURCC = 0x04;
uint32 dwSize;
uint32 dwFlags;
uint32 dwHeight;
uint32 dwWidth;
uint32 dwLinearSize;
uint32 dwDepth;
uint32 dwMipMapCount;
uint32 dwReserved1[11];
DDSPixelFormat ddpf;
uint32 dwCaps;
uint32 dwCaps2;
uint32 dwCaps3;
uint32 dwCaps4;
uint32 dwReserved2;
void setTexture()
{
dwCaps |= CAPS_TEXTURE;
}
void setFourCC(uint32 fcc)
{
dwFlags |= FOURCC;
ddpf.dwFourCC = fcc;
}
void setMipMapLevels(uint32 levels)
{
dwCaps |= (CAPS_COMPLEX | CAPS_MIPMAP);
dwFlags |= DDSD_MIPMAPCOUNT;
dwMipMapCount = levels;
}
void setDimensions(uint32 width, uint32 height)
{
dwFlags |= (DDSD_WIDTH | DDSD_HEIGHT);
dwWidth = width;
dwHeight = height;
}
void setVolumeDimensions(uint32 width, uint32 height, uint32 depth)
{
dwCaps |= CAPS_COMPLEX;
dwFlags |= (DDSD_WIDTH | DDSD_HEIGHT | DDSD_DEPTH);
dwWidth = width;
dwHeight = height;
dwDepth = depth;
}
};
static bool ByteSwapRequired = false;
static bool IsLittleEndian()
{
@ -593,6 +810,61 @@ static void WriteFloat(ostream& out, float f)
}
void WriteDDSHeader(ostream& out, const DDSHeader& dds)
{
WriteUint32(out, dds.dwSize);
WriteUint32(out, dds.dwFlags);
WriteUint32(out, dds.dwHeight);
WriteUint32(out, dds.dwWidth);
WriteUint32(out, dds.dwLinearSize);
WriteUint32(out, dds.dwDepth);
WriteUint32(out, dds.dwMipMapCount);
for (unsigned int i = 0; i < sizeof(dds.dwReserved1) / sizeof(uint32); i++)
{
WriteUint32(out, dds.dwReserved1[i]);
}
WriteUint32(out, dds.ddpf.dwSize);
WriteUint32(out, dds.ddpf.dwFlags);
WriteUint32(out, dds.ddpf.dwFourCC);
WriteUint32(out, dds.ddpf.dwRGBBitCount);
WriteUint32(out, dds.ddpf.dwRBitMask);
WriteUint32(out, dds.ddpf.dwGBitMask);
WriteUint32(out, dds.ddpf.dwBBitMask);
WriteUint32(out, dds.ddpf.dwABitMask);
WriteUint32(out, dds.dwCaps);
WriteUint32(out, dds.dwCaps2);
WriteUint32(out, dds.dwCaps3);
WriteUint32(out, dds.dwCaps4);
WriteUint32(out, dds.dwReserved2);
}
static void WriteScatterTableDDS(ostream& out, Vector4f* inscatterTable)
{
DDSHeader dds;
dds.setTexture();
dds.setFourCC(DDSHeader::D3DFMT_A16B16G16R16F);
dds.setVolumeDimensions(SunAngleSamples, ViewAngleSamples, HeightSamples);
//dds.setMipMapLevels();
}
#if TEST_FLOAT_TO_HALF
int main(void)
{
while (cin.good())
{
float f = 0.0f;
cin >> f;
cout << hex << floatToHalf(f) << endl;
}
return 0;
}
#endif
int main(int argc, char* argv[])
{
bool commandLineOK = parseCommandLine(argc, argv);
@ -634,6 +906,7 @@ int main(int argc, char* argv[])
ofstream out(OutputFileName.c_str(), ostream::binary);
// Table dimensions
WriteUint32(out, ViewAngleSamples);
WriteUint32(out, HeightSamples);