|
@@ -6,6 +6,7 @@ import {
|
|
|
DataTextureLoader,
|
|
|
DefaultLoadingManager,
|
|
|
FloatType,
|
|
|
+ HalfFloatType,
|
|
|
LinearEncoding,
|
|
|
LinearFilter,
|
|
|
NearestFilter,
|
|
@@ -326,8 +327,84 @@ RGBELoader.prototype._parser = function ( buffer ) {
|
|
|
|
|
|
return data_rgba;
|
|
|
|
|
|
+ };
|
|
|
+
|
|
|
+ var RGBEByteToRGBFloat = function ( sourceArray, sourceOffset, destArray, destOffset ) {
|
|
|
+
|
|
|
+ var e = sourceArray[ sourceOffset + 3 ];
|
|
|
+ var scale = Math.pow( 2.0, e - 128.0 ) / 255.0;
|
|
|
+
|
|
|
+ destArray[ destOffset + 0 ] = sourceArray[ sourceOffset + 0 ] * scale;
|
|
|
+ destArray[ destOffset + 1 ] = sourceArray[ sourceOffset + 1 ] * scale;
|
|
|
+ destArray[ destOffset + 2 ] = sourceArray[ sourceOffset + 2 ] * scale;
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ var RGBEByteToRGBHalf = ( 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. */
|
|
|
+ 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;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
}
|
|
|
- ;
|
|
|
+
|
|
|
+ return function ( sourceArray, sourceOffset, destArray, destOffset ) {
|
|
|
+
|
|
|
+ var e = sourceArray[ sourceOffset + 3 ];
|
|
|
+ var scale = Math.pow( 2.0, e - 128.0 ) / 255.0;
|
|
|
+
|
|
|
+ destArray[ destOffset + 0 ] = toHalf( sourceArray[ sourceOffset + 0 ] * scale );
|
|
|
+ destArray[ destOffset + 1 ] = toHalf( sourceArray[ sourceOffset + 1 ] * scale );
|
|
|
+ destArray[ destOffset + 2 ] = toHalf( sourceArray[ sourceOffset + 2 ] * scale );
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ } )();
|
|
|
|
|
|
var byteArray = new Uint8Array( buffer );
|
|
|
byteArray.pos = 0;
|
|
@@ -337,46 +414,55 @@ RGBELoader.prototype._parser = function ( buffer ) {
|
|
|
|
|
|
var w = rgbe_header_info.width,
|
|
|
h = rgbe_header_info.height,
|
|
|
- image_rgba_data = RGBE_ReadPixels_RLE( byteArray.subarray( byteArray.pos ), w, h )
|
|
|
- ;
|
|
|
+ image_rgba_data = RGBE_ReadPixels_RLE( byteArray.subarray( byteArray.pos ), w, h );
|
|
|
+
|
|
|
if ( RGBE_RETURN_FAILURE !== image_rgba_data ) {
|
|
|
|
|
|
- if ( this.type === UnsignedByteType ) {
|
|
|
+ switch ( this.type ) {
|
|
|
|
|
|
- var data = image_rgba_data;
|
|
|
- var format = RGBEFormat; // handled as THREE.RGBAFormat in shaders
|
|
|
- var type = UnsignedByteType;
|
|
|
+ case UnsignedByteType:
|
|
|
|
|
|
- } else if ( this.type === FloatType ) {
|
|
|
+ var data = image_rgba_data;
|
|
|
+ var format = RGBEFormat; // handled as THREE.RGBAFormat in shaders
|
|
|
+ var type = UnsignedByteType;
|
|
|
+ break;
|
|
|
|
|
|
- var RGBEByteToRGBFloat = function ( sourceArray, sourceOffset, destArray, destOffset ) {
|
|
|
+ case FloatType:
|
|
|
|
|
|
- var e = sourceArray[ sourceOffset + 3 ];
|
|
|
- var scale = Math.pow( 2.0, e - 128.0 ) / 255.0;
|
|
|
+ var numElements = ( image_rgba_data.length / 4 ) * 3;
|
|
|
+ var floatArray = new Float32Array( numElements );
|
|
|
|
|
|
- destArray[ destOffset + 0 ] = sourceArray[ sourceOffset + 0 ] * scale;
|
|
|
- destArray[ destOffset + 1 ] = sourceArray[ sourceOffset + 1 ] * scale;
|
|
|
- destArray[ destOffset + 2 ] = sourceArray[ sourceOffset + 2 ] * scale;
|
|
|
+ for ( var j = 0; j < numElements; j ++ ) {
|
|
|
|
|
|
- };
|
|
|
+ RGBEByteToRGBFloat( image_rgba_data, j * 4, floatArray, j * 3 );
|
|
|
|
|
|
- var numElements = ( image_rgba_data.length / 4 ) * 3;
|
|
|
- var floatArray = new Float32Array( numElements );
|
|
|
+ }
|
|
|
|
|
|
- for ( var j = 0; j < numElements; j ++ ) {
|
|
|
+ var data = floatArray;
|
|
|
+ var format = RGBFormat;
|
|
|
+ var type = FloatType;
|
|
|
+ break;
|
|
|
|
|
|
- RGBEByteToRGBFloat( image_rgba_data, j * 4, floatArray, j * 3 );
|
|
|
+ case HalfFloatType:
|
|
|
|
|
|
- }
|
|
|
+ var numElements = ( image_rgba_data.length / 4 ) * 3;
|
|
|
+ var halfArray = new Uint16Array( numElements );
|
|
|
|
|
|
- var data = floatArray;
|
|
|
- var format = RGBFormat;
|
|
|
- var type = FloatType;
|
|
|
+ for ( var j = 0; j < numElements; j ++ ) {
|
|
|
|
|
|
+ RGBEByteToRGBHalf( image_rgba_data, j * 4, halfArray, j * 3 );
|
|
|
|
|
|
- } else {
|
|
|
+ }
|
|
|
|
|
|
- console.error( 'THREE.RGBELoader: unsupported type: ', this.type );
|
|
|
+ var data = halfArray;
|
|
|
+ var format = RGBFormat;
|
|
|
+ var type = HalfFloatType;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+
|
|
|
+ console.error( 'THREE.RGBELoader: unsupported type: ', this.type );
|
|
|
+ break;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -429,6 +515,15 @@ RGBELoader.prototype.load = function ( url, onLoad, onProgress, onError ) {
|
|
|
texture.flipY = true;
|
|
|
break;
|
|
|
|
|
|
+ case HalfFloatType:
|
|
|
+
|
|
|
+ texture.encoding = LinearEncoding;
|
|
|
+ texture.minFilter = LinearFilter;
|
|
|
+ texture.magFilter = LinearFilter;
|
|
|
+ texture.generateMipmaps = false;
|
|
|
+ texture.flipY = true;
|
|
|
+ break;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
if ( onLoad ) onLoad( texture, texData );
|