From eb10483faf30ee9c0e9300a0b7457bc66cd2e60c Mon Sep 17 00:00:00 2001 From: castano Date: Fri, 30 Sep 2011 01:52:27 +0000 Subject: [PATCH] Fix bugs. In progress cube map loading. --- project/vc9/cubemaptest/cubemaptest.vcproj | 330 +++++++++++++++++ project/vc9/nvcore/nvcore.vcproj | 36 ++ project/vc9/nvtt.sln | 27 ++ src/nvcore/Memory.cpp | 3 +- src/nvcore/Utils.h | 82 ++--- src/nvimage/DirectDrawSurface.cpp | 402 +++++++++++++++------ src/nvimage/DirectDrawSurface.h | 15 +- src/nvimage/FloatImage.h | 6 +- src/nvimage/nvimage.h | 7 +- src/nvtt/CubeSurface.cpp | 134 +++++-- src/nvtt/CubeSurface.h | 2 +- src/nvtt/nvtt.h | 14 +- 12 files changed, 824 insertions(+), 234 deletions(-) create mode 100755 project/vc9/cubemaptest/cubemaptest.vcproj diff --git a/project/vc9/cubemaptest/cubemaptest.vcproj b/project/vc9/cubemaptest/cubemaptest.vcproj new file mode 100755 index 0000000..2ee7853 --- /dev/null +++ b/project/vc9/cubemaptest/cubemaptest.vcproj @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/project/vc9/nvcore/nvcore.vcproj b/project/vc9/nvcore/nvcore.vcproj index 9af9e2c..16cc8a7 100644 --- a/project/vc9/nvcore/nvcore.vcproj +++ b/project/vc9/nvcore/nvcore.vcproj @@ -323,6 +323,38 @@ + + + + + + + + + + + + + + diff --git a/project/vc9/nvtt.sln b/project/vc9/nvtt.sln index 271b0b0..02df0c7 100644 --- a/project/vc9/nvtt.sln +++ b/project/vc9/nvtt.sln @@ -91,6 +91,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bc6h", "bc6h\bc6h.vcproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nvthread", "nvthread\nvthread.vcproj", "{3DD3A43D-C6EA-460F-821B-6C339A03C5BB}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cubemaptest", "cubemaptest\cubemaptest.vcproj", "{CFB3FEAC-5720-4B16-9D7E-039DB180B641}" + ProjectSection(ProjectDependencies) = postProject + {1AEB7681-57D8-48EE-813D-5C41CC38B647} = {1AEB7681-57D8-48EE-813D-5C41CC38B647} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug (no cuda)|Mixed Platforms = Debug (no cuda)|Mixed Platforms @@ -482,6 +487,28 @@ Global {3DD3A43D-C6EA-460F-821B-6C339A03C5BB}.Release|Win32.Build.0 = Release|Win32 {3DD3A43D-C6EA-460F-821B-6C339A03C5BB}.Release|x64.ActiveCfg = Release|x64 {3DD3A43D-C6EA-460F-821B-6C339A03C5BB}.Release|x64.Build.0 = Release|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug (no cuda)|Mixed Platforms.ActiveCfg = Debug|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug (no cuda)|Mixed Platforms.Build.0 = Debug|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug (no cuda)|Win32.ActiveCfg = Debug|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug (no cuda)|x64.ActiveCfg = Debug|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug (no cuda)|x64.Build.0 = Debug|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug|Mixed Platforms.Build.0 = Debug|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug|Win32.ActiveCfg = Debug|Win32 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug|Win32.Build.0 = Debug|Win32 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug|x64.ActiveCfg = Debug|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Debug|x64.Build.0 = Debug|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release (no cuda)|Mixed Platforms.ActiveCfg = Release|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release (no cuda)|Mixed Platforms.Build.0 = Release|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release (no cuda)|Win32.ActiveCfg = Release|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release (no cuda)|x64.ActiveCfg = Release|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release (no cuda)|x64.Build.0 = Release|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release|Mixed Platforms.ActiveCfg = Release|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release|Mixed Platforms.Build.0 = Release|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release|Win32.ActiveCfg = Release|Win32 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release|Win32.Build.0 = Release|Win32 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release|x64.ActiveCfg = Release|x64 + {CFB3FEAC-5720-4B16-9D7E-039DB180B641}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/nvcore/Memory.cpp b/src/nvcore/Memory.cpp index 6a42a6d..644f40a 100644 --- a/src/nvcore/Memory.cpp +++ b/src/nvcore/Memory.cpp @@ -114,5 +114,6 @@ void operator delete(void* p, const std::nothrow_t&) throw() #endif // 0 - #endif // NV_OVERRIDE_ALLOC + + diff --git a/src/nvcore/Utils.h b/src/nvcore/Utils.h index 9c9159e..fbcc9c6 100644 --- a/src/nvcore/Utils.h +++ b/src/nvcore/Utils.h @@ -7,16 +7,18 @@ #include "nvcore.h" #include "Debug.h" // nvDebugCheck +#include + // Just in case. Grrr. #undef min #undef max #define NV_INT8_MIN (-128) #define NV_INT8_MAX 127 -#define NV_INT16_MIN (-32768) +#define NV_INT16_MIN (-32767-1) #define NV_INT16_MAX 32767 #define NV_UINT16_MAX 0xffff -#define NV_INT32_MIN (-2147483648) +#define NV_INT32_MIN (-2147483647-1) #define NV_INT32_MAX 2147483647 #define NV_UINT32_MAX 0xffffffff #define NV_INT64_MAX POSH_I64(9223372036854775807) @@ -37,63 +39,29 @@ namespace nv inline uint32 asUnsigned(int32 x) { return (uint32) x; } inline uint64 asUnsigned(int64 x) { return (uint64) x; } - template inline uint32 toU32(T x) { - nvDebugCheck(x <= NV_UINT32_MAX); - nvDebugCheck(x >= 0); - return (uint32) x; - } - /* - template inline int8 toI8(T x) { - nvDebugCheck(x <= INT8_MAX); - nvDebugCheck(x >= INT8_MIN); - int8 y = (int8) x; - nvDebugCheck(x == (T)y); - return y; - } - - template inline uint8 toU8(T x) { - nvDebugCheck(x <= UINT8_MAX); - nvDebugCheck(x >= 0); - return (uint8) x; - } + // uint32 casts: + template inline uint32 toU32(T x) { return x; } + template <> inline uint32 toU32(uint64 x) { nvDebugCheck(x <= NV_UINT32_MAX); return (uint32)x; } + template <> inline uint32 toU32(int64 x) { nvDebugCheck(x >= 0 && x <= NV_UINT32_MAX); return (uint32)x; } + //template <> inline uint32 toU32(uint32 x) { return x; } + template <> inline uint32 toU32(int32 x) { nvDebugCheck(x >= 0); return (uint32)x; } + //template <> inline uint32 toU32(uint16 x) { return x; } + template <> inline uint32 toU32(int16 x) { nvDebugCheck(x >= 0); return (uint32)x; } + //template <> inline uint32 toU32(uint8 x) { return x; } + template <> inline uint32 toU32(int8 x) { nvDebugCheck(x >= 0); return (uint32)x; } + + // int32 casts: + template inline int32 toI32(T x) { return x; } + template <> inline int32 toI32(uint64 x) { nvDebugCheck(x <= NV_INT32_MAX); return (int32)x; } + template <> inline int32 toI32(int64 x) { nvDebugCheck(x >= NV_INT32_MIN && x <= NV_UINT32_MAX); return (int32)x; } + template <> inline int32 toI32(uint32 x) { nvDebugCheck(x <= NV_INT32_MAX); return (int32)x; } + //template <> inline int32 toI32(int32 x) { return x; } + //template <> inline int32 toI32(uint16 x) { return x; } + //template <> inline int32 toI32(int16 x) { return x; } + //template <> inline int32 toI32(uint8 x) { return x; } + //template <> inline int32 toI32(int8 x) { return x; } - template inline int16 toI16(T x) { - nvDebugCheck(x <= INT16_MAX); - nvDebugCheck(x >= INT16_MIN); - return (int16) x; - } - - template inline uint16 toU16(T x) { - nvDebugCheck(x <= UINT16_MAX); - nvDebugCheck(x >= 0); - return (uint16) x; - } - - template inline int32 toI32(T x) { - nvDebugCheck(x <= INT32_MAX); - nvDebugCheck(x >= INT32_MIN); - return (int32) x; - } - - template inline uint32 toU32(T x) { - nvDebugCheck(x <= UINT32_MAX); - nvDebugCheck(x >= 0); - return (uint32) x; - } - - template inline int64 toI64(T x) { - nvDebugCheck(x <= INT64_MAX); - nvDebugCheck(x >= INT64_MIN); - return (int64) x; - } - - template inline uint64 toU64(T x) { - nvDebugCheck(x <= UINT64_MAX); - nvDebugCheck(x >= 0); - return (uint64) x; - } - */ /// Swap two values. template diff --git a/src/nvimage/DirectDrawSurface.cpp b/src/nvimage/DirectDrawSurface.cpp index 92f0e19..aa8ff4d 100644 --- a/src/nvimage/DirectDrawSurface.cpp +++ b/src/nvimage/DirectDrawSurface.cpp @@ -223,6 +223,154 @@ namespace } } + static uint pixelSize(D3DFORMAT format) { + if (format == D3DFMT_R16F) return 8*2; + if (format == D3DFMT_G16R16F) return 8*4; + if (format == D3DFMT_A16B16G16R16F) return 8*8; + if (format == D3DFMT_R32F) return 8*4; + if (format == D3DFMT_G32R32F) return 8*8; + if (format == D3DFMT_A32B32G32R32F) return 8*16; + + if (format == D3DFMT_R8G8B8) return 8*3; + if (format == D3DFMT_A8R8G8B8) return 8*4; + if (format == D3DFMT_X8R8G8B8) return 8*4; + if (format == D3DFMT_R5G6B5) return 8*2; + if (format == D3DFMT_X1R5G5B5) return 8*2; + if (format == D3DFMT_A1R5G5B5) return 8*2; + if (format == D3DFMT_A4R4G4B4) return 8*2; + if (format == D3DFMT_R3G3B2) return 8*1; + if (format == D3DFMT_A8) return 8*1; + if (format == D3DFMT_A8R3G3B2) return 8*2; + if (format == D3DFMT_X4R4G4B4) return 8*2; + if (format == D3DFMT_A2B10G10R10) return 8*4; + if (format == D3DFMT_A8B8G8R8) return 8*4; + if (format == D3DFMT_X8B8G8R8) return 8*4; + if (format == D3DFMT_G16R16) return 8*4; + if (format == D3DFMT_A2R10G10B10) return 8*4; + if (format == D3DFMT_A2B10G10R10) return 8*4; + + if (format == D3DFMT_L8) return 8*1; + if (format == D3DFMT_L16) return 8*2; + + return 0; + } + + static uint pixelSize(DXGI_FORMAT format) { + switch(format) { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 8*16; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 8*12; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return 8*8; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + + case DXGI_FORMAT_R11G11B10_FLOAT: + + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + return 8*4; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + return 8*2; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + return 8*1; + + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + return 8*4; + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + return 8*4; + + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + return 8*2; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + return 8*4; + + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return 8*4; + } + + return 0; + } + } // namespace namespace nv @@ -334,55 +482,6 @@ namespace } // namespace - -static uint pixelSize(D3DFORMAT format) { - if (D3DFMT_R16F) return 2; - if (D3DFMT_G16R16F) return 4; - if (D3DFMT_A16B16G16R16F) return 8; - if (D3DFMT_R32F) return 4; - if (D3DFMT_G32R32F) return 8; - if (D3DFMT_A32B32G32R32F) return 16; - - if (D3DFMT_R8G8B8) return 3; - if (D3DFMT_A8R8G8B8) return 4; - if (D3DFMT_X8R8G8B8) return 4; - if (D3DFMT_R5G6B5) return 2; - if (D3DFMT_X1R5G5B5) return 2; - if (D3DFMT_A1R5G5B5) return 2; - if (D3DFMT_A4R4G4B4) return 2; - if (D3DFMT_R3G3B2) return 1; - if (D3DFMT_A8) return 1; - if (D3DFMT_A8R3G3B2) return 2; - if (D3DFMT_X4R4G4B4) return 2; - if (D3DFMT_A2B10G10R10) return 4; - if (D3DFMT_A8B8G8R8) return 4; - if (D3DFMT_X8B8G8R8) return 4; - if (D3DFMT_G16R16) return 4; - if (D3DFMT_A2R10G10B10) return 4; - if (D3DFMT_A2B10G10R10) return 4; - - if (D3DFMT_L8) return 1; - if (D3DFMT_L16) return 2; - - return 0; -} - -static uint blockSize(uint fourcc) -{ - if (fourcc == FOURCC_DXT1) return 8; - if (fourcc == FOURCC_DXT3) return 16; - if (fourcc == FOURCC_DXT5) return 16; - if (fourcc == FOURCC_ATI1) return 8; - if (fourcc == FOURCC_ATI2) return 16; - return 0; -} - -static uint blockSize(DXGI_FORMAT format) -{ - -} - - uint nv::findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { for (int i = 0; i < s_d3d9FormatCount; i++) @@ -720,6 +819,76 @@ uint DDSHeader::d3d9Format() const } } +uint DDSHeader::pixelSize() const +{ + if (hasDX10Header()) { + return ::pixelSize((DXGI_FORMAT)header10.dxgiFormat); + } + else { + if (flags & DDPF_FOURCC) { + return ::pixelSize((D3DFORMAT)pf.fourcc); + } + else { + nvDebugCheck((pf.flags & DDPF_RGB) || (pf.flags & DDPF_LUMINANCE)); + return pf.bitcount; + } + } +} + +uint DDSHeader::blockSize() const +{ + switch(pf.fourcc) + { + case FOURCC_DXT1: + case FOURCC_ATI1: + return 8; + case FOURCC_DXT2: + case FOURCC_DXT3: + case FOURCC_DXT4: + case FOURCC_DXT5: + case FOURCC_RXGB: + case FOURCC_ATI2: + return 16; + case FOURCC_DX10: + switch(header10.dxgiFormat) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return 8; + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 16; + }; + }; + + // Not a block image. + return 0; +} + +bool DDSHeader::isBlockFormat() const +{ + return blockSize() != 0; +} + + + DirectDrawSurface::DirectDrawSurface() : stream(NULL) @@ -1039,18 +1208,50 @@ void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) return data; }*/ -uint DirectDrawSurface::surfaceSize(uint mipmap) const +/*uint DirectDrawSurface::surfaceSize(uint mipmap) const { + uint w = header.width(); + uint h = header.height(); + uint d = header.depth(); + for (int m = 0; m < mipmap; m++) { + w = (w + 1) / 2; + h = (h + 1) / 2; + d = (d + 1) / 2; + } + bool isBlockFormat; + uint blockOrPixelSize; + + if (header.hasDX10Header()) { + blockOrPixelSize = blockSize(header10.dxgiFormat); + isBlockFormat = (blockOrPixelSize != 0); + if (isBlockFormat) { + blockOrPixelSize = pixelSize(header10.dxgiFormat); + } + } + else { + header.pf.flags + } + if (isBlockFormat) { + w = (w + 3) / 4; + h = (h + 3) / 4; + d = (d + 3) / 4; // @@ Is it necessary to align the depths? + } - return 0; -} + uint blockOrPixelCount = w * h * d; + + return blockCount = blockOrPixelSize; +}*/ bool DirectDrawSurface::readSurface(uint face, uint mipmap, void * data, uint size) { - // - return false; + if (size != surfaceSize(mipmap)) return false; + + stream->seek(offset(face, mipmap)); + if (stream->isError()) return false; + + return stream->serialize(data, size) == size; } @@ -1225,75 +1426,48 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba) } -uint DirectDrawSurface::blockSize() const +static uint mipmapExtent(uint mipmap, uint x) { - switch(header.pf.fourcc) - { - case FOURCC_DXT1: - case FOURCC_ATI1: - return 8; - case FOURCC_DXT2: - case FOURCC_DXT3: - case FOURCC_DXT4: - case FOURCC_DXT5: - case FOURCC_RXGB: - case FOURCC_ATI2: - return 16; - case FOURCC_DX10: - switch(header.header10.dxgiFormat) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC4_SNORM: - return 8; - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC5_SNORM: - return 16; - }; - }; + for (uint m = 0; m < mipmap; m++) { + x = max(1U, x / 2); + } + return x; +} - // Not a block image. - return 0; +uint DirectDrawSurface::surfaceWidth(uint mipmap) const +{ + return mipmapExtent(mipmap, width()); } -uint DirectDrawSurface::mipmapSize(uint mipmap) const +uint DirectDrawSurface::surfaceHeight(uint mipmap) const { - uint w = width(); - uint h = height(); - uint d = depth(); + return mipmapExtent(mipmap, height()); +} - for (uint m = 0; m < mipmap; m++) - { - w = max(1U, w / 2); - h = max(1U, h / 2); - d = max(1U, d / 2); - } +uint DirectDrawSurface::surfaceDepth(uint mipmap) const +{ + return mipmapExtent(mipmap, depth()); +} - if (header.pf.flags & DDPF_FOURCC) - { - // @@ How are 3D textures aligned? - w = (w + 3) / 4; - h = (h + 3) / 4; - return blockSize() * w * h * d; - } - else - { - nvDebugCheck((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE)); +uint DirectDrawSurface::surfaceSize(uint mipmap) const +{ + uint w = surfaceWidth(mipmap); + uint h = surfaceHeight(mipmap); + uint d = surfaceDepth(mipmap); - uint pitch = computeBytePitch(w, header.pf.bitcount, 1); // Asuming 1 byte alignment, which is the same D3DX expects. + uint blockSize = header.blockSize(); + if (blockSize == 0) { + uint bitCount = header.pixelSize(); + uint pitch = computeBytePitch(w, bitCount, 1); // Asuming 1 byte alignment, which is the same D3DX expects. return pitch * h * d; } + else { + w = (w + 3) / 4; + h = (h + 3) / 4; + d = d; // @@ How are 3D textures aligned? + return blockSize * w * h * d; + } } uint DirectDrawSurface::faceSize() const @@ -1303,7 +1477,7 @@ uint DirectDrawSurface::faceSize() const for (uint m = 0; m < count; m++) { - size += mipmapSize(m); + size += surfaceSize(m); } return size; @@ -1325,7 +1499,7 @@ uint DirectDrawSurface::offset(const uint face, const uint mipmap) for (uint m = 0; m < mipmap; m++) { - size += mipmapSize(m); + size += surfaceSize(m); } return size; diff --git a/src/nvimage/DirectDrawSurface.h b/src/nvimage/DirectDrawSurface.h index c681538..ed02b8a 100644 --- a/src/nvimage/DirectDrawSurface.h +++ b/src/nvimage/DirectDrawSurface.h @@ -336,6 +336,9 @@ namespace nv bool isSrgb() const; bool hasAlpha() const; uint d3d9Format() const; + uint pixelSize() const; // In bits! + uint blockSize() const; // In bytes! + bool isBlockFormat() const; }; NVIMAGE_API Stream & operator<< (Stream & s, DDSHeader & header); @@ -373,25 +376,21 @@ namespace nv void mipmap(Image * img, uint f, uint m); + uint surfaceWidth(uint mipmap) const; + uint surfaceHeight(uint mipmap) const; + uint surfaceDepth(uint mipmap) const; uint surfaceSize(uint mipmap) const; bool readSurface(uint face, uint mipmap, void * data, uint size); - // void mipmap(FloatImage * img, uint f, uint m); - //void * readData(uint * sizePtr); - void printInfo() const; // Only initialized after loading. DDSHeader header; - DDSHeader10 header10; private: - uint blockSize() const; uint faceSize() const; - uint mipmapSize(uint m) const; - - uint offset(uint f, uint m); + uint offset(uint face, uint mipmap); void readLinearImage(Image * img); void readBlockImage(Image * img); diff --git a/src/nvimage/FloatImage.h b/src/nvimage/FloatImage.h index 608b440..672b79f 100644 --- a/src/nvimage/FloatImage.h +++ b/src/nvimage/FloatImage.h @@ -317,9 +317,9 @@ namespace nv inline uint FloatImage::indexClamp(int x, int y, int z) const { - x = wrapClamp(x, m_width - 1); - y = wrapClamp(y, m_height - 1); - z = wrapClamp(z, m_depth - 1); + x = wrapClamp(x, m_width); + y = wrapClamp(y, m_height); + z = wrapClamp(z, m_depth); return index(x, y, z); } diff --git a/src/nvimage/nvimage.h b/src/nvimage/nvimage.h index 8ddb931..e6edc55 100644 --- a/src/nvimage/nvimage.h +++ b/src/nvimage/nvimage.h @@ -34,11 +34,10 @@ namespace nv { return ((w * bitsize + alignmentInBits - 1) / alignmentInBits) * alignmentInBits; } - inline uint computeBytePitch(uint w, uint bitsize, uint alignmentInBits) + inline uint computeBytePitch(uint w, uint bitsize, uint alignmentInBytes) { - nvDebugCheck(alignmentInBits >= 8); - - uint pitch = computeBitPitch(w, bitsize, alignmentInBits); + uint pitch = computeBitPitch(w, bitsize, 8*alignmentInBytes); + nvDebugCheck((pitch & 7) == 0); return (pitch + 7) / 8; } diff --git a/src/nvtt/CubeSurface.cpp b/src/nvtt/CubeSurface.cpp index 1dc31ea..c37124b 100644 --- a/src/nvtt/CubeSurface.cpp +++ b/src/nvtt/CubeSurface.cpp @@ -102,7 +102,7 @@ const Surface & CubeSurface::face(int f) const } -bool CubeSurface::load(const char * fileName) +bool CubeSurface::load(const char * fileName, int mipmap) { if (strcmp(Path::extension(fileName), ".dds") == 0) { nv::DirectDrawSurface dds(fileName); @@ -116,41 +116,51 @@ bool CubeSurface::load(const char * fileName) } // Make sure it's a valid cube. - if (dds.header.width != dds.header.height) return false; - //if ((dds.header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) return false; + if (dds.header.width != dds.header.height) return false; + //if ((dds.header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) return false; + if (mipmap < 0) { + mipmap = dds.mipmapCount() - 1 - mipmap; + } + if (mipmap < 0 || mipmap > toI32(dds.mipmapCount())) return false; + nvtt::InputFormat inputFormat = nvtt::InputFormat_RGBA_16F; if (dds.header.hasDX10Header()) { - if (dds.header10.dxgiFormat == DXGI_FORMAT_R16G16B16A16_FLOAT) inputFormat = nvtt::InputFormat_RGBA_16F; - else if (dds.header10.dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT) inputFormat = nvtt::InputFormat_RGBA_32F; + if (dds.header.header10.dxgiFormat == DXGI_FORMAT_R16G16B16A16_FLOAT) inputFormat = nvtt::InputFormat_RGBA_16F; + else if (dds.header.header10.dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT) inputFormat = nvtt::InputFormat_RGBA_32F; else return false; } else { - if ((dds.header.pf.flags & DDPF_FOURCC) == 0) return false; - - if (dds.header.pf.fourcc == D3DFMT_A16B16G16R16F) inputFormat = nvtt::InputFormat_RGBA_16F; - else if (dds.header.pf.fourcc == D3DFMT_A32B32G32R32F) inputFormat = nvtt::InputFormat_RGBA_32F; - else return false; + if ((dds.header.pf.flags & DDPF_FOURCC) != 0) { + if (dds.header.pf.fourcc == D3DFMT_A16B16G16R16F) inputFormat = nvtt::InputFormat_RGBA_16F; + else if (dds.header.pf.fourcc == D3DFMT_A32B32G32R32F) inputFormat = nvtt::InputFormat_RGBA_32F; + else return false; + } + else { + if (dds.header.pf.bitcount == 32 /*&& ...*/) inputFormat = nvtt::InputFormat_BGRA_8UB; + else return false; // @@ Do pixel format conversions! + } } - uint edgeLength = dds.header.width; + uint edgeLength = dds.surfaceWidth(mipmap); + uint size = dds.surfaceSize(mipmap); - uint size = dds.surfaceSize(0); void * data = malloc(size); for (int f = 0; f < 6; f++) { - dds.readSurface(f, 0, data, size); + dds.readSurface(f, mipmap, data, size); m->face[f].setImage(inputFormat, edgeLength, edgeLength, 1, data); } m->edgeLength = edgeLength; free(data); + + return true; } - // @@ TODO return false; } @@ -180,20 +190,61 @@ CubeSurface CubeSurface::irradianceFilter(int size) const } + +// Solid angle of an axis aligned quad from (0,0,1) to (x,y,1) +// See: http://www.fizzmoll11.com/thesis/ for a derivation of this formula. +static float areaElement(float x, float y) { + return atan2(x*y, sqrtf(x*x + y*y + 1)); +} + +// Solid angle of a hemicube texel. +static float solidAngleTerm(uint x, uint y, float inverseEdgeLength) { + // Transform x,y to [-1, 1] range, offset by 0.5 to point to texel center. + float u = (float(x) + 0.5f) * (2 * inverseEdgeLength) - 1.0f; + float v = (float(y) + 0.5f) * (2 * inverseEdgeLength) - 1.0f; + nvDebugCheck(u >= -1.0f && u <= 1.0f); + nvDebugCheck(v >= -1.0f && v <= 1.0f); + +#if 1 + // Exact solid angle: + float x0 = u - inverseEdgeLength; + float y0 = v - inverseEdgeLength; + float x1 = u + inverseEdgeLength; + float y1 = v + inverseEdgeLength; + float solidAngle = areaElement(x0, y0) - areaElement(x0, y1) - areaElement(x1, y0) + areaElement(x1, y1); + nvDebugCheck(solidAngle > 0.0f); + + return solidAngle; +#else + // This formula is equivalent, but not as precise. + float pixel_area = nv::square(2.0f * inverseEdgeLength); + float dist_square = 1.0f + nv::square(u) + nv::square(v); + float cos_theta = 1.0f / sqrt(dist_square); + float cos_theta_d2 = cos_theta / dist_square; // Funny this is just 1/dist^3 or cos(tetha)^3 + + return pixel_area * cos_theta_d2; +#endif +} + + // Small solid angle table that takes into account cube map symmetry. struct SolidAngleTable { - SolidAngleTable(int edgeLength) : size(edgeLength/2) { + SolidAngleTable(uint edgeLength) : size(edgeLength/2) { // Allocate table. data.resize(size * size); - // @@ Init table. + // Init table. + const float inverseEdgeLength = 1.0f / edgeLength; + for (uint y = 0; y < size; y++) { + for (uint x = 0; x < size; x++) { + data[y * size + x] = solidAngleTerm(128+x, 128+y, inverseEdgeLength); + } + } } - - // - float lookup(int x, int y) const { + float lookup(uint x, uint y) const { if (x >= size) x -= size; else if (x < size) x = size - x - 1; if (y >= size) y -= size; @@ -202,18 +253,19 @@ struct SolidAngleTable { return data[y * size + x]; } - int size; + uint size; nv::Array data; }; // ilen = inverse edge length. -Vector3 texelDirection(uint face, uint x, uint y, float ilen) +static Vector3 texelDirection(uint face, uint x, uint y, float ilen) { + // Transform x,y to [-1, 1] range, offset by 0.5 to point to texel center. float u = (float(x) + 0.5f) * (2 * ilen) - 1.0f; float v = (float(y) + 0.5f) * (2 * ilen) - 1.0f; - nvDebugCheck(u >= 0.0f && u <= 1.0f); - nvDebugCheck(v >= 0.0f && v <= 1.0f); + nvDebugCheck(u >= -1.0f && u <= 1.0f); + nvDebugCheck(v >= -1.0f && v <= 1.0f); Vector3 n; @@ -257,6 +309,8 @@ struct VectorTable { VectorTable(uint edgeLength) : size(edgeLength) { float invEdgeLength = 1.0f / edgeLength; + data.resize(size*size*6); + for (uint f = 0; f < 6; f++) { for (uint y = 0; y < size; y++) { for (uint x = 0; x < size; x++) { @@ -287,7 +341,9 @@ CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower) const SolidAngleTable solidAngleTable(edgeLength); VectorTable vectorTable(edgeLength); -#if 1 + const float threshold = 0.0001f; + +#if 0 // Scatter approach. // For each texel of the input cube. @@ -315,13 +371,13 @@ CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower) const Vector3 filterDir = texelDirection(ff, xx, yy, 1.0f / size); - float power = powf(saturate(dot(texelDir, filterDir)), cosinePower); + float scale = powf(saturate(dot(texelDir, filterDir)), cosinePower); - if (power > 0.01) { - filteredFace->pixel(0, xx, yy, 0) += r * power; - filteredFace->pixel(1, xx, yy, 0) += g * power; - filteredFace->pixel(2, xx, yy, 0) += b * power; - filteredFace->pixel(3, xx, yy, 0) += solidAngle * power; + if (scale > threshold) { + filteredFace->pixel(0, xx, yy, 0) += r * scale; + filteredFace->pixel(1, xx, yy, 0) += g * scale; + filteredFace->pixel(2, xx, yy, 0) += b * scale; + filteredFace->pixel(3, xx, yy, 0) += solidAngle * scale; } } } @@ -360,10 +416,10 @@ CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower) const nvtt::Surface filteredFace = filteredCube.m->face[f]; FloatImage * filteredImage = filteredFace.m->image; - for (uint y = 0; y < size; y++) { - for (uint x = 0; x < size; x++) { + for (uint y = 0; y < uint(size); y++) { + for (uint x = 0; x < uint(size); x++) { - const Vector3 filterDir = texelDirection(f, x, y, size); + const Vector3 filterDir = texelDirection(f, x, y, 1.0f / size); Vector3 color(0); float sum = 0; @@ -379,11 +435,11 @@ CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower) const // @@ We should probably store solid angle and direction together. Vector3 inputDir = vectorTable.lookup(ff, xx, yy); - float power = powf(saturate(dot(inputDir, filterDir)), cosinePower); + float scale = powf(saturate(dot(inputDir, filterDir)), cosinePower); - if (power > 0.01f) { // @@ Adjustable threshold. + if (scale > threshold) { float solidAngle = solidAngleTable.lookup(xx, yy); - float contribution = solidAngle * power; + float contribution = solidAngle * scale; sum += contribution; @@ -391,9 +447,9 @@ CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower) const float g = inputImage->pixel(1, xx, yy, 0); float b = inputImage->pixel(2, xx, yy, 0); - color.r += r * contribution; - color.g += g * contribution; - color.b += b * contribution; + color.x += r * contribution; + color.y += g * contribution; + color.z += b * contribution; } } } diff --git a/src/nvtt/CubeSurface.h b/src/nvtt/CubeSurface.h index a7fe248..5863dca 100644 --- a/src/nvtt/CubeSurface.h +++ b/src/nvtt/CubeSurface.h @@ -65,7 +65,7 @@ namespace nvtt for (uint i = 0; i < 6; i++) { face[i].detach(); face[i].m->image = new nv::FloatImage; - face[i].m->image->allocate(edgeLength, edgeLength, 1); + face[i].m->image->allocate(4, edgeLength, edgeLength, 1); } } diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index 52e38fa..c58a2a9 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -548,15 +548,15 @@ namespace nvtt NVTT_API int countMipmaps() const; // Texture data. - NVTT_API bool load(const char * fileName); + NVTT_API bool load(const char * fileName, int mipmap); NVTT_API bool save(const char * fileName) const; - Surface & face(int face); - const Surface & face(int face) const; + NVTT_API Surface & face(int face); + NVTT_API const Surface & face(int face) const; // Layout conversion. @@ Not implemented. - void fold(const Surface & img, CubeLayout layout); - Surface unfold(CubeLayout layout) const; + NVTT_API void fold(const Surface & img, CubeLayout layout); + NVTT_API Surface unfold(CubeLayout layout) const; // @@ Angular extent filtering. @@ -565,8 +565,8 @@ namespace nvtt // @@ Add edge fixup methods. // Filtering. - CubeSurface irradianceFilter(int size) const; - CubeSurface cosinePowerFilter(int size, float cosinePower) const; + NVTT_API CubeSurface irradianceFilter(int size) const; + NVTT_API CubeSurface cosinePowerFilter(int size, float cosinePower) const; /* NVTT_API void resize(int w, int h, ResizeFilter filter);