Comparing version
93
index.js
// All values and structures referenced from: | ||
// http://msdn.microsoft.com/en-us/library/bb943991.aspx/ | ||
// | ||
// DX10 Cubemap support based on | ||
// https://github.com/dariomanesku/cmft/issues/7#issuecomment-69516844 | ||
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb943983(v=vs.85).aspx | ||
// https://github.com/playcanvas/engine/blob/master/src/resources/resources_texture.js | ||
@@ -11,3 +16,9 @@ var DDS_MAGIC = 0x20534444 | ||
var FOURCC_DXT5 = fourCCToInt32('DXT5') | ||
var FOURCC_DX10 = fourCCToInt32('DX10') | ||
var FOURCC_FP32F = 116 // DXGI_FORMAT_R32G32B32A32_FLOAT | ||
var DDSCAPS2_CUBEMAP = 0x200 | ||
var D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3 | ||
var DXGI_FORMAT_R32G32B32A32_FLOAT = 2 | ||
// The header length in 32 bit ints | ||
@@ -25,2 +36,3 @@ var headerLengthInt = 31 | ||
var off_pfFourCC = 21 | ||
var off_caps2 = 28 | ||
@@ -56,2 +68,19 @@ module.exports = parseHeaders | ||
break | ||
case FOURCC_FP32F: | ||
format = 'rgba32f' | ||
break | ||
case FOURCC_DX10: | ||
var dx10Header = new Uint32Array(arrayBuffer.slice(128, 128 + 20)) | ||
format = dx10Header[0] | ||
var resourceDimension = dx10Header[1] | ||
var miscFlag = dx10Header[2] | ||
var arraySize = dx10Header[3] | ||
var miscFlags2 = dx10Header[4] | ||
if (resourceDimension === D3D10_RESOURCE_DIMENSION_TEXTURE2D && format === DXGI_FORMAT_R32G32B32A32_FLOAT) { | ||
format = 'rgba32f' | ||
} else { | ||
throw new Error('Unsupported DX10 texture format ' + format) | ||
} | ||
break | ||
default: | ||
@@ -63,2 +92,3 @@ throw new Error('Unsupported FourCC code: ' + int32ToFourCC(fourCC)) | ||
var mipmapCount = 1 | ||
if (flags & DDSD_MIPMAPCOUNT) { | ||
@@ -68,2 +98,8 @@ mipmapCount = Math.max(1, header[off_mipmapCount]) | ||
var cubemap = false | ||
var caps2 = header[off_caps2] | ||
if (caps2 & DDSCAPS2_CUBEMAP) { | ||
cubemap = true | ||
} | ||
var width = header[off_width] | ||
@@ -77,14 +113,51 @@ var height = header[off_height] | ||
for (var i = 0; i < mipmapCount; i++) { | ||
dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes | ||
images.push({ | ||
offset: dataOffset, | ||
length: dataLength, | ||
shape: [ width, height ] | ||
}) | ||
dataOffset += dataLength | ||
width = Math.floor(width / 2) | ||
height = Math.floor(height / 2) | ||
if (fourCC === FOURCC_DX10) { | ||
dataOffset += 20 | ||
} | ||
if (cubemap) { | ||
for (var f = 0; f < 6; f++) { | ||
if (format !== 'rgba32f') { | ||
throw new Error('Only RGBA32f cubemaps are supported') | ||
} | ||
var bpp = 4 * 32 / 8 | ||
width = texWidth | ||
height = texHeight | ||
// cubemap should have all mipmap levels defined | ||
// Math.log2(width) + 1 | ||
var requiredMipLevels = Math.log(width) / Math.log(2) + 1 | ||
for (var i = 0; i < requiredMipLevels; i++) { | ||
dataLength = width * height * bpp | ||
images.push({ | ||
offset: dataOffset, | ||
length: dataLength, | ||
shape: [ width, height ] | ||
}) | ||
// Reuse data from the previous level if we are beyond mipmapCount | ||
// This is hack for CMFT not publishing full mipmap chain https://github.com/dariomanesku/cmft/issues/10 | ||
if (i < mipmapCount) { | ||
dataOffset += dataLength | ||
} | ||
width = Math.floor(width / 2) | ||
height = Math.floor(height / 2) | ||
} | ||
} | ||
} else { | ||
for (var i = 0; i < mipmapCount; i++) { | ||
dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes | ||
images.push({ | ||
offset: dataOffset, | ||
length: dataLength, | ||
shape: [ width, height ] | ||
}) | ||
dataOffset += dataLength | ||
width = Math.floor(width / 2) | ||
height = Math.floor(height / 2) | ||
} | ||
} | ||
return { | ||
@@ -91,0 +164,0 @@ shape: [ texWidth, texHeight ], |
{ | ||
"name": "parse-dds", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "parses the headers of a DDS texture file", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
8794
34.55%155
70.33%