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);