2
0
Guilherme Avila 5 жил өмнө
parent
commit
ca79fec56d

+ 181 - 164
examples/js/loaders/EXRLoader.js

@@ -745,7 +745,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 					var count = - l;
 					size -= count + 1;
-					
+
 					for ( var i = 0; i < count; i ++ ) {
 
 						out.push( reader.getUint8( p ++ ) );
@@ -757,7 +757,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 					var count = l;
 					size -= 2;
-					
+
 					var value = reader.getUint8( p ++ );
 
 					for ( var i = 0; i < count + 1; i ++ ) {
@@ -788,7 +788,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 			var numBlocksY = Math.ceil( height / 8.0 );
 			var leftoverX = width - ( numBlocksX - 1 ) * 8;
 			var leftoverY = height - ( numBlocksY - 1 ) * 8;
-			
+
 			var currAcComp = { value: 0 };
 			var currDcComp = new Array( numComp );
 			var dctData = new Array( numComp );
@@ -825,7 +825,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 						halfZigBlock[ comp ].fill( 0 );
 
 						// set block DC component
-						halfZigBlock[ comp ][ 0 ] = dcBuffer[ currDcComp[ comp ]++ ];
+						halfZigBlock[ comp ][ 0 ] = dcBuffer[ currDcComp[ comp ] ++ ];
 						// set block AC components
 						unRleAC( currAcComp, acBuffer, halfZigBlock[ comp ] );
 
@@ -857,13 +857,13 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 					let type = channelData[ cscSet.idx[ comp ] ].type;
 
 					for ( let y = 8 * blocky; y < 8 * blocky + maxY; ++ y ) {
-	
+
 						offset = rowOffsets[ comp ][ y ];
-	
+
 						for ( let blockx = 0; blockx < numFullBlocksX; ++ blockx ) {
-	
+
 							let src = blockx * 64 + ( ( y & 0x7 ) * 8 );
-							
+
 							dataView.setUint16( offset + 0 * INT16_SIZE * type, rowBlock[ comp ][ src + 0 ], true );
 							dataView.setUint16( offset + 1 * INT16_SIZE * type, rowBlock[ comp ][ src + 1 ], true );
 							dataView.setUint16( offset + 2 * INT16_SIZE * type, rowBlock[ comp ][ src + 2 ], true );
@@ -875,29 +875,29 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 							dataView.setUint16( offset + 7 * INT16_SIZE * type, rowBlock[ comp ][ src + 7 ], true );
 
 							offset += 8 * INT16_SIZE * type;
-							
+
 						}
-						
+
 					}
 
 					// handle partial X blocks
 					if ( numFullBlocksX != numBlocksX ) {
 
 						for ( let y = 8 * blocky; y < 8 * blocky + maxY; ++ y ) {
-	
+
 							let offset = rowOffsets[ comp ][ y ] + 8 * numFullBlocksX * INT16_SIZE * type;
 							let src = numFullBlocksX * 64 + ( ( y & 0x7 ) * 8 );
-							
+
 							for ( let x = 0; x < maxX; ++ x ) {
 
 								dataView.setUint16( offset + x * INT16_SIZE * type, rowBlock[ comp ][ src + x ], true );
 
 							}
-							
+
 						}
 
 					}
-	
+
 				} // comp
 
 			} // blocky
@@ -955,11 +955,11 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 				} else {
 
 					halfZigBlock[ dctComp ] = acValue;
-					dctComp++;
+					dctComp ++;
 
 				}
 
-				currAcComp.value++;
+				currAcComp.value ++;
 
 			}
 
@@ -967,88 +967,88 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 		function unZigZag( src, dst ) {
 
-			dst[0] = decodeFloat16( src[0] );
-			dst[1] = decodeFloat16( src[1] );
-			dst[2] = decodeFloat16( src[5] );
-			dst[3] = decodeFloat16( src[6] );
-			dst[4] = decodeFloat16( src[14] );
-			dst[5] = decodeFloat16( src[15] );
-			dst[6] = decodeFloat16( src[27] );
-			dst[7] = decodeFloat16( src[28] );
-			dst[8] = decodeFloat16( src[2] );
-			dst[9] = decodeFloat16( src[4] );
-
-			dst[10] = decodeFloat16( src[7] );
-			dst[11] = decodeFloat16( src[13] );
-			dst[12] = decodeFloat16( src[16] );
-			dst[13] = decodeFloat16( src[26] );
-			dst[14] = decodeFloat16( src[29] );
-			dst[15] = decodeFloat16( src[42] );
-			dst[16] = decodeFloat16( src[3] );
-			dst[17] = decodeFloat16( src[8] );
-			dst[18] = decodeFloat16( src[12] );
-			dst[19] = decodeFloat16( src[17] );
-
-			dst[20] = decodeFloat16( src[25] );
-			dst[21] = decodeFloat16( src[30] );
-			dst[22] = decodeFloat16( src[41] );
-			dst[23] = decodeFloat16( src[43] );
-			dst[24] = decodeFloat16( src[9] );
-			dst[25] = decodeFloat16( src[11] );
-			dst[26] = decodeFloat16( src[18] );
-			dst[27] = decodeFloat16( src[24] );
-			dst[28] = decodeFloat16( src[31] );
-			dst[29] = decodeFloat16( src[40] );
-
-			dst[30] = decodeFloat16( src[44] );
-			dst[31] = decodeFloat16( src[53] );
-			dst[32] = decodeFloat16( src[10] );
-			dst[33] = decodeFloat16( src[19] );
-			dst[34] = decodeFloat16( src[23] );
-			dst[35] = decodeFloat16( src[32] );
-			dst[36] = decodeFloat16( src[39] );
-			dst[37] = decodeFloat16( src[45] );
-			dst[38] = decodeFloat16( src[52] );
-			dst[39] = decodeFloat16( src[54] );
-
-			dst[40] = decodeFloat16( src[20] );
-			dst[41] = decodeFloat16( src[22] );
-			dst[42] = decodeFloat16( src[33] );
-			dst[43] = decodeFloat16( src[38] );
-			dst[44] = decodeFloat16( src[46] );
-			dst[45] = decodeFloat16( src[51] );
-			dst[46] = decodeFloat16( src[55] );
-			dst[47] = decodeFloat16( src[60] );
-			dst[48] = decodeFloat16( src[21] );
-			dst[49] = decodeFloat16( src[34] );
-
-			dst[50] = decodeFloat16( src[37] );
-			dst[51] = decodeFloat16( src[47] );
-			dst[52] = decodeFloat16( src[50] );
-			dst[53] = decodeFloat16( src[56] );
-			dst[54] = decodeFloat16( src[59] );
-			dst[55] = decodeFloat16( src[61] );
-			dst[56] = decodeFloat16( src[35] );
-			dst[57] = decodeFloat16( src[36] );
-			dst[58] = decodeFloat16( src[48] );
-			dst[59] = decodeFloat16( src[49] );
-
-			dst[60] = decodeFloat16( src[57] );
-			dst[61] = decodeFloat16( src[58] );
-			dst[62] = decodeFloat16( src[62] );
-			dst[63] = decodeFloat16( src[63] );
+			dst[ 0 ] = decodeFloat16( src[ 0 ] );
+			dst[ 1 ] = decodeFloat16( src[ 1 ] );
+			dst[ 2 ] = decodeFloat16( src[ 5 ] );
+			dst[ 3 ] = decodeFloat16( src[ 6 ] );
+			dst[ 4 ] = decodeFloat16( src[ 14 ] );
+			dst[ 5 ] = decodeFloat16( src[ 15 ] );
+			dst[ 6 ] = decodeFloat16( src[ 27 ] );
+			dst[ 7 ] = decodeFloat16( src[ 28 ] );
+			dst[ 8 ] = decodeFloat16( src[ 2 ] );
+			dst[ 9 ] = decodeFloat16( src[ 4 ] );
+
+			dst[ 10 ] = decodeFloat16( src[ 7 ] );
+			dst[ 11 ] = decodeFloat16( src[ 13 ] );
+			dst[ 12 ] = decodeFloat16( src[ 16 ] );
+			dst[ 13 ] = decodeFloat16( src[ 26 ] );
+			dst[ 14 ] = decodeFloat16( src[ 29 ] );
+			dst[ 15 ] = decodeFloat16( src[ 42 ] );
+			dst[ 16 ] = decodeFloat16( src[ 3 ] );
+			dst[ 17 ] = decodeFloat16( src[ 8 ] );
+			dst[ 18 ] = decodeFloat16( src[ 12 ] );
+			dst[ 19 ] = decodeFloat16( src[ 17 ] );
+
+			dst[ 20 ] = decodeFloat16( src[ 25 ] );
+			dst[ 21 ] = decodeFloat16( src[ 30 ] );
+			dst[ 22 ] = decodeFloat16( src[ 41 ] );
+			dst[ 23 ] = decodeFloat16( src[ 43 ] );
+			dst[ 24 ] = decodeFloat16( src[ 9 ] );
+			dst[ 25 ] = decodeFloat16( src[ 11 ] );
+			dst[ 26 ] = decodeFloat16( src[ 18 ] );
+			dst[ 27 ] = decodeFloat16( src[ 24 ] );
+			dst[ 28 ] = decodeFloat16( src[ 31 ] );
+			dst[ 29 ] = decodeFloat16( src[ 40 ] );
+
+			dst[ 30 ] = decodeFloat16( src[ 44 ] );
+			dst[ 31 ] = decodeFloat16( src[ 53 ] );
+			dst[ 32 ] = decodeFloat16( src[ 10 ] );
+			dst[ 33 ] = decodeFloat16( src[ 19 ] );
+			dst[ 34 ] = decodeFloat16( src[ 23 ] );
+			dst[ 35 ] = decodeFloat16( src[ 32 ] );
+			dst[ 36 ] = decodeFloat16( src[ 39 ] );
+			dst[ 37 ] = decodeFloat16( src[ 45 ] );
+			dst[ 38 ] = decodeFloat16( src[ 52 ] );
+			dst[ 39 ] = decodeFloat16( src[ 54 ] );
+
+			dst[ 40 ] = decodeFloat16( src[ 20 ] );
+			dst[ 41 ] = decodeFloat16( src[ 22 ] );
+			dst[ 42 ] = decodeFloat16( src[ 33 ] );
+			dst[ 43 ] = decodeFloat16( src[ 38 ] );
+			dst[ 44 ] = decodeFloat16( src[ 46 ] );
+			dst[ 45 ] = decodeFloat16( src[ 51 ] );
+			dst[ 46 ] = decodeFloat16( src[ 55 ] );
+			dst[ 47 ] = decodeFloat16( src[ 60 ] );
+			dst[ 48 ] = decodeFloat16( src[ 21 ] );
+			dst[ 49 ] = decodeFloat16( src[ 34 ] );
+
+			dst[ 50 ] = decodeFloat16( src[ 37 ] );
+			dst[ 51 ] = decodeFloat16( src[ 47 ] );
+			dst[ 52 ] = decodeFloat16( src[ 50 ] );
+			dst[ 53 ] = decodeFloat16( src[ 56 ] );
+			dst[ 54 ] = decodeFloat16( src[ 59 ] );
+			dst[ 55 ] = decodeFloat16( src[ 61 ] );
+			dst[ 56 ] = decodeFloat16( src[ 35 ] );
+			dst[ 57 ] = decodeFloat16( src[ 36 ] );
+			dst[ 58 ] = decodeFloat16( src[ 48 ] );
+			dst[ 59 ] = decodeFloat16( src[ 49 ] );
+
+			dst[ 60 ] = decodeFloat16( src[ 57 ] );
+			dst[ 61 ] = decodeFloat16( src[ 58 ] );
+			dst[ 62 ] = decodeFloat16( src[ 62 ] );
+			dst[ 63 ] = decodeFloat16( src[ 63 ] );
 
 		}
 
 		function dctInverse( data ) {
 
-			const a = .5 * Math.cos ( 3.14159 / 4.0 );
-			const b = .5 * Math.cos ( 3.14159 / 16.0 );
-			const c = .5 * Math.cos ( 3.14159 / 8.0 );
-			const d = .5 * Math.cos ( 3.*3.14159 / 16.0 );
-			const e = .5 * Math.cos ( 5.*3.14159 / 16.0 );
-			const f = .5 * Math.cos ( 3.*3.14159 / 8.0 );
-			const g = .5 * Math.cos ( 7.*3.14159 / 16.0 );
+			const a = 0.5 * Math.cos( 3.14159 / 4.0 );
+			const b = 0.5 * Math.cos( 3.14159 / 16.0 );
+			const c = 0.5 * Math.cos( 3.14159 / 8.0 );
+			const d = 0.5 * Math.cos( 3.0 * 3.14159 / 16.0 );
+			const e = 0.5 * Math.cos( 5.0 * 3.14159 / 16.0 );
+			const f = 0.5 * Math.cos( 3.0 * 3.14159 / 8.0 );
+			const g = 0.5 * Math.cos( 7.0 * 3.14159 / 16.0 );
 
 			var alpha = new Array( 4 );
 			var beta = new Array( 4 );
@@ -1059,31 +1059,31 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 				var rowPtr = row * 8;
 
-				alpha[ 0 ] = c * data[ rowPtr + 2 ]; 
-				alpha[ 1 ] = f * data[ rowPtr + 2 ]; 
-				alpha[ 2 ] = c * data[ rowPtr + 6 ]; 
-				alpha[ 3 ] = f * data[ rowPtr + 6 ]; 
-		
+				alpha[ 0 ] = c * data[ rowPtr + 2 ];
+				alpha[ 1 ] = f * data[ rowPtr + 2 ];
+				alpha[ 2 ] = c * data[ rowPtr + 6 ];
+				alpha[ 3 ] = f * data[ rowPtr + 6 ];
+
 				beta[ 0 ] = b * data[ rowPtr + 1 ] + d * data[ rowPtr + 3 ] + e * data[ rowPtr + 5 ] + g * data[ rowPtr + 7 ];
 				beta[ 1 ] = d * data[ rowPtr + 1 ] - g * data[ rowPtr + 3 ] - b * data[ rowPtr + 5 ] - e * data[ rowPtr + 7 ];
 				beta[ 2 ] = e * data[ rowPtr + 1 ] - b * data[ rowPtr + 3 ] + g * data[ rowPtr + 5 ] + d * data[ rowPtr + 7 ];
 				beta[ 3 ] = g * data[ rowPtr + 1 ] - e * data[ rowPtr + 3 ] + d * data[ rowPtr + 5 ] - b * data[ rowPtr + 7 ];
-		
+
 				theta[ 0 ] = a * ( data[ rowPtr + 0 ] + data[ rowPtr + 4 ] );
 				theta[ 3 ] = a * ( data[ rowPtr + 0 ] - data[ rowPtr + 4 ] );
-				theta[ 1 ] = alpha[ 0 ] + alpha[ 3 ]; 
-				theta[ 2 ] = alpha[ 1 ] - alpha[ 2 ]; 
-		
+				theta[ 1 ] = alpha[ 0 ] + alpha[ 3 ];
+				theta[ 2 ] = alpha[ 1 ] - alpha[ 2 ];
+
 				gamma[ 0 ] = theta[ 0 ] + theta[ 1 ];
 				gamma[ 1 ] = theta[ 3 ] + theta[ 2 ];
 				gamma[ 2 ] = theta[ 3 ] - theta[ 2 ];
 				gamma[ 3 ] = theta[ 0 ] - theta[ 1 ];
-		
+
 				data[ rowPtr + 0 ] = gamma[ 0 ] + beta[ 0 ];
 				data[ rowPtr + 1 ] = gamma[ 1 ] + beta[ 1 ];
 				data[ rowPtr + 2 ] = gamma[ 2 ] + beta[ 2 ];
 				data[ rowPtr + 3 ] = gamma[ 3 ] + beta[ 3 ];
-		
+
 				data[ rowPtr + 4 ] = gamma[ 3 ] - beta[ 3 ];
 				data[ rowPtr + 5 ] = gamma[ 2 ] - beta[ 2 ];
 				data[ rowPtr + 6 ] = gamma[ 1 ] - beta[ 1 ];
@@ -1093,29 +1093,29 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 			for ( var column = 0; column < 8; ++ column ) {
 
-				alpha[ 0 ] = c * data[ 16 + column ]; 
-				alpha[ 1 ] = f * data[ 16 + column ]; 
-				alpha[ 2 ] = c * data[ 48 + column ]; 
-				alpha[ 3 ] = f * data[ 48 + column ]; 
+				alpha[ 0 ] = c * data[ 16 + column ];
+				alpha[ 1 ] = f * data[ 16 + column ];
+				alpha[ 2 ] = c * data[ 48 + column ];
+				alpha[ 3 ] = f * data[ 48 + column ];
 
-				beta[ 0 ] = b * data[ 8 + column ]  + d * data[ 24 + column ] + e * data[ 40 + column ] + g * data[ 56 + column ];
-				beta[ 1 ] = d * data[ 8 + column ]  - g * data[ 24 + column ] - b * data[ 40 + column ] - e * data[ 56 + column ];
-				beta[ 2 ] = e * data[ 8 + column ]  - b * data[ 24 + column ] + g * data[ 40 + column ] + d * data[ 56 + column ];
-				beta[ 3 ] = g * data [8 + column ]  - e * data[ 24 + column ] + d * data[ 40 + column ] - b * data[ 56 + column ];
+				beta[ 0 ] = b * data[ 8 + column ] + d * data[ 24 + column ] + e * data[ 40 + column ] + g * data[ 56 + column ];
+				beta[ 1 ] = d * data[ 8 + column ] - g * data[ 24 + column ] - b * data[ 40 + column ] - e * data[ 56 + column ];
+				beta[ 2 ] = e * data[ 8 + column ] - b * data[ 24 + column ] + g * data[ 40 + column ] + d * data[ 56 + column ];
+				beta[ 3 ] = g * data[ 8 + column ] - e * data[ 24 + column ] + d * data[ 40 + column ] - b * data[ 56 + column ];
 
 				theta[ 0 ] = a * ( data[ column ] + data[ 32 + column ] );
 				theta[ 3 ] = a * ( data[ column ] - data[ 32 + column ] );
 
-				theta[ 1 ] = alpha[ 0 ] + alpha[ 3 ]; 
-				theta[ 2 ] = alpha[ 1 ] - alpha[ 2 ]; 
+				theta[ 1 ] = alpha[ 0 ] + alpha[ 3 ];
+				theta[ 2 ] = alpha[ 1 ] - alpha[ 2 ];
 
 				gamma[ 0 ] = theta[ 0 ] + theta[ 1 ];
 				gamma[ 1 ] = theta[ 3 ] + theta[ 2 ];
 				gamma[ 2 ] = theta[ 3 ] - theta[ 2 ];
 				gamma[ 3 ] = theta[ 0 ] - theta[ 1 ];
 
-				data[      column ] = gamma[ 0 ] + beta[ 0 ];
-				data[  8 + column ] = gamma[ 1 ] + beta[ 1 ];
+				data[ 0 + column ] = gamma[ 0 ] + beta[ 0 ];
+				data[ 8 + column ] = gamma[ 1 ] + beta[ 1 ];
 				data[ 16 + column ] = gamma[ 2 ] + beta[ 2 ];
 				data[ 24 + column ] = gamma[ 3 ] + beta[ 3 ];
 
@@ -1334,15 +1334,15 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 				totalDcUncompressedCount: parseInt64( inDataView, inOffset ),
 				acCompression: parseInt64( inDataView, inOffset )
 
-			}
+			};
 
-			if ( dwaHeader.version < 2 ) 
+			if ( dwaHeader.version < 2 )
 				throw 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported';
 
 			// Read channel ruleset information
 			var channelRules = new Array();
 			var ruleSize = parseUint16( inDataView, inOffset ) - INT16_SIZE;
-			
+
 			while ( ruleSize > 0 ) {
 
 				var name = parseNullTerminatedString( inDataView.buffer, inOffset );
@@ -1352,10 +1352,10 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 				var index = new Int8Array( [ csc ] )[ 0 ];
 				var type = parseUint8( inDataView, inOffset );
 
-				channelRules.push( { 
-					name: name, 
-					index: index, 
-					type: type, 
+				channelRules.push( {
+					name: name,
+					index: index,
+					type: type,
 					compression: compression,
 				} );
 
@@ -1443,7 +1443,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 					array: info.array,
 					offset: inOffset,
 					size: dwaHeader.dcCompressedSize
-				}
+				};
 				var dcBuffer = new Uint16Array( uncompressZIP( zlibInfo ).buffer );
 				inOffset.value += dwaHeader.dcCompressedSize;
 
@@ -1505,20 +1505,22 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 								for ( var byte = 0; byte < INT16_SIZE * cd.type; ++ byte ) {
 
-									outBuffer[ rowOffsetBytes++ ] = rleBuffer[ rleOffset + byte * cd.width * cd.height ];
+									outBuffer[ rowOffsetBytes ++ ] = rleBuffer[ rleOffset + byte * cd.width * cd.height ];
 
 								}
 
-								rleOffset++
+								rleOffset ++;
 
 							}
 
-							row++;
+							row ++;
 
 						}
 
 						break;
 
+					case LOSSY_DCT: // skip
+
 					default:
 						throw 'EXRLoader.parse: unsupported channel compression';
 
@@ -1641,45 +1643,60 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 		}
 
-		// https://stackoverflow.com/questions/32633585/how-do-you-convert-to-half-floats-in-javascript
-		var encodeFloat16 = ( function() {
-
-			var floatView = new Float32Array(1);
-			var int32View = new Int32Array(floatView.buffer);
-		  
-			return function toHalf( fval ) {
-
-			  floatView[ 0 ] = fval;
-			  var fbits = int32View[ 0 ];
-			  var sign  = ( fbits >> 16 ) & 0x8000;          // sign only
-			  var val   = ( fbits & 0x7fffffff ) + 0x1000; // rounded value
-		  
-			  if ( val >= 0x47800000 ) {             // might be or become NaN/Inf
-				if ( ( fbits & 0x7fffffff ) >= 0x47800000 ) {
-													// is or must become NaN/Inf
-				  if( val < 0x7f800000 ) {          // was value but too large
-					return sign | 0x7c00;           // make it +/-Inf
-				  }
-				  return sign | 0x7c00 |            // remains +/-Inf or NaN
-					  ( fbits & 0x007fffff ) >> 13; // keep NaN (and Inf) bits
+		var encodeFloat16 = ( function () {
+
+			// Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410
+
+			var floatView = new Float32Array( 1 );
+			var int32View = new Int32Array( floatView.buffer );
+
+			/* This method is faster than the OpenEXR implementation (very often
+			 * used, eg. in Ogre), with the additional benefit of rounding, inspired
+			 * by James Tursa?s half-precision code. */
+			return function toHalf( val ) {
+
+				floatView[ 0 ] = val;
+				var x = int32View[ 0 ];
+
+				var bits = ( x >> 16 ) & 0x8000; /* Get the sign */
+				var m = ( x >> 12 ) & 0x07ff; /* Keep one extra bit for rounding */
+				var e = ( x >> 23 ) & 0xff; /* Using int is faster here */
+
+				/* If zero, or denormal, or exponent underflows too much for a denormal
+				 * half, return signed zero. */
+				if ( e < 103 ) return bits;
+
+				/* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
+				if ( e > 142 ) {
+
+					bits |= 0x7c00;
+					/* If exponent was 0xff and one mantissa bit was set, it means NaN,
+							 * not Inf, so make sure we set one mantissa bit too. */
+					bits |= ( ( e == 255 ) ? 0 : 1 ) && ( x & 0x007fffff );
+					return bits;
+
+				}
+
+				/* If exponent underflows but not too much, return a denormal */
+				if ( e < 113 ) {
+
+					m |= 0x0800;
+					/* Extra rounding may overflow and set mantissa to 0 and exponent
+					 * to 1, which is OK. */
+					bits |= ( m >> ( 114 - e ) ) + ( ( m >> ( 113 - e ) ) & 1 );
+					return bits;
+
 				}
-				return sign | 0x7bff;               // unrounded not quite Inf
-			  }
-			  if ( val >= 0x38800000 ) {             // remains normalized value
-				return sign | val - 0x38000000 >> 13; // exp - 127 + 15
-			  }
-			  if ( val < 0x33000000 )  {             // too small for subnormal
-				return sign;                        // becomes +/-0
-			  }
-			  val = ( fbits & 0x7fffffff ) >> 23;   // tmp exp for subnormal calc
-			  return sign | ( ( fbits & 0x7fffff | 0x800000 ) // add subnormal bit
-				   + ( 0x800000 >>> val - 102 )     // round depending on cut off
-				   >> 126 - val );                  // div by 2^(1-(exp-127+15)) and >> 13 | exp=
-				   
+
+				bits |= ( ( e - 112 ) << 10 ) | ( m >> 1 );
+				/* Extra rounding. An overflow will set mantissa to 0 and increment
+				 * the exponent, which is OK. */
+				bits += m & 1;
+				return bits;
+
 			};
-			
-		} () );
 
+		} )();
 
 		function parseUint16( dataView, offset ) {
 
@@ -1925,7 +1942,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 				scanlineBlockSize = 256;
 				uncompress = uncompressDWA;
 				break;
-	
+
 			default:
 
 				throw 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported';

+ 181 - 164
examples/jsm/loaders/EXRLoader.js

@@ -756,7 +756,7 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 					var count = - l;
 					size -= count + 1;
-					
+
 					for ( var i = 0; i < count; i ++ ) {
 
 						out.push( reader.getUint8( p ++ ) );
@@ -768,7 +768,7 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 					var count = l;
 					size -= 2;
-					
+
 					var value = reader.getUint8( p ++ );
 
 					for ( var i = 0; i < count + 1; i ++ ) {
@@ -799,7 +799,7 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 			var numBlocksY = Math.ceil( height / 8.0 );
 			var leftoverX = width - ( numBlocksX - 1 ) * 8;
 			var leftoverY = height - ( numBlocksY - 1 ) * 8;
-			
+
 			var currAcComp = { value: 0 };
 			var currDcComp = new Array( numComp );
 			var dctData = new Array( numComp );
@@ -836,7 +836,7 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 						halfZigBlock[ comp ].fill( 0 );
 
 						// set block DC component
-						halfZigBlock[ comp ][ 0 ] = dcBuffer[ currDcComp[ comp ]++ ];
+						halfZigBlock[ comp ][ 0 ] = dcBuffer[ currDcComp[ comp ] ++ ];
 						// set block AC components
 						unRleAC( currAcComp, acBuffer, halfZigBlock[ comp ] );
 
@@ -868,13 +868,13 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 					let type = channelData[ cscSet.idx[ comp ] ].type;
 
 					for ( let y = 8 * blocky; y < 8 * blocky + maxY; ++ y ) {
-	
+
 						offset = rowOffsets[ comp ][ y ];
-	
+
 						for ( let blockx = 0; blockx < numFullBlocksX; ++ blockx ) {
-	
+
 							let src = blockx * 64 + ( ( y & 0x7 ) * 8 );
-							
+
 							dataView.setUint16( offset + 0 * INT16_SIZE * type, rowBlock[ comp ][ src + 0 ], true );
 							dataView.setUint16( offset + 1 * INT16_SIZE * type, rowBlock[ comp ][ src + 1 ], true );
 							dataView.setUint16( offset + 2 * INT16_SIZE * type, rowBlock[ comp ][ src + 2 ], true );
@@ -886,29 +886,29 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 							dataView.setUint16( offset + 7 * INT16_SIZE * type, rowBlock[ comp ][ src + 7 ], true );
 
 							offset += 8 * INT16_SIZE * type;
-							
+
 						}
-						
+
 					}
 
 					// handle partial X blocks
 					if ( numFullBlocksX != numBlocksX ) {
 
 						for ( let y = 8 * blocky; y < 8 * blocky + maxY; ++ y ) {
-	
+
 							let offset = rowOffsets[ comp ][ y ] + 8 * numFullBlocksX * INT16_SIZE * type;
 							let src = numFullBlocksX * 64 + ( ( y & 0x7 ) * 8 );
-							
+
 							for ( let x = 0; x < maxX; ++ x ) {
 
 								dataView.setUint16( offset + x * INT16_SIZE * type, rowBlock[ comp ][ src + x ], true );
 
 							}
-							
+
 						}
 
 					}
-	
+
 				} // comp
 
 			} // blocky
@@ -966,11 +966,11 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 				} else {
 
 					halfZigBlock[ dctComp ] = acValue;
-					dctComp++;
+					dctComp ++;
 
 				}
 
-				currAcComp.value++;
+				currAcComp.value ++;
 
 			}
 
@@ -978,88 +978,88 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 		function unZigZag( src, dst ) {
 
-			dst[0] = decodeFloat16( src[0] );
-			dst[1] = decodeFloat16( src[1] );
-			dst[2] = decodeFloat16( src[5] );
-			dst[3] = decodeFloat16( src[6] );
-			dst[4] = decodeFloat16( src[14] );
-			dst[5] = decodeFloat16( src[15] );
-			dst[6] = decodeFloat16( src[27] );
-			dst[7] = decodeFloat16( src[28] );
-			dst[8] = decodeFloat16( src[2] );
-			dst[9] = decodeFloat16( src[4] );
-
-			dst[10] = decodeFloat16( src[7] );
-			dst[11] = decodeFloat16( src[13] );
-			dst[12] = decodeFloat16( src[16] );
-			dst[13] = decodeFloat16( src[26] );
-			dst[14] = decodeFloat16( src[29] );
-			dst[15] = decodeFloat16( src[42] );
-			dst[16] = decodeFloat16( src[3] );
-			dst[17] = decodeFloat16( src[8] );
-			dst[18] = decodeFloat16( src[12] );
-			dst[19] = decodeFloat16( src[17] );
-
-			dst[20] = decodeFloat16( src[25] );
-			dst[21] = decodeFloat16( src[30] );
-			dst[22] = decodeFloat16( src[41] );
-			dst[23] = decodeFloat16( src[43] );
-			dst[24] = decodeFloat16( src[9] );
-			dst[25] = decodeFloat16( src[11] );
-			dst[26] = decodeFloat16( src[18] );
-			dst[27] = decodeFloat16( src[24] );
-			dst[28] = decodeFloat16( src[31] );
-			dst[29] = decodeFloat16( src[40] );
-
-			dst[30] = decodeFloat16( src[44] );
-			dst[31] = decodeFloat16( src[53] );
-			dst[32] = decodeFloat16( src[10] );
-			dst[33] = decodeFloat16( src[19] );
-			dst[34] = decodeFloat16( src[23] );
-			dst[35] = decodeFloat16( src[32] );
-			dst[36] = decodeFloat16( src[39] );
-			dst[37] = decodeFloat16( src[45] );
-			dst[38] = decodeFloat16( src[52] );
-			dst[39] = decodeFloat16( src[54] );
-
-			dst[40] = decodeFloat16( src[20] );
-			dst[41] = decodeFloat16( src[22] );
-			dst[42] = decodeFloat16( src[33] );
-			dst[43] = decodeFloat16( src[38] );
-			dst[44] = decodeFloat16( src[46] );
-			dst[45] = decodeFloat16( src[51] );
-			dst[46] = decodeFloat16( src[55] );
-			dst[47] = decodeFloat16( src[60] );
-			dst[48] = decodeFloat16( src[21] );
-			dst[49] = decodeFloat16( src[34] );
-
-			dst[50] = decodeFloat16( src[37] );
-			dst[51] = decodeFloat16( src[47] );
-			dst[52] = decodeFloat16( src[50] );
-			dst[53] = decodeFloat16( src[56] );
-			dst[54] = decodeFloat16( src[59] );
-			dst[55] = decodeFloat16( src[61] );
-			dst[56] = decodeFloat16( src[35] );
-			dst[57] = decodeFloat16( src[36] );
-			dst[58] = decodeFloat16( src[48] );
-			dst[59] = decodeFloat16( src[49] );
-
-			dst[60] = decodeFloat16( src[57] );
-			dst[61] = decodeFloat16( src[58] );
-			dst[62] = decodeFloat16( src[62] );
-			dst[63] = decodeFloat16( src[63] );
+			dst[ 0 ] = decodeFloat16( src[ 0 ] );
+			dst[ 1 ] = decodeFloat16( src[ 1 ] );
+			dst[ 2 ] = decodeFloat16( src[ 5 ] );
+			dst[ 3 ] = decodeFloat16( src[ 6 ] );
+			dst[ 4 ] = decodeFloat16( src[ 14 ] );
+			dst[ 5 ] = decodeFloat16( src[ 15 ] );
+			dst[ 6 ] = decodeFloat16( src[ 27 ] );
+			dst[ 7 ] = decodeFloat16( src[ 28 ] );
+			dst[ 8 ] = decodeFloat16( src[ 2 ] );
+			dst[ 9 ] = decodeFloat16( src[ 4 ] );
+
+			dst[ 10 ] = decodeFloat16( src[ 7 ] );
+			dst[ 11 ] = decodeFloat16( src[ 13 ] );
+			dst[ 12 ] = decodeFloat16( src[ 16 ] );
+			dst[ 13 ] = decodeFloat16( src[ 26 ] );
+			dst[ 14 ] = decodeFloat16( src[ 29 ] );
+			dst[ 15 ] = decodeFloat16( src[ 42 ] );
+			dst[ 16 ] = decodeFloat16( src[ 3 ] );
+			dst[ 17 ] = decodeFloat16( src[ 8 ] );
+			dst[ 18 ] = decodeFloat16( src[ 12 ] );
+			dst[ 19 ] = decodeFloat16( src[ 17 ] );
+
+			dst[ 20 ] = decodeFloat16( src[ 25 ] );
+			dst[ 21 ] = decodeFloat16( src[ 30 ] );
+			dst[ 22 ] = decodeFloat16( src[ 41 ] );
+			dst[ 23 ] = decodeFloat16( src[ 43 ] );
+			dst[ 24 ] = decodeFloat16( src[ 9 ] );
+			dst[ 25 ] = decodeFloat16( src[ 11 ] );
+			dst[ 26 ] = decodeFloat16( src[ 18 ] );
+			dst[ 27 ] = decodeFloat16( src[ 24 ] );
+			dst[ 28 ] = decodeFloat16( src[ 31 ] );
+			dst[ 29 ] = decodeFloat16( src[ 40 ] );
+
+			dst[ 30 ] = decodeFloat16( src[ 44 ] );
+			dst[ 31 ] = decodeFloat16( src[ 53 ] );
+			dst[ 32 ] = decodeFloat16( src[ 10 ] );
+			dst[ 33 ] = decodeFloat16( src[ 19 ] );
+			dst[ 34 ] = decodeFloat16( src[ 23 ] );
+			dst[ 35 ] = decodeFloat16( src[ 32 ] );
+			dst[ 36 ] = decodeFloat16( src[ 39 ] );
+			dst[ 37 ] = decodeFloat16( src[ 45 ] );
+			dst[ 38 ] = decodeFloat16( src[ 52 ] );
+			dst[ 39 ] = decodeFloat16( src[ 54 ] );
+
+			dst[ 40 ] = decodeFloat16( src[ 20 ] );
+			dst[ 41 ] = decodeFloat16( src[ 22 ] );
+			dst[ 42 ] = decodeFloat16( src[ 33 ] );
+			dst[ 43 ] = decodeFloat16( src[ 38 ] );
+			dst[ 44 ] = decodeFloat16( src[ 46 ] );
+			dst[ 45 ] = decodeFloat16( src[ 51 ] );
+			dst[ 46 ] = decodeFloat16( src[ 55 ] );
+			dst[ 47 ] = decodeFloat16( src[ 60 ] );
+			dst[ 48 ] = decodeFloat16( src[ 21 ] );
+			dst[ 49 ] = decodeFloat16( src[ 34 ] );
+
+			dst[ 50 ] = decodeFloat16( src[ 37 ] );
+			dst[ 51 ] = decodeFloat16( src[ 47 ] );
+			dst[ 52 ] = decodeFloat16( src[ 50 ] );
+			dst[ 53 ] = decodeFloat16( src[ 56 ] );
+			dst[ 54 ] = decodeFloat16( src[ 59 ] );
+			dst[ 55 ] = decodeFloat16( src[ 61 ] );
+			dst[ 56 ] = decodeFloat16( src[ 35 ] );
+			dst[ 57 ] = decodeFloat16( src[ 36 ] );
+			dst[ 58 ] = decodeFloat16( src[ 48 ] );
+			dst[ 59 ] = decodeFloat16( src[ 49 ] );
+
+			dst[ 60 ] = decodeFloat16( src[ 57 ] );
+			dst[ 61 ] = decodeFloat16( src[ 58 ] );
+			dst[ 62 ] = decodeFloat16( src[ 62 ] );
+			dst[ 63 ] = decodeFloat16( src[ 63 ] );
 
 		}
 
 		function dctInverse( data ) {
 
-			const a = .5 * Math.cos ( 3.14159 / 4.0 );
-			const b = .5 * Math.cos ( 3.14159 / 16.0 );
-			const c = .5 * Math.cos ( 3.14159 / 8.0 );
-			const d = .5 * Math.cos ( 3.*3.14159 / 16.0 );
-			const e = .5 * Math.cos ( 5.*3.14159 / 16.0 );
-			const f = .5 * Math.cos ( 3.*3.14159 / 8.0 );
-			const g = .5 * Math.cos ( 7.*3.14159 / 16.0 );
+			const a = 0.5 * Math.cos( 3.14159 / 4.0 );
+			const b = 0.5 * Math.cos( 3.14159 / 16.0 );
+			const c = 0.5 * Math.cos( 3.14159 / 8.0 );
+			const d = 0.5 * Math.cos( 3.0 * 3.14159 / 16.0 );
+			const e = 0.5 * Math.cos( 5.0 * 3.14159 / 16.0 );
+			const f = 0.5 * Math.cos( 3.0 * 3.14159 / 8.0 );
+			const g = 0.5 * Math.cos( 7.0 * 3.14159 / 16.0 );
 
 			var alpha = new Array( 4 );
 			var beta = new Array( 4 );
@@ -1070,31 +1070,31 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 				var rowPtr = row * 8;
 
-				alpha[ 0 ] = c * data[ rowPtr + 2 ]; 
-				alpha[ 1 ] = f * data[ rowPtr + 2 ]; 
-				alpha[ 2 ] = c * data[ rowPtr + 6 ]; 
-				alpha[ 3 ] = f * data[ rowPtr + 6 ]; 
-		
+				alpha[ 0 ] = c * data[ rowPtr + 2 ];
+				alpha[ 1 ] = f * data[ rowPtr + 2 ];
+				alpha[ 2 ] = c * data[ rowPtr + 6 ];
+				alpha[ 3 ] = f * data[ rowPtr + 6 ];
+
 				beta[ 0 ] = b * data[ rowPtr + 1 ] + d * data[ rowPtr + 3 ] + e * data[ rowPtr + 5 ] + g * data[ rowPtr + 7 ];
 				beta[ 1 ] = d * data[ rowPtr + 1 ] - g * data[ rowPtr + 3 ] - b * data[ rowPtr + 5 ] - e * data[ rowPtr + 7 ];
 				beta[ 2 ] = e * data[ rowPtr + 1 ] - b * data[ rowPtr + 3 ] + g * data[ rowPtr + 5 ] + d * data[ rowPtr + 7 ];
 				beta[ 3 ] = g * data[ rowPtr + 1 ] - e * data[ rowPtr + 3 ] + d * data[ rowPtr + 5 ] - b * data[ rowPtr + 7 ];
-		
+
 				theta[ 0 ] = a * ( data[ rowPtr + 0 ] + data[ rowPtr + 4 ] );
 				theta[ 3 ] = a * ( data[ rowPtr + 0 ] - data[ rowPtr + 4 ] );
-				theta[ 1 ] = alpha[ 0 ] + alpha[ 3 ]; 
-				theta[ 2 ] = alpha[ 1 ] - alpha[ 2 ]; 
-		
+				theta[ 1 ] = alpha[ 0 ] + alpha[ 3 ];
+				theta[ 2 ] = alpha[ 1 ] - alpha[ 2 ];
+
 				gamma[ 0 ] = theta[ 0 ] + theta[ 1 ];
 				gamma[ 1 ] = theta[ 3 ] + theta[ 2 ];
 				gamma[ 2 ] = theta[ 3 ] - theta[ 2 ];
 				gamma[ 3 ] = theta[ 0 ] - theta[ 1 ];
-		
+
 				data[ rowPtr + 0 ] = gamma[ 0 ] + beta[ 0 ];
 				data[ rowPtr + 1 ] = gamma[ 1 ] + beta[ 1 ];
 				data[ rowPtr + 2 ] = gamma[ 2 ] + beta[ 2 ];
 				data[ rowPtr + 3 ] = gamma[ 3 ] + beta[ 3 ];
-		
+
 				data[ rowPtr + 4 ] = gamma[ 3 ] - beta[ 3 ];
 				data[ rowPtr + 5 ] = gamma[ 2 ] - beta[ 2 ];
 				data[ rowPtr + 6 ] = gamma[ 1 ] - beta[ 1 ];
@@ -1104,29 +1104,29 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 			for ( var column = 0; column < 8; ++ column ) {
 
-				alpha[ 0 ] = c * data[ 16 + column ]; 
-				alpha[ 1 ] = f * data[ 16 + column ]; 
-				alpha[ 2 ] = c * data[ 48 + column ]; 
-				alpha[ 3 ] = f * data[ 48 + column ]; 
+				alpha[ 0 ] = c * data[ 16 + column ];
+				alpha[ 1 ] = f * data[ 16 + column ];
+				alpha[ 2 ] = c * data[ 48 + column ];
+				alpha[ 3 ] = f * data[ 48 + column ];
 
-				beta[ 0 ] = b * data[ 8 + column ]  + d * data[ 24 + column ] + e * data[ 40 + column ] + g * data[ 56 + column ];
-				beta[ 1 ] = d * data[ 8 + column ]  - g * data[ 24 + column ] - b * data[ 40 + column ] - e * data[ 56 + column ];
-				beta[ 2 ] = e * data[ 8 + column ]  - b * data[ 24 + column ] + g * data[ 40 + column ] + d * data[ 56 + column ];
-				beta[ 3 ] = g * data [8 + column ]  - e * data[ 24 + column ] + d * data[ 40 + column ] - b * data[ 56 + column ];
+				beta[ 0 ] = b * data[ 8 + column ] + d * data[ 24 + column ] + e * data[ 40 + column ] + g * data[ 56 + column ];
+				beta[ 1 ] = d * data[ 8 + column ] - g * data[ 24 + column ] - b * data[ 40 + column ] - e * data[ 56 + column ];
+				beta[ 2 ] = e * data[ 8 + column ] - b * data[ 24 + column ] + g * data[ 40 + column ] + d * data[ 56 + column ];
+				beta[ 3 ] = g * data[ 8 + column ] - e * data[ 24 + column ] + d * data[ 40 + column ] - b * data[ 56 + column ];
 
 				theta[ 0 ] = a * ( data[ column ] + data[ 32 + column ] );
 				theta[ 3 ] = a * ( data[ column ] - data[ 32 + column ] );
 
-				theta[ 1 ] = alpha[ 0 ] + alpha[ 3 ]; 
-				theta[ 2 ] = alpha[ 1 ] - alpha[ 2 ]; 
+				theta[ 1 ] = alpha[ 0 ] + alpha[ 3 ];
+				theta[ 2 ] = alpha[ 1 ] - alpha[ 2 ];
 
 				gamma[ 0 ] = theta[ 0 ] + theta[ 1 ];
 				gamma[ 1 ] = theta[ 3 ] + theta[ 2 ];
 				gamma[ 2 ] = theta[ 3 ] - theta[ 2 ];
 				gamma[ 3 ] = theta[ 0 ] - theta[ 1 ];
 
-				data[      column ] = gamma[ 0 ] + beta[ 0 ];
-				data[  8 + column ] = gamma[ 1 ] + beta[ 1 ];
+				data[ 0 + column ] = gamma[ 0 ] + beta[ 0 ];
+				data[ 8 + column ] = gamma[ 1 ] + beta[ 1 ];
 				data[ 16 + column ] = gamma[ 2 ] + beta[ 2 ];
 				data[ 24 + column ] = gamma[ 3 ] + beta[ 3 ];
 
@@ -1345,15 +1345,15 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 				totalDcUncompressedCount: parseInt64( inDataView, inOffset ),
 				acCompression: parseInt64( inDataView, inOffset )
 
-			}
+			};
 
-			if ( dwaHeader.version < 2 ) 
+			if ( dwaHeader.version < 2 )
 				throw 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported';
 
 			// Read channel ruleset information
 			var channelRules = new Array();
 			var ruleSize = parseUint16( inDataView, inOffset ) - INT16_SIZE;
-			
+
 			while ( ruleSize > 0 ) {
 
 				var name = parseNullTerminatedString( inDataView.buffer, inOffset );
@@ -1363,10 +1363,10 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 				var index = new Int8Array( [ csc ] )[ 0 ];
 				var type = parseUint8( inDataView, inOffset );
 
-				channelRules.push( { 
-					name: name, 
-					index: index, 
-					type: type, 
+				channelRules.push( {
+					name: name,
+					index: index,
+					type: type,
 					compression: compression,
 				} );
 
@@ -1454,7 +1454,7 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 					array: info.array,
 					offset: inOffset,
 					size: dwaHeader.dcCompressedSize
-				}
+				};
 				var dcBuffer = new Uint16Array( uncompressZIP( zlibInfo ).buffer );
 				inOffset.value += dwaHeader.dcCompressedSize;
 
@@ -1516,20 +1516,22 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 								for ( var byte = 0; byte < INT16_SIZE * cd.type; ++ byte ) {
 
-									outBuffer[ rowOffsetBytes++ ] = rleBuffer[ rleOffset + byte * cd.width * cd.height ];
+									outBuffer[ rowOffsetBytes ++ ] = rleBuffer[ rleOffset + byte * cd.width * cd.height ];
 
 								}
 
-								rleOffset++
+								rleOffset ++;
 
 							}
 
-							row++;
+							row ++;
 
 						}
 
 						break;
 
+					case LOSSY_DCT: // skip
+
 					default:
 						throw 'EXRLoader.parse: unsupported channel compression';
 
@@ -1652,45 +1654,60 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 		}
 
-		// https://stackoverflow.com/questions/32633585/how-do-you-convert-to-half-floats-in-javascript
-		var encodeFloat16 = ( function() {
-
-			var floatView = new Float32Array(1);
-			var int32View = new Int32Array(floatView.buffer);
-		  
-			return function toHalf( fval ) {
-
-			  floatView[ 0 ] = fval;
-			  var fbits = int32View[ 0 ];
-			  var sign  = ( fbits >> 16 ) & 0x8000;          // sign only
-			  var val   = ( fbits & 0x7fffffff ) + 0x1000; // rounded value
-		  
-			  if ( val >= 0x47800000 ) {             // might be or become NaN/Inf
-				if ( ( fbits & 0x7fffffff ) >= 0x47800000 ) {
-													// is or must become NaN/Inf
-				  if( val < 0x7f800000 ) {          // was value but too large
-					return sign | 0x7c00;           // make it +/-Inf
-				  }
-				  return sign | 0x7c00 |            // remains +/-Inf or NaN
-					  ( fbits & 0x007fffff ) >> 13; // keep NaN (and Inf) bits
+		var encodeFloat16 = ( function () {
+
+			// Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410
+
+			var floatView = new Float32Array( 1 );
+			var int32View = new Int32Array( floatView.buffer );
+
+			/* This method is faster than the OpenEXR implementation (very often
+			 * used, eg. in Ogre), with the additional benefit of rounding, inspired
+			 * by James Tursa?s half-precision code. */
+			return function toHalf( val ) {
+
+				floatView[ 0 ] = val;
+				var x = int32View[ 0 ];
+
+				var bits = ( x >> 16 ) & 0x8000; /* Get the sign */
+				var m = ( x >> 12 ) & 0x07ff; /* Keep one extra bit for rounding */
+				var e = ( x >> 23 ) & 0xff; /* Using int is faster here */
+
+				/* If zero, or denormal, or exponent underflows too much for a denormal
+				 * half, return signed zero. */
+				if ( e < 103 ) return bits;
+
+				/* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
+				if ( e > 142 ) {
+
+					bits |= 0x7c00;
+					/* If exponent was 0xff and one mantissa bit was set, it means NaN,
+							 * not Inf, so make sure we set one mantissa bit too. */
+					bits |= ( ( e == 255 ) ? 0 : 1 ) && ( x & 0x007fffff );
+					return bits;
+
+				}
+
+				/* If exponent underflows but not too much, return a denormal */
+				if ( e < 113 ) {
+
+					m |= 0x0800;
+					/* Extra rounding may overflow and set mantissa to 0 and exponent
+					 * to 1, which is OK. */
+					bits |= ( m >> ( 114 - e ) ) + ( ( m >> ( 113 - e ) ) & 1 );
+					return bits;
+
 				}
-				return sign | 0x7bff;               // unrounded not quite Inf
-			  }
-			  if ( val >= 0x38800000 ) {             // remains normalized value
-				return sign | val - 0x38000000 >> 13; // exp - 127 + 15
-			  }
-			  if ( val < 0x33000000 )  {             // too small for subnormal
-				return sign;                        // becomes +/-0
-			  }
-			  val = ( fbits & 0x7fffffff ) >> 23;   // tmp exp for subnormal calc
-			  return sign | ( ( fbits & 0x7fffff | 0x800000 ) // add subnormal bit
-				   + ( 0x800000 >>> val - 102 )     // round depending on cut off
-				   >> 126 - val );                  // div by 2^(1-(exp-127+15)) and >> 13 | exp=
-				   
+
+				bits |= ( ( e - 112 ) << 10 ) | ( m >> 1 );
+				/* Extra rounding. An overflow will set mantissa to 0 and increment
+				 * the exponent, which is OK. */
+				bits += m & 1;
+				return bits;
+
 			};
-			
-		} () );
 
+		} )();
 
 		function parseUint16( dataView, offset ) {
 
@@ -1936,7 +1953,7 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 				scanlineBlockSize = 256;
 				uncompress = uncompressDWA;
 				break;
-	
+
 			default:
 
 				throw 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported';