| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| // OpenGL Image Copyright (c) 2008 - 2011 G-Truc Creation (www.g-truc.net) |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| // Created : 2010-09-08 |
| // Updated : 2010-09-27 |
| // Licence : This source is under MIT License |
| // File : gli/gtx/loader_dds9.inl |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| namespace gli{ |
| namespace gtx{ |
| namespace loader_dds9{ |
| namespace detail |
| { |
| // DDS Documentation |
| /* |
| http://msdn.microsoft.com/en-us/library/bb943991(VS.85).aspx#File_Layout1 |
| http://msdn.microsoft.com/en-us/library/bb943992.aspx |
| */ |
| |
| #define GLI_MAKEFOURCC(ch0, ch1, ch2, ch3) \ |
| (glm::uint32)( \ |
| (((glm::uint32)(glm::uint8)(ch3) << 24) & 0xFF000000) | \ |
| (((glm::uint32)(glm::uint8)(ch2) << 16) & 0x00FF0000) | \ |
| (((glm::uint32)(glm::uint8)(ch1) << 8) & 0x0000FF00) | \ |
| ((glm::uint32)(glm::uint8)(ch0) & 0x000000FF) ) |
| |
| //enum dds_format |
| //{ |
| // GLI_D3DFMT_R8G8B8 = 20, |
| // GLI_D3DFMT_A8R8G8B8 = 21, |
| // GLI_D3DFMT_X8R8G8B8 = 22, |
| // GLI_D3DFMT_A8 = 28, |
| // GLI_D3DFMT_A2B10G10R10 = 31, |
| // GLI_D3DFMT_A8B8G8R8 = 32, |
| // GLI_D3DFMT_X8B8G8R8 = 33, |
| // GLI_D3DFMT_G16R16 = 34, |
| // GLI_D3DFMT_A2R10G10B10 = 35, |
| // GLI_D3DFMT_A16B16G16R16 = 36, |
| |
| // GLI_D3DFMT_L8 = 50, |
| // GLI_D3DFMT_A8L8 = 51, |
| |
| // GLI_D3DFMT_DXT1 = GLI_MAKEFOURCC('D', 'X', 'T', '1'), |
| // GLI_D3DFMT_DXT2 = GLI_MAKEFOURCC('D', 'X', 'T', '2'), |
| // GLI_D3DFMT_DXT3 = GLI_MAKEFOURCC('D', 'X', 'T', '3'), |
| // GLI_D3DFMT_DXT4 = GLI_MAKEFOURCC('D', 'X', 'T', '4'), |
| // GLI_D3DFMT_DXT5 = GLI_MAKEFOURCC('D', 'X', 'T', '5'), |
| // GLI_D3DFMT_DX10 = GLI_MAKEFOURCC('D', 'X', '1', '0'), |
| |
| // GLI_D3DFMT_D32 = 71, |
| // GLI_D3DFMT_D24S8 = 75, |
| // GLI_D3DFMT_D24X8 = 77, |
| // GLI_D3DFMT_D16 = 80, |
| // GLI_D3DFMT_L16 = 81, |
| // GLI_D3DFMT_D32F_LOCKABLE = 82, |
| // GLI_D3DFMT_D24FS8 = 83, |
| |
| // GLI_D3DFMT_R16F = 111, |
| // GLI_D3DFMT_G16R16F = 112, |
| // GLI_D3DFMT_A16B16G16R16F = 113, |
| |
| // GLI_D3DFMT_R32F = 114, |
| // GLI_D3DFMT_G32R32F = 115, |
| // GLI_D3DFMT_A32B32G32R32F = 116 |
| //}; |
| |
| enum ddsCubemapflag |
| { |
| GLI_DDSCAPS2_CUBEMAP = 0x00000200, |
| GLI_DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400, |
| GLI_DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800, |
| GLI_DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000, |
| GLI_DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000, |
| GLI_DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000, |
| GLI_DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000, |
| GLI_DDSCAPS2_VOLUME = 0x00200000 |
| }; |
| |
| enum ddsSurfaceflag |
| { |
| GLI_DDSCAPS_COMPLEX = 0x00000008, |
| GLI_DDSCAPS_MIPMAP = 0x00400000, |
| GLI_DDSCAPS_TEXTURE = 0x00001000 |
| }; |
| |
| struct ddsPixelFormat |
| { |
| glm::uint32 size; // 32 |
| glm::uint32 flags; |
| glm::uint32 fourCC; |
| glm::uint32 bpp; |
| glm::uint32 redMask; |
| glm::uint32 greenMask; |
| glm::uint32 blueMask; |
| glm::uint32 alphaMask; |
| }; |
| |
| struct ddsHeader |
| { |
| glm::uint32 size; |
| glm::uint32 flags; |
| glm::uint32 height; |
| glm::uint32 width; |
| glm::uint32 pitch; |
| glm::uint32 depth; |
| glm::uint32 mipMapLevels; |
| glm::uint32 reserved1[11]; |
| ddsPixelFormat format; |
| glm::uint32 surfaceFlags; |
| glm::uint32 cubemapFlags; |
| glm::uint32 reserved2[3]; |
| }; |
| |
| glm::uint32 const GLI_D3DFMT_R8G8B8 = 20; |
| glm::uint32 const GLI_D3DFMT_A8R8G8B8 = 21; |
| glm::uint32 const GLI_D3DFMT_X8R8G8B8 = 22; |
| glm::uint32 const GLI_D3DFMT_R5G6B5 = 23; |
| glm::uint32 const GLI_D3DFMT_X1R5G5B5 = 24; |
| glm::uint32 const GLI_D3DFMT_A1R5G5B5 = 25; |
| glm::uint32 const GLI_D3DFMT_A4R4G4B4 = 26; |
| glm::uint32 const GLI_D3DFMT_X4R4G4B4 = 30; |
| glm::uint32 const GLI_D3DFMT_A2B10G10R10 = 31; |
| glm::uint32 const GLI_D3DFMT_A8B8G8R8 = 32; |
| glm::uint32 const GLI_D3DFMT_X8B8G8R8 = 33; |
| glm::uint32 const GLI_D3DFMT_G16R16 = 34; |
| glm::uint32 const GLI_D3DFMT_A2R10G10B10 = 35; |
| glm::uint32 const GLI_D3DFMT_A16B16G16R16 = 36; |
| |
| |
| glm::uint32 const GLI_FOURCC_DXT1 = GLI_MAKEFOURCC('D', 'X', 'T', '1'); |
| glm::uint32 const GLI_FOURCC_DXT2 = GLI_MAKEFOURCC('D', 'X', 'T', '2'); |
| glm::uint32 const GLI_FOURCC_DXT3 = GLI_MAKEFOURCC('D', 'X', 'T', '3'); |
| glm::uint32 const GLI_FOURCC_DXT4 = GLI_MAKEFOURCC('D', 'X', 'T', '4'); |
| glm::uint32 const GLI_FOURCC_DXT5 = GLI_MAKEFOURCC('D', 'X', 'T', '5'); |
| glm::uint32 const GLI_FOURCC_ATI1 = GLI_MAKEFOURCC('A', 'T', 'I', '1'); // ATI1 |
| glm::uint32 const GLI_FOURCC_ATI2 = GLI_MAKEFOURCC('A', 'T', 'I', '2'); // ATI2 (AKA 3Dc) |
| glm::uint32 const GLI_FOURCC_DX10 = GLI_MAKEFOURCC('D', 'X', '1', '0'); |
| glm::uint32 const GLI_FOURCC_BC4U = GLI_MAKEFOURCC('B', 'C', '4', 'U'); |
| glm::uint32 const GLI_FOURCC_BC4S = GLI_MAKEFOURCC('B', 'C', '4', 'S'); |
| glm::uint32 const GLI_FOURCC_BC5U = GLI_MAKEFOURCC('B', 'C', '5', 'U'); |
| glm::uint32 const GLI_FOURCC_BC5S = GLI_MAKEFOURCC('B', 'C', '5', 'S'); |
| glm::uint32 const GLI_FOURCC_BC6H = GLI_MAKEFOURCC('B', 'C', '6', 'H'); |
| glm::uint32 const GLI_FOURCC_BC7 = GLI_MAKEFOURCC('B', 'C', '7', 'U'); |
| |
| glm::uint32 const GLI_FOURCC_R16F = 0x0000006f; // 16-bit float Red |
| glm::uint32 const GLI_FOURCC_G16R16F = 0x00000070; // 16-bit float Red/Green |
| glm::uint32 const GLI_FOURCC_A16B16G16R16F = 0x00000071; // 16-bit float RGBA |
| glm::uint32 const GLI_FOURCC_R32F = 0x00000072; // 32-bit float Red |
| glm::uint32 const GLI_FOURCC_G32R32F = 0x00000073; // 32-bit float Red/Green |
| glm::uint32 const GLI_FOURCC_A32B32G32R32F = 0x00000074; // 32-bit float RGBA |
| |
| glm::uint32 const GLI_DDPF_ALPHAPIXELS = 0x00000001; // The surface has alpha channel information in the pixel format. |
| glm::uint32 const GLI_DDPF_ALPHA = 0x00000002; // The pixel format contains alpha only information |
| glm::uint32 const GLI_DDPF_FOURCC = 0x00000004; // The FourCC code is valid. |
| glm::uint32 const GLI_DDPF_RGB = 0x00000040; // The RGB data in the pixel format structure is valid. |
| //glm::uint32 const GLI_DDPF_COMPRESSED = 0x00000080; // The surface will accept pixel data in the format specified and compress it during the write. |
| //glm::uint32 const GLI_DDPF_RGBTOYUV = 0x00000100; // The surface will accept RGB data and translate it during the write to YUV data. |
| glm::uint32 const GLI_DDPF_YUV = 0x00000200; // Pixel format is YUV - YUV data in pixel format struct is valid. |
| //glm::uint32 const GLI_DDPF_ZBUFFER = 0x00000400; // Pixel format is a z buffer only surface |
| //glm::uint32 const GLI_DDPF_ZPIXELS = 0x00002000; // The surface contains Z information in the pixels |
| //glm::uint32 const GLI_DDPF_STENCILBUFFER = 0x00004000; // The surface contains stencil information along with Z |
| //glm::uint32 const GLI_DDPF_ALPHAPREMULT = 0x00008000; // Premultiplied alpha format -- the color components have been premultiplied by the alpha component. |
| glm::uint32 const GLI_DDPF_LUMINANCE = 0x00020000; // Luminance data in the pixel format is valid. |
| //glm::uint32 const GLI_DDPF_BUMPLUMINANCE = 0x00040000; // Use this flag for luminance-only or luminance+alpha surfaces, the bit depth is then ddpf.dwLuminanceBitCount. |
| //glm::uint32 const GLI_DDPF_BUMPDUDV = 0x00080000; // Bump map dUdV data in the pixel format is valid. |
| |
| glm::uint32 const GLI_DDSD_CAPS = 0x00000001; |
| glm::uint32 const GLI_DDSD_HEIGHT = 0x00000002; |
| glm::uint32 const GLI_DDSD_WIDTH = 0x00000004; |
| glm::uint32 const GLI_DDSD_PITCH = 0x00000008; |
| glm::uint32 const GLI_DDSD_PIXELFORMAT = 0x00001000; |
| glm::uint32 const GLI_DDSD_MIPMAPCOUNT = 0x00020000; |
| glm::uint32 const GLI_DDSD_LINEARSIZE = 0x00080000; |
| glm::uint32 const GLI_DDSD_DEPTH = 0x00800000; |
| |
| struct DDLoader |
| { |
| glm::uint32 BlockSize; |
| glm::uint32 BPP; |
| gli::format Format; |
| }; |
| |
| enum format_type |
| { |
| FORMAT_TYPE_NULL, |
| FORMAT_RGBA, |
| FORMAT_FOURCC |
| }; |
| |
| inline glm::uint32 getFormatFourCC(gli::texture2D const & Image) |
| { |
| switch(Image.format()) |
| { |
| default: |
| return 0; |
| case DXT1: |
| return GLI_FOURCC_DXT1; |
| case DXT3: |
| return GLI_FOURCC_DXT3; |
| case DXT5: |
| return GLI_FOURCC_DXT5; |
| case ATI1N_UNORM: |
| case ATI1N_SNORM: |
| case ATI2N_UNORM: |
| case ATI2N_SNORM: |
| case BP_UF16: |
| case BP_SF16: |
| case BP: |
| return GLI_FOURCC_DX10; |
| case R16F: |
| return GLI_FOURCC_R16F; |
| case RG16F: |
| return GLI_FOURCC_G16R16F; |
| case RGBA16F: |
| return GLI_FOURCC_A16B16G16R16F; |
| case R32F: |
| return GLI_FOURCC_R32F; |
| case RG32F: |
| return GLI_FOURCC_G32R32F; |
| case RGBA32F: |
| return GLI_FOURCC_A32B32G32R32F; |
| } |
| } |
| |
| inline glm::uint32 getFormatBlockSize(gli::texture2D const & Image) |
| { |
| switch(Image.format()) |
| { |
| default: |
| return 0; |
| case DXT1: |
| return 8; |
| case DXT3: |
| return 16; |
| case DXT5: |
| return 16; |
| case ATI1N_UNORM: |
| case ATI1N_SNORM: |
| return 16; |
| case ATI2N_UNORM: |
| case ATI2N_SNORM: |
| return 32; |
| case BP_UF16: |
| case BP_SF16: |
| return 32; |
| case BP: |
| return 32; |
| case R16F: |
| return 2; |
| case RG16F: |
| return 4; |
| case RGBA16F: |
| return 8; |
| case R32F: |
| return 4; |
| case RG32F: |
| return 8; |
| case RGBA32F: |
| return 16; |
| } |
| } |
| |
| inline glm::uint32 getFormatFlags(gli::texture2D const & Image) |
| { |
| glm::uint32 Result = 0; |
| |
| switch(Image.format()) |
| { |
| default: |
| break; |
| case R8U: |
| case RG8U: |
| case RGB8U: |
| case RGBA8U: |
| case R16U: |
| case RG16U: |
| case RGB16U: |
| case RGBA16U: |
| case R32U: |
| case RG32U: |
| case RGB32U: |
| case RGBA32U: |
| case R8I: |
| case RG8I: |
| case RGB8I: |
| case RGBA8I: |
| case R16I: |
| case RG16I: |
| case RGB16I: |
| case RGBA16I: |
| case R32I: |
| case RG32I: |
| case RGB32I: |
| case RGBA32I: |
| Result |= GLI_DDPF_RGB; |
| break; |
| case R16F: |
| case RG16F: |
| case RGB16F: |
| case RGBA16F: |
| case R32F: |
| case RG32F: |
| case RGB32F: |
| case RGBA32F: |
| case RGBE8: |
| case RGB9E5: |
| case RG11B10F: |
| case R5G6B5: |
| case RGBA4: |
| case RGB10A2: |
| case D16: |
| case D24X8: |
| case D24S8: |
| case D32F: |
| case D32FS8X24: |
| case DXT1: |
| case DXT3: |
| case DXT5: |
| case ATI1N_UNORM: |
| case ATI1N_SNORM: |
| case ATI2N_UNORM: |
| case ATI2N_SNORM: |
| case BP_UF16: |
| case BP_SF16: |
| case BP: |
| Result |= GLI_DDPF_FOURCC; |
| break; |
| }; |
| |
| return Result; |
| } |
| |
| inline glm::uint32 getFormatBPP(gli::texture2D const & Image) |
| { |
| switch(Image.format()) |
| { |
| default: |
| return 0; |
| case R8U: |
| case R8I: |
| return 8; |
| case RG8U: |
| case RG8I: |
| return 16; |
| case RGB8U: |
| case RGB8I: |
| return 24; |
| case RGBA8U: |
| case RGBA8I: |
| return 32; |
| case DXT1: |
| return 4; |
| case DXT3: |
| return 8; |
| case DXT5: |
| return 8; |
| case ATI1N_UNORM: |
| case ATI1N_SNORM: |
| return 4; |
| case ATI2N_UNORM: |
| case ATI2N_SNORM: |
| return 8; |
| case BP_UF16: |
| case BP_SF16: |
| return 8; |
| case BP: |
| return 8; |
| } |
| } |
| |
| inline bool isCompressed(gli::texture2D const & Image) |
| { |
| switch(Image.format()) |
| { |
| default: |
| return false; |
| case DXT1: |
| case DXT3: |
| case DXT5: |
| case ATI1N_UNORM: |
| case ATI1N_SNORM: |
| case ATI2N_UNORM: |
| case ATI2N_SNORM: |
| case BP_UF16: |
| case BP_SF16: |
| case BP: |
| return true; |
| } |
| return false; |
| } |
| |
| }//namespace detail |
| |
| inline texture2D loadDDS9 |
| ( |
| std::string const & Filename |
| ) |
| { |
| std::ifstream FileIn(Filename.c_str(), std::ios::in | std::ios::binary); |
| if(FileIn.fail()) |
| return texture2D(); |
| |
| detail::ddsHeader SurfaceDesc; |
| char Magic[4]; |
| |
| //* Read magic number and check if valid .dds file |
| FileIn.read((char*)&Magic, sizeof(Magic)); |
| |
| assert(strncmp(Magic, "DDS ", 4) == 0); |
| |
| // Get the surface descriptor |
| FileIn.read((char*)&SurfaceDesc, sizeof(SurfaceDesc)); |
| |
| std::size_t Width = SurfaceDesc.width; |
| std::size_t Height = SurfaceDesc.height; |
| |
| //std::size_t Levels = glm::max(glm::highestBit(Width), glm::highestBit(Height)); |
| |
| detail::DDLoader Loader; |
| if(SurfaceDesc.format.flags & detail::GLI_DDPF_FOURCC) |
| { |
| switch(SurfaceDesc.format.fourCC) |
| { |
| case detail::GLI_FOURCC_DX10: |
| assert(0); |
| break; |
| case detail::GLI_FOURCC_DXT1: |
| Loader.BlockSize = 8; |
| Loader.Format = DXT1; |
| break; |
| case detail::GLI_FOURCC_DXT3: |
| Loader.BlockSize = 16; |
| Loader.Format = DXT3; |
| break; |
| case detail::GLI_FOURCC_DXT5: |
| Loader.BlockSize = 16; |
| Loader.Format = DXT5; |
| break; |
| case detail::GLI_FOURCC_R16F: |
| Loader.BlockSize = 2; |
| Loader.Format = R16F; |
| break; |
| case detail::GLI_FOURCC_G16R16F: |
| Loader.BlockSize = 4; |
| Loader.Format = RG16F; |
| break; |
| case detail::GLI_FOURCC_A16B16G16R16F: |
| Loader.BlockSize = 8; |
| Loader.Format = RGBA16F; |
| break; |
| case detail::GLI_FOURCC_R32F: |
| Loader.BlockSize = 4; |
| Loader.Format = R32F; |
| break; |
| case detail::GLI_FOURCC_G32R32F: |
| Loader.BlockSize = 8; |
| Loader.Format = RG32F; |
| break; |
| case detail::GLI_FOURCC_A32B32G32R32F: |
| Loader.BlockSize = 16; |
| Loader.Format = RGBA32F; |
| break; |
| |
| default: |
| assert(0); |
| return texture2D(); |
| } |
| } |
| else if(SurfaceDesc.format.flags & detail::GLI_DDPF_RGB) |
| { |
| switch(SurfaceDesc.format.bpp) |
| { |
| case 8: |
| Loader.BlockSize = 2; |
| Loader.Format = R8U; |
| break; |
| case 16: |
| Loader.BlockSize = 2; |
| Loader.Format = RG8U; |
| break; |
| case 24: |
| Loader.BlockSize = 3; |
| Loader.Format = RGB8U; |
| break; |
| case 32: |
| Loader.BlockSize = 4; |
| Loader.Format = RGBA8U; |
| break; |
| } |
| } |
| else |
| { |
| |
| } |
| |
| gli::format Format = Loader.Format; |
| |
| std::streamoff Curr = FileIn.tellg(); |
| FileIn.seekg(0, std::ios_base::end); |
| std::streamoff End = FileIn.tellg(); |
| FileIn.seekg(Curr, std::ios_base::beg); |
| |
| std::vector<glm::byte> Data(std::size_t(End - Curr), 0); |
| std::size_t Offset = 0; |
| |
| FileIn.read((char*)&Data[0], std::streamsize(Data.size())); |
| |
| //image Image(glm::min(MipMapCount, Levels));//SurfaceDesc.mipMapLevels); |
| std::size_t MipMapCount = (SurfaceDesc.flags & detail::GLI_DDSD_MIPMAPCOUNT) ? SurfaceDesc.mipMapLevels : 1; |
| //if(Loader.Format == DXT1 || Loader.Format == DXT3 || Loader.Format == DXT5) |
| // MipMapCount -= 2; |
| texture2D Image(MipMapCount); |
| for(std::size_t Level = 0; Level < Image.levels() && (Width || Height); ++Level) |
| { |
| Width = glm::max(std::size_t(Width), std::size_t(1)); |
| Height = glm::max(std::size_t(Height), std::size_t(1)); |
| |
| std::size_t MipmapSize = 0; |
| if(Loader.Format == DXT1 || Loader.Format == DXT3 || Loader.Format == DXT5) |
| MipmapSize = ((Width + 3) >> 2) * ((Height + 3) >> 2) * Loader.BlockSize; |
| else |
| MipmapSize = Width * Height * Loader.BlockSize; |
| std::vector<glm::byte> MipmapData(MipmapSize, 0); |
| |
| memcpy(&MipmapData[0], &Data[0] + Offset, MipmapSize); |
| |
| image2D::dimensions_type Dimensions(Width, Height); |
| Image[Level] = image2D(Dimensions, Format, MipmapData); |
| |
| Offset += MipmapSize; |
| Width >>= 1; |
| Height >>= 1; |
| } |
| |
| return Image; |
| } |
| |
| inline textureCube loadTextureCubeDDS9 |
| ( |
| std::string const & Filename |
| ) |
| { |
| std::ifstream FileIn(Filename.c_str(), std::ios::in | std::ios::binary); |
| if(FileIn.fail()) |
| return textureCube(); |
| |
| detail::ddsHeader SurfaceDesc; |
| char Magic[4]; |
| |
| //* Read magic number and check if valid .dds file |
| FileIn.read((char*)&Magic, sizeof(Magic)); |
| |
| assert(strncmp(Magic, "DDS ", 4) == 0); |
| |
| // Get the surface descriptor |
| FileIn.read((char*)&SurfaceDesc, sizeof(SurfaceDesc)); |
| |
| std::size_t Width = SurfaceDesc.width; |
| std::size_t Height = SurfaceDesc.height; |
| |
| //std::size_t Levels = glm::max(glm::highestBit(Width), glm::highestBit(Height)); |
| |
| detail::DDLoader Loader; |
| if(SurfaceDesc.format.flags & detail::GLI_DDPF_FOURCC) |
| { |
| switch(SurfaceDesc.format.fourCC) |
| { |
| case detail::GLI_FOURCC_DX10: |
| assert(0); |
| break; |
| case detail::GLI_FOURCC_DXT1: |
| Loader.BlockSize = 8; |
| Loader.Format = DXT1; |
| break; |
| case detail::GLI_FOURCC_DXT3: |
| Loader.BlockSize = 16; |
| Loader.Format = DXT3; |
| break; |
| case detail::GLI_FOURCC_DXT5: |
| Loader.BlockSize = 16; |
| Loader.Format = DXT5; |
| break; |
| case detail::GLI_FOURCC_R16F: |
| Loader.BlockSize = 2; |
| Loader.Format = R16F; |
| break; |
| case detail::GLI_FOURCC_G16R16F: |
| Loader.BlockSize = 4; |
| Loader.Format = RG16F; |
| break; |
| case detail::GLI_FOURCC_A16B16G16R16F: |
| Loader.BlockSize = 8; |
| Loader.Format = RGBA16F; |
| break; |
| case detail::GLI_FOURCC_R32F: |
| Loader.BlockSize = 4; |
| Loader.Format = R32F; |
| break; |
| case detail::GLI_FOURCC_G32R32F: |
| Loader.BlockSize = 8; |
| Loader.Format = RG32F; |
| break; |
| case detail::GLI_FOURCC_A32B32G32R32F: |
| Loader.BlockSize = 16; |
| Loader.Format = RGBA32F; |
| break; |
| |
| default: |
| assert(0); |
| return textureCube(); |
| } |
| } |
| else if(SurfaceDesc.format.flags & detail::GLI_DDPF_RGB) |
| { |
| switch(SurfaceDesc.format.bpp) |
| { |
| case 8: |
| Loader.BlockSize = 2; |
| Loader.Format = R8U; |
| break; |
| case 16: |
| Loader.BlockSize = 2; |
| Loader.Format = RG8U; |
| break; |
| case 24: |
| Loader.BlockSize = 3; |
| Loader.Format = RGB8U; |
| break; |
| case 32: |
| Loader.BlockSize = 4; |
| Loader.Format = RGBA8U; |
| break; |
| } |
| } |
| else |
| { |
| |
| } |
| |
| gli::format Format = Loader.Format; |
| |
| std::streamoff Curr = FileIn.tellg(); |
| FileIn.seekg(0, std::ios_base::end); |
| std::streamoff End = FileIn.tellg(); |
| FileIn.seekg(Curr, std::ios_base::beg); |
| |
| std::vector<glm::byte> Data(std::size_t(End - Curr), 0); |
| std::size_t Offset = 0; |
| |
| FileIn.read((char*)&Data[0], std::streamsize(Data.size())); |
| |
| //image Image(glm::min(MipMapCount, Levels));//SurfaceDesc.mipMapLevels); |
| std::size_t MipMapCount = (SurfaceDesc.flags & detail::GLI_DDSD_MIPMAPCOUNT) ? SurfaceDesc.mipMapLevels : 1; |
| //if(Loader.Format == DXT1 || Loader.Format == DXT3 || Loader.Format == DXT5) |
| // MipMapCount -= 2; |
| textureCube Texture(MipMapCount); |
| |
| for(textureCube::size_type Face = 0; Face < FACE_MAX; ++Face) |
| { |
| Width = SurfaceDesc.width; |
| Height = SurfaceDesc.height; |
| |
| for(textureCube::size_type Level = 0; Level < Texture.levels() && (Width || Height); ++Level) |
| { |
| Width = glm::max(std::size_t(Width), std::size_t(1)); |
| Height = glm::max(std::size_t(Height), std::size_t(1)); |
| |
| std::size_t MipmapSize = 0; |
| if(Loader.Format == DXT1 || Loader.Format == DXT3 || Loader.Format == DXT5) |
| MipmapSize = ((Width + 3) >> 2) * ((Height + 3) >> 2) * Loader.BlockSize; |
| else |
| MipmapSize = Width * Height * Loader.BlockSize; |
| std::vector<glm::byte> MipmapData(MipmapSize, 0); |
| |
| memcpy(&MipmapData[0], &Data[0] + Offset, MipmapSize); |
| |
| textureCube::dimensions_type Dimensions(Width, Height); |
| Texture[textureCube::face_type(Face)][Level] = image2D(Dimensions, Format, MipmapData); |
| |
| Offset += MipmapSize; |
| Width >>= 1; |
| Height >>= 1; |
| } |
| } |
| |
| return Texture; |
| } |
| |
| inline void saveDDS9 |
| ( |
| texture2D const & Texture, |
| std::string const & Filename |
| ) |
| { |
| std::ofstream FileOut(Filename.c_str(), std::ios::out | std::ios::binary); |
| if (!FileOut) |
| return; |
| |
| char const * Magic = "DDS "; |
| FileOut.write((char*)Magic, sizeof(char) * 4); |
| |
| glm::uint32 Caps = detail::GLI_DDSD_CAPS | detail::GLI_DDSD_HEIGHT | detail::GLI_DDSD_WIDTH | detail::GLI_DDSD_PIXELFORMAT; |
| |
| detail::ddsHeader SurfaceDesc; |
| SurfaceDesc.size = sizeof(detail::ddsHeader); |
| SurfaceDesc.flags = Caps | (detail::isCompressed(Texture) ? detail::GLI_DDSD_LINEARSIZE : detail::GLI_DDSD_PITCH) | (Texture.levels() > 1 ? detail::GLI_DDSD_MIPMAPCOUNT : 0); //659463; |
| SurfaceDesc.width = Texture[0].dimensions().x; |
| SurfaceDesc.height = Texture[0].dimensions().y; |
| SurfaceDesc.pitch = loader_dds9::detail::isCompressed(Texture) ? size(Texture, LINEAR_SIZE) : 32; |
| SurfaceDesc.depth = 0; |
| SurfaceDesc.mipMapLevels = glm::uint32(Texture.levels()); |
| SurfaceDesc.format.size = sizeof(detail::ddsPixelFormat); |
| SurfaceDesc.format.flags = detail::getFormatFlags(Texture); |
| SurfaceDesc.format.fourCC = detail::getFormatFourCC(Texture); |
| SurfaceDesc.format.bpp = detail::getFormatBPP(Texture); |
| SurfaceDesc.format.redMask = 0; |
| SurfaceDesc.format.greenMask = 0; |
| SurfaceDesc.format.blueMask = 0; |
| SurfaceDesc.format.alphaMask = 0; |
| SurfaceDesc.surfaceFlags = detail::GLI_DDSCAPS_TEXTURE | (Texture.levels() > 1 ? detail::GLI_DDSCAPS_MIPMAP : 0); |
| SurfaceDesc.cubemapFlags = 0; |
| |
| FileOut.write((char*)&SurfaceDesc, sizeof(SurfaceDesc)); |
| |
| for(texture2D::level_type Level = 0; Level < Texture.levels(); ++Level) |
| { |
| texture2D::size_type ImageSize = size(Texture[Level], gli::LINEAR_SIZE); |
| FileOut.write((char*)(Texture[Level].data()), ImageSize); |
| } |
| |
| if(FileOut.fail() || FileOut.bad()) |
| return; |
| |
| FileOut.close (); |
| } |
| |
| inline void saveTextureCubeDDS9 |
| ( |
| textureCube const & Texture, |
| std::string const & Filename |
| ) |
| { |
| std::ofstream FileOut(Filename.c_str(), std::ios::out | std::ios::binary); |
| if (!FileOut || Texture.empty()) |
| return; |
| |
| char const * Magic = "DDS "; |
| FileOut.write((char*)Magic, sizeof(char) * 4); |
| |
| glm::uint32 Caps = detail::GLI_DDSD_CAPS | detail::GLI_DDSD_HEIGHT | detail::GLI_DDSD_WIDTH | detail::GLI_DDSD_PIXELFORMAT | detail::GLI_DDSCAPS_COMPLEX; |
| |
| detail::ddsHeader SurfaceDesc; |
| SurfaceDesc.size = sizeof(detail::ddsHeader); |
| SurfaceDesc.flags = Caps | (detail::isCompressed(Texture[POSITIVE_X]) ? detail::GLI_DDSD_LINEARSIZE : detail::GLI_DDSD_PITCH) | (Texture.levels() > 1 ? detail::GLI_DDSD_MIPMAPCOUNT : 0); //659463; |
| SurfaceDesc.width = Texture[POSITIVE_X][0].dimensions().x; |
| SurfaceDesc.height = Texture[POSITIVE_X][0].dimensions().y; |
| SurfaceDesc.pitch = loader_dds9::detail::isCompressed(Texture[POSITIVE_X]) ? size(Texture[POSITIVE_X], LINEAR_SIZE) : 32; |
| SurfaceDesc.depth = 0; |
| SurfaceDesc.mipMapLevels = glm::uint32(Texture.levels()); |
| SurfaceDesc.format.size = sizeof(detail::ddsPixelFormat); |
| SurfaceDesc.format.flags = detail::getFormatFlags(Texture[POSITIVE_X]); |
| SurfaceDesc.format.fourCC = detail::getFormatFourCC(Texture[POSITIVE_X]); |
| SurfaceDesc.format.bpp = detail::getFormatBPP(Texture[POSITIVE_X]); |
| SurfaceDesc.format.redMask = 0; |
| SurfaceDesc.format.greenMask = 0; |
| SurfaceDesc.format.blueMask = 0; |
| SurfaceDesc.format.alphaMask = 0; |
| SurfaceDesc.surfaceFlags = detail::GLI_DDSCAPS_TEXTURE | (Texture.levels() > 1 ? detail::GLI_DDSCAPS_MIPMAP : 0); |
| SurfaceDesc.cubemapFlags = |
| detail::GLI_DDSCAPS2_CUBEMAP | detail::GLI_DDSCAPS2_CUBEMAP_POSITIVEX | detail::GLI_DDSCAPS2_CUBEMAP_NEGATIVEX | detail::GLI_DDSCAPS2_CUBEMAP_POSITIVEY | detail::GLI_DDSCAPS2_CUBEMAP_NEGATIVEY | detail::GLI_DDSCAPS2_CUBEMAP_POSITIVEZ | detail::GLI_DDSCAPS2_CUBEMAP_NEGATIVEZ; |
| |
| FileOut.write((char*)&SurfaceDesc, sizeof(SurfaceDesc)); |
| |
| for(textureCube::size_type Face = 0; Face < FACE_MAX; ++Face) |
| for(texture2D::level_type Level = 0; Level < Texture.levels(); ++Level) |
| { |
| texture2D::size_type ImageSize = size(Texture[textureCube::face_type(Face)][Level], gli::LINEAR_SIZE); |
| FileOut.write((char*)(Texture[textureCube::face_type(Face)][Level].data()), ImageSize); |
| } |
| |
| if(FileOut.fail() || FileOut.bad()) |
| return; |
| |
| FileOut.close (); |
| } |
| |
| }//namespace loader_dds9 |
| }//namespace gtx |
| }//namespace gli |