import Texture from '../Texture'; import Texture2D from '../Texture2D'; import TextureCube from '../TextureCube'; // http://msdn.microsoft.com/en-us/library/windows/desktop/bb943991(v=vs.85).aspx // https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js var DDS_MAGIC = 0x20534444; var DDSD_CAPS = 0x1; var DDSD_HEIGHT = 0x2; var DDSD_WIDTH = 0x4; var DDSD_PITCH = 0x8; var DDSD_PIXELFORMAT = 0x1000; var DDSD_MIPMAPCOUNT = 0x20000; var DDSD_LINEARSIZE = 0x80000; var DDSD_DEPTH = 0x800000; var DDSCAPS_COMPLEX = 0x8; var DDSCAPS_MIPMAP = 0x400000; var DDSCAPS_TEXTURE = 0x1000; var DDSCAPS2_CUBEMAP = 0x200; var DDSCAPS2_CUBEMAP_POSITIVEX = 0x400; var DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800; var DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000; var DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000; var DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000; var DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; var DDSCAPS2_VOLUME = 0x200000; var DDPF_ALPHAPIXELS = 0x1; var DDPF_ALPHA = 0x2; var DDPF_FOURCC = 0x4; var DDPF_RGB = 0x40; var DDPF_YUV = 0x200; var DDPF_LUMINANCE = 0x20000; function fourCCToInt32(value) { return value.charCodeAt(0) + (value.charCodeAt(1) << 8) + (value.charCodeAt(2) << 16) + (value.charCodeAt(3) << 24); } function int32ToFourCC(value) { return String.fromCharCode( value & 0xff, (value >> 8) & 0xff, (value >> 16) & 0xff, (value >> 24) & 0xff ); } var headerLengthInt = 31; // The header length in 32 bit ints var FOURCC_DXT1 = fourCCToInt32('DXT1'); var FOURCC_DXT3 = fourCCToInt32('DXT3'); var FOURCC_DXT5 = fourCCToInt32('DXT5'); // Offsets into the header array var off_magic = 0; var off_size = 1; var off_flags = 2; var off_height = 3; var off_width = 4; var off_mipmapCount = 7; var off_pfFlags = 20; var off_pfFourCC = 21; var off_caps = 27; var off_caps2 = 28; var off_caps3 = 29; var off_caps4 = 30; var ret = { parse: function(arrayBuffer, out) { var header = new Int32Array(arrayBuffer, 0, headerLengthInt); if (header[off_magic] !== DDS_MAGIC) { return null; } if (!header(off_pfFlags) & DDPF_FOURCC) { return null; } var fourCC = header(off_pfFourCC); var width = header[off_width]; var height = header[off_height]; var isCubeMap = header[off_caps2] & DDSCAPS2_CUBEMAP; var hasMipmap = header[off_flags] & DDSD_MIPMAPCOUNT; var blockBytes, internalFormat; switch(fourCC) { case FOURCC_DXT1: blockBytes = 8; internalFormat = Texture.COMPRESSED_RGB_S3TC_DXT1_EXT; break; case FOURCC_DXT3: blockBytes = 16; internalFormat = Texture.COMPRESSED_RGBA_S3TC_DXT3_EXT; break; case FOURCC_DXT5: blockBytes = 16; internalFormat = Texture.COMPRESSED_RGBA_S3TC_DXT5_EXT; break; default: return null; } var dataOffset = header[off_size] + 4; // TODO: Suppose all face are existed var faceNumber = isCubeMap ? 6 : 1; var mipmapCount = 1; if (hasMipmap) { mipmapCount = Math.max(1, header[off_mipmapCount]); } var textures = []; for (var f = 0; f < faceNumber; f++) { var _width = width; var _height = height; textures[f] = new Texture2D({ width: _width, height: _height, format: internalFormat }); var mipmaps = []; for (var i = 0; i < mipmapCount; i++) { var dataLength = Math.max(4, _width) / 4 * Math.max(4, _height) / 4 * blockBytes; var byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength); dataOffset += dataLength; _width *= 0.5; _height *= 0.5; mipmaps[i] = byteArray; } textures[f].pixels = mipmaps[0]; if (hasMipmap) { textures[f].mipmaps = mipmaps; } } // TODO // return isCubeMap ? textures : textures[0]; if (out) { out.width = textures[0].width; out.height = textures[0].height; out.format = textures[0].format; out.pixels = textures[0].pixels; out.mipmaps = textures[0].mipmaps; } else { return textures[0]; } } }; export default ret;