babylon.tools.dds.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. module BABYLON.Internals {
  2. // Based on demo done by Brandon Jones - http://media.tojicode.com/webgl-samples/dds.html
  3. // All values and structures referenced from:
  4. // http://msdn.microsoft.com/en-us/library/bb943991.aspx/
  5. var DDS_MAGIC = 0x20534444;
  6. var DDSD_CAPS = 0x1,
  7. DDSD_HEIGHT = 0x2,
  8. DDSD_WIDTH = 0x4,
  9. DDSD_PITCH = 0x8,
  10. DDSD_PIXELFORMAT = 0x1000,
  11. DDSD_MIPMAPCOUNT = 0x20000,
  12. DDSD_LINEARSIZE = 0x80000,
  13. DDSD_DEPTH = 0x800000;
  14. var DDSCAPS_COMPLEX = 0x8,
  15. DDSCAPS_MIPMAP = 0x400000,
  16. DDSCAPS_TEXTURE = 0x1000;
  17. var DDSCAPS2_CUBEMAP = 0x200,
  18. DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
  19. DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
  20. DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
  21. DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
  22. DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
  23. DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
  24. DDSCAPS2_VOLUME = 0x200000;
  25. var DDPF_ALPHAPIXELS = 0x1,
  26. DDPF_ALPHA = 0x2,
  27. DDPF_FOURCC = 0x4,
  28. DDPF_RGB = 0x40,
  29. DDPF_YUV = 0x200,
  30. DDPF_LUMINANCE = 0x20000;
  31. function FourCCToInt32(value) {
  32. return value.charCodeAt(0) +
  33. (value.charCodeAt(1) << 8) +
  34. (value.charCodeAt(2) << 16) +
  35. (value.charCodeAt(3) << 24);
  36. }
  37. function Int32ToFourCC(value) {
  38. return String.fromCharCode(
  39. value & 0xff,
  40. (value >> 8) & 0xff,
  41. (value >> 16) & 0xff,
  42. (value >> 24) & 0xff
  43. );
  44. }
  45. var FOURCC_DXT1 = FourCCToInt32("DXT1");
  46. var FOURCC_DXT3 = FourCCToInt32("DXT3");
  47. var FOURCC_DXT5 = FourCCToInt32("DXT5");
  48. var headerLengthInt = 31; // The header length in 32 bit ints
  49. // Offsets into the header array
  50. var off_magic = 0;
  51. var off_size = 1;
  52. var off_flags = 2;
  53. var off_height = 3;
  54. var off_width = 4;
  55. var off_mipmapCount = 7;
  56. var off_pfFlags = 20;
  57. var off_pfFourCC = 21;
  58. export class DDSTools {
  59. public static GetDDSInfo(arrayBuffer): { width: number; height: number; mipmapCount: number } {
  60. var header = new Int32Array(arrayBuffer, 0, headerLengthInt);
  61. var mipmapCount = 1;
  62. if (header[off_flags] & DDSD_MIPMAPCOUNT) {
  63. mipmapCount = Math.max(1, header[off_mipmapCount]);
  64. }
  65. return {
  66. width: header[off_width],
  67. height: header[off_height],
  68. mipmapCount: mipmapCount
  69. };
  70. }
  71. public static UploadDDSLevels(gl, ext, arrayBuffer, loadMipmaps?: boolean): void {
  72. var header = new Int32Array(arrayBuffer, 0, headerLengthInt),
  73. fourCC, blockBytes, internalFormat,
  74. width, height, dataLength, dataOffset,
  75. byteArray, mipmapCount, i;
  76. if (header[off_magic] != DDS_MAGIC) {
  77. console.error("Invalid magic number in DDS header");
  78. return;
  79. }
  80. if ((header[off_pfFlags] & DDPF_FOURCC) !== DDPF_FOURCC) {
  81. console.error("Unsupported format, must contain a FourCC code");
  82. return;
  83. }
  84. fourCC = header[off_pfFourCC];
  85. switch (fourCC) {
  86. case FOURCC_DXT1:
  87. blockBytes = 8;
  88. internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
  89. break;
  90. case FOURCC_DXT3:
  91. blockBytes = 16;
  92. internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT;
  93. break;
  94. case FOURCC_DXT5:
  95. blockBytes = 16;
  96. internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
  97. break;
  98. default:
  99. console.error("Unsupported FourCC code:", Int32ToFourCC(fourCC));
  100. return;
  101. }
  102. mipmapCount = 1;
  103. if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
  104. mipmapCount = Math.max(1, header[off_mipmapCount]);
  105. }
  106. width = header[off_width];
  107. height = header[off_height];
  108. dataOffset = header[off_size] + 4;
  109. for (i = 0; i < mipmapCount; ++i) {
  110. dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes;
  111. byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength);
  112. gl.compressedTexImage2D(gl.TEXTURE_2D, i, internalFormat, width, height, 0, byteArray);
  113. dataOffset += dataLength;
  114. width *= 0.5;
  115. height *= 0.5;
  116. }
  117. }
  118. }
  119. }