|
@@ -6,10 +6,9 @@ import {
|
|
|
LinearEncoding,
|
|
|
LinearFilter,
|
|
|
NearestFilter,
|
|
|
+ RedFormat,
|
|
|
RGBAFormat,
|
|
|
RGBEEncoding,
|
|
|
- RGBEFormat,
|
|
|
- RGBFormat,
|
|
|
UnsignedByteType
|
|
|
} from '../../../build/three.module.js';
|
|
|
import * as fflate from '../libs/fflate.module.js';
|
|
@@ -1312,8 +1311,7 @@ class EXRLoader extends DataTextureLoader {
|
|
|
var inDataView = info.viewer;
|
|
|
var inOffset = { value: info.offset.value };
|
|
|
|
|
|
- var tmpBufSize = info.width * scanlineBlockSize * ( EXRHeader.channels.length * info.type );
|
|
|
- var outBuffer = new Uint16Array( tmpBufSize );
|
|
|
+ var outBuffer = new Uint16Array( info.width * info.scanlineBlockSize * ( info.channels * info.type ) );
|
|
|
var bitmap = new Uint8Array( BITMAP_SIZE );
|
|
|
|
|
|
// Setup channel info
|
|
@@ -1333,6 +1331,7 @@ class EXRLoader extends DataTextureLoader {
|
|
|
}
|
|
|
|
|
|
// Read range compression data
|
|
|
+
|
|
|
var minNonZero = parseUint16( inDataView, inOffset );
|
|
|
var maxNonZero = parseUint16( inDataView, inOffset );
|
|
|
|
|
@@ -1489,7 +1488,7 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
var inDataView = info.viewer;
|
|
|
var inOffset = { value: info.offset.value };
|
|
|
- var outBuffer = new Uint8Array( info.width * info.lines * ( EXRHeader.channels.length * info.type * INT16_SIZE ) );
|
|
|
+ var outBuffer = new Uint8Array( info.width * info.lines * ( info.channels * info.type * INT16_SIZE ) );
|
|
|
|
|
|
// Read compression header information
|
|
|
var dwaHeader = {
|
|
@@ -1737,16 +1736,6 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
}
|
|
|
|
|
|
- function parseUlong( dataView, offset ) {
|
|
|
-
|
|
|
- var uLong = dataView.getUint32( 0, true );
|
|
|
-
|
|
|
- offset.value = offset.value + ULONG_SIZE;
|
|
|
-
|
|
|
- return uLong;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
function parseRational( dataView, offset ) {
|
|
|
|
|
|
var x = parseInt32( dataView, offset );
|
|
@@ -2037,270 +2026,268 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
}
|
|
|
|
|
|
- var bufferDataView = new DataView( buffer );
|
|
|
- var uInt8Array = new Uint8Array( buffer );
|
|
|
-
|
|
|
- var EXRHeader = {};
|
|
|
-
|
|
|
- bufferDataView.getUint32( 0, true ); // magic
|
|
|
- bufferDataView.getUint8( 4, true ); // versionByteZero
|
|
|
- bufferDataView.getUint8( 5, true ); // fullMask
|
|
|
-
|
|
|
- // start of header
|
|
|
-
|
|
|
- var offset = { value: 8 }; // start at 8, after magic stuff
|
|
|
-
|
|
|
- var keepReading = true;
|
|
|
+ function parseHeader( dataView, buffer, offset ) {
|
|
|
|
|
|
- while ( keepReading ) {
|
|
|
+ const EXRHeader = {};
|
|
|
|
|
|
- var attributeName = parseNullTerminatedString( buffer, offset );
|
|
|
+ if ( dataView.getUint32( 0, true ) != 20000630 ) // magic
|
|
|
+ throw "THREE.EXRLoader: provided file doesn't appear to be in OpenEXR format.";
|
|
|
|
|
|
- if ( attributeName == 0 ) {
|
|
|
+ EXRHeader.version = dataView.getUint8( 4, true );
|
|
|
|
|
|
- keepReading = false;
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- var attributeType = parseNullTerminatedString( buffer, offset );
|
|
|
- var attributeSize = parseUint32( bufferDataView, offset );
|
|
|
- var attributeValue = parseValue( bufferDataView, buffer, offset, attributeType, attributeSize );
|
|
|
-
|
|
|
- if ( attributeValue === undefined ) {
|
|
|
-
|
|
|
- console.warn( `EXRLoader.parse: skipped unknown header attribute type \'${ attributeType }\'.` );
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- EXRHeader[ attributeName ] = attributeValue;
|
|
|
-
|
|
|
- }
|
|
|
+ const spec = dataView.getUint8( 5, true ); // fullMask
|
|
|
|
|
|
+ EXRHeader.spec = {
|
|
|
+ singleTile: !!(spec & 1),
|
|
|
+ longName: !!(spec & 2),
|
|
|
+ deepFormat: !!(spec & 4),
|
|
|
+ multiPart: !!(spec & 8),
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ // start of header
|
|
|
|
|
|
- // offsets
|
|
|
- var dataWindowHeight = EXRHeader.dataWindow.yMax + 1;
|
|
|
+ offset.value = 8; // start at 8 - after pre-amble
|
|
|
|
|
|
- var uncompress;
|
|
|
- var scanlineBlockSize;
|
|
|
+ var keepReading = true;
|
|
|
|
|
|
- switch ( EXRHeader.compression ) {
|
|
|
+ while ( keepReading ) {
|
|
|
|
|
|
- case 'NO_COMPRESSION':
|
|
|
+ var attributeName = parseNullTerminatedString( buffer, offset );
|
|
|
|
|
|
- scanlineBlockSize = 1;
|
|
|
- uncompress = uncompressRAW;
|
|
|
- break;
|
|
|
+ if ( attributeName == 0 ) {
|
|
|
|
|
|
- case 'RLE_COMPRESSION':
|
|
|
+ keepReading = false;
|
|
|
|
|
|
- scanlineBlockSize = 1;
|
|
|
- uncompress = uncompressRLE;
|
|
|
- break;
|
|
|
-
|
|
|
- case 'ZIPS_COMPRESSION':
|
|
|
-
|
|
|
- scanlineBlockSize = 1;
|
|
|
- uncompress = uncompressZIP;
|
|
|
- break;
|
|
|
-
|
|
|
- case 'ZIP_COMPRESSION':
|
|
|
-
|
|
|
- scanlineBlockSize = 16;
|
|
|
- uncompress = uncompressZIP;
|
|
|
- break;
|
|
|
+ } else {
|
|
|
|
|
|
- case 'PIZ_COMPRESSION':
|
|
|
+ var attributeType = parseNullTerminatedString( buffer, offset );
|
|
|
+ var attributeSize = parseUint32( dataView, offset );
|
|
|
+ var attributeValue = parseValue( dataView, buffer, offset, attributeType, attributeSize );
|
|
|
|
|
|
- scanlineBlockSize = 32;
|
|
|
- uncompress = uncompressPIZ;
|
|
|
- break;
|
|
|
+ if ( attributeValue === undefined ) {
|
|
|
|
|
|
- case 'PXR24_COMPRESSION':
|
|
|
+ console.warn( `EXRLoader.parse: skipped unknown header attribute type \'${attributeType}\'.` );
|
|
|
|
|
|
- scanlineBlockSize = 16;
|
|
|
- uncompress = uncompressPXR;
|
|
|
- break;
|
|
|
+ } else {
|
|
|
|
|
|
- case 'DWAA_COMPRESSION':
|
|
|
+ EXRHeader[ attributeName ] = attributeValue;
|
|
|
|
|
|
- scanlineBlockSize = 32;
|
|
|
- uncompress = uncompressDWA;
|
|
|
- break;
|
|
|
+ }
|
|
|
|
|
|
- case 'DWAB_COMPRESSION':
|
|
|
+ }
|
|
|
|
|
|
- scanlineBlockSize = 256;
|
|
|
- uncompress = uncompressDWA;
|
|
|
- break;
|
|
|
+ }
|
|
|
|
|
|
- default:
|
|
|
+ if ( spec != 0 ) {
|
|
|
+ console.error( "EXRHeader:", EXRHeader );
|
|
|
+ throw "THREE.EXRLoader: provided file is currently unsupported."
|
|
|
+ }
|
|
|
|
|
|
- throw 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported';
|
|
|
+ return EXRHeader;
|
|
|
|
|
|
}
|
|
|
|
|
|
- var size_t;
|
|
|
- var getValue;
|
|
|
-
|
|
|
- // mixed pixelType not supported
|
|
|
- var pixelType = EXRHeader.channels[ 0 ].pixelType;
|
|
|
-
|
|
|
- if ( pixelType === 1 ) { // half
|
|
|
+ function setupDecoder( EXRHeader, dataView, uInt8Array, offset, outputType ) {
|
|
|
|
|
|
- switch ( this.type ) {
|
|
|
+ const EXRDecoder = {
|
|
|
+ size: 0,
|
|
|
+ viewer: dataView,
|
|
|
+ array: uInt8Array,
|
|
|
+ offset: offset,
|
|
|
+ width: EXRHeader.dataWindow.xMax - EXRHeader.dataWindow.xMin + 1,
|
|
|
+ height: EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1,
|
|
|
+ channels: EXRHeader.channels.length,
|
|
|
+ bytesPerLine: null,
|
|
|
+ lines: null,
|
|
|
+ inputSize: null,
|
|
|
+ type: EXRHeader.channels[ 0 ].pixelType,
|
|
|
+ uncompress: null,
|
|
|
+ getter: null,
|
|
|
+ format: null,
|
|
|
+ encoding: null,
|
|
|
+ };
|
|
|
|
|
|
- case UnsignedByteType:
|
|
|
- case FloatType:
|
|
|
+ switch ( EXRHeader.compression ) {
|
|
|
|
|
|
- getValue = parseFloat16;
|
|
|
- size_t = INT16_SIZE;
|
|
|
+ case 'NO_COMPRESSION':
|
|
|
+ EXRDecoder.lines = 1;
|
|
|
+ EXRDecoder.uncompress = uncompressRAW;
|
|
|
break;
|
|
|
|
|
|
- case HalfFloatType:
|
|
|
-
|
|
|
- getValue = parseUint16;
|
|
|
- size_t = INT16_SIZE;
|
|
|
+ case 'RLE_COMPRESSION':
|
|
|
+ EXRDecoder.lines = 1;
|
|
|
+ EXRDecoder.uncompress = uncompressRLE;
|
|
|
break;
|
|
|
|
|
|
- }
|
|
|
+ case 'ZIPS_COMPRESSION':
|
|
|
+ EXRDecoder.lines = 1;
|
|
|
+ EXRDecoder.uncompress = uncompressZIP;
|
|
|
+ break;
|
|
|
|
|
|
- } else if ( pixelType === 2 ) { // float
|
|
|
+ case 'ZIP_COMPRESSION':
|
|
|
+ EXRDecoder.lines = 16;
|
|
|
+ EXRDecoder.uncompress = uncompressZIP;
|
|
|
+ break;
|
|
|
|
|
|
- switch ( this.type ) {
|
|
|
+ case 'PIZ_COMPRESSION':
|
|
|
+ EXRDecoder.lines = 32;
|
|
|
+ EXRDecoder.uncompress = uncompressPIZ;
|
|
|
+ break;
|
|
|
|
|
|
- case UnsignedByteType:
|
|
|
- case FloatType:
|
|
|
+ case 'PXR24_COMPRESSION':
|
|
|
+ EXRDecoder.lines = 16;
|
|
|
+ EXRDecoder.uncompress = uncompressPXR;
|
|
|
+ break;
|
|
|
|
|
|
- getValue = parseFloat32;
|
|
|
- size_t = FLOAT32_SIZE;
|
|
|
+ case 'DWAA_COMPRESSION':
|
|
|
+ EXRDecoder.lines = 32;
|
|
|
+ EXRDecoder.uncompress = uncompressDWA;
|
|
|
break;
|
|
|
|
|
|
- case HalfFloatType:
|
|
|
+ case 'DWAB_COMPRESSION':
|
|
|
+ EXRDecoder.lines = 256;
|
|
|
+ EXRDecoder.uncompress = uncompressDWA;
|
|
|
+ break;
|
|
|
|
|
|
- getValue = decodeFloat32;
|
|
|
- size_t = FLOAT32_SIZE;
|
|
|
+ default:
|
|
|
+ throw 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported';
|
|
|
|
|
|
}
|
|
|
|
|
|
- } else {
|
|
|
-
|
|
|
- throw 'EXRLoader.parse: unsupported pixelType ' + pixelType + ' for ' + EXRHeader.compression + '.';
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var numBlocks = dataWindowHeight / scanlineBlockSize;
|
|
|
-
|
|
|
- for ( var i = 0; i < numBlocks; i ++ ) {
|
|
|
+ EXRDecoder.scanlineBlockSize = EXRDecoder.lines;
|
|
|
|
|
|
- parseUlong( bufferDataView, offset ); // scanlineOffset
|
|
|
+ if ( EXRDecoder.type == 1 ) {
|
|
|
|
|
|
- }
|
|
|
+ // half
|
|
|
+ switch ( outputType ) {
|
|
|
|
|
|
- // we should be passed the scanline offset table, start reading pixel data
|
|
|
+ case UnsignedByteType:
|
|
|
+ case FloatType:
|
|
|
+ EXRDecoder.getter = parseFloat16;
|
|
|
+ EXRDecoder.inputSize = INT16_SIZE;
|
|
|
+ break;
|
|
|
|
|
|
- var width = EXRHeader.dataWindow.xMax - EXRHeader.dataWindow.xMin + 1;
|
|
|
- var height = EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1;
|
|
|
- // Firefox only supports RGBA (half) float textures
|
|
|
- // var numChannels = EXRHeader.channels.length;
|
|
|
- var numChannels = 4;
|
|
|
- var size = width * height * numChannels;
|
|
|
+ case HalfFloatType:
|
|
|
+ EXRDecoder.getter = parseUint16;
|
|
|
+ EXRDecoder.inputSize = INT16_SIZE;
|
|
|
+ break;
|
|
|
|
|
|
- // Fill initially with 1s for the alpha value if the texture is not RGBA, RGB values will be overwritten
|
|
|
- switch ( this.type ) {
|
|
|
+ }
|
|
|
|
|
|
- case UnsignedByteType:
|
|
|
- case FloatType:
|
|
|
+ } else if ( EXRDecoder.type == 2 ) {
|
|
|
|
|
|
- var byteArray = new Float32Array( size );
|
|
|
+ // float
|
|
|
+ switch ( outputType ) {
|
|
|
|
|
|
- if ( EXRHeader.channels.length < numChannels ) {
|
|
|
+ case UnsignedByteType:
|
|
|
+ case FloatType:
|
|
|
+ EXRDecoder.getter = parseFloat32;
|
|
|
+ EXRDecoder.inputSize = FLOAT32_SIZE;
|
|
|
+ break;
|
|
|
|
|
|
- byteArray.fill( 1, 0, size );
|
|
|
+ case HalfFloatType:
|
|
|
+ EXRDecoder.getter = decodeFloat32;
|
|
|
+ EXRDecoder.inputSize = FLOAT32_SIZE;
|
|
|
|
|
|
}
|
|
|
|
|
|
- break;
|
|
|
+ } else {
|
|
|
|
|
|
- case HalfFloatType:
|
|
|
+ throw 'EXRLoader.parse: unsupported pixelType ' + EXRDecoder.type + ' for ' + EXRHeader.compression + '.';
|
|
|
|
|
|
- var byteArray = new Uint16Array( size );
|
|
|
+ }
|
|
|
|
|
|
- if ( EXRHeader.channels.length < numChannels ) {
|
|
|
+ EXRDecoder.blockCount = ( EXRHeader.dataWindow.yMax + 1 ) / EXRDecoder.scanlineBlockSize;
|
|
|
|
|
|
- byteArray.fill( 0x3C00, 0, size ); // Uint16Array holds half float data, 0x3C00 is 1
|
|
|
+ for ( var i = 0; i < EXRDecoder.blockCount; i ++ )
|
|
|
+ parseInt64( dataView, offset ) // scanlineOffset
|
|
|
+
|
|
|
+ // we should be passed the scanline offset table, ready to start reading pixel data.
|
|
|
|
|
|
- }
|
|
|
+ // RGB images will be converted to RGBA format, preventing software emulation in select devices.
|
|
|
+ EXRDecoder.outputChannels = ( ( EXRDecoder.channels == 3 ) ? 4 : EXRDecoder.channels );
|
|
|
+ const size = EXRDecoder.width * EXRDecoder.height * EXRDecoder.outputChannels;
|
|
|
|
|
|
- break;
|
|
|
+ switch ( outputType ) {
|
|
|
|
|
|
- default:
|
|
|
+ case UnsignedByteType:
|
|
|
+ case FloatType:
|
|
|
+ EXRDecoder.byteArray = new Float32Array( size );
|
|
|
|
|
|
- console.error( 'THREE.EXRLoader: unsupported type: ', this.type );
|
|
|
- break;
|
|
|
+ // Fill initially with 1s for the alpha value if the texture is not RGBA, RGB values will be overwritten
|
|
|
+ if ( EXRDecoder.channels < EXRDecoder.outputChannels )
|
|
|
+ EXRDecoder.byteArray.fill( 1, 0, size );
|
|
|
+
|
|
|
+ break;
|
|
|
|
|
|
- }
|
|
|
+ case HalfFloatType:
|
|
|
+ EXRDecoder.byteArray = new Uint16Array( size );
|
|
|
+
|
|
|
+ if ( EXRDecoder.channels < EXRDecoder.outputChannels )
|
|
|
+ EXRDecoder.byteArray.fill( 0x3C00, 0, size ); // Uint16Array holds half float data, 0x3C00 is 1
|
|
|
|
|
|
- var channelOffsets = {
|
|
|
- R: 0,
|
|
|
- G: 1,
|
|
|
- B: 2,
|
|
|
- A: 3
|
|
|
- };
|
|
|
+ break;
|
|
|
|
|
|
- var compressionInfo = {
|
|
|
+ default:
|
|
|
+ console.error( 'THREE.EXRLoader: unsupported type: ', outputType );
|
|
|
+ break;
|
|
|
|
|
|
- size: 0,
|
|
|
- width: width,
|
|
|
- lines: scanlineBlockSize,
|
|
|
+ }
|
|
|
|
|
|
- offset: offset,
|
|
|
- array: uInt8Array,
|
|
|
- viewer: bufferDataView,
|
|
|
+ EXRDecoder.bytesPerLine = EXRDecoder.width * EXRDecoder.inputSize * EXRDecoder.channels;
|
|
|
|
|
|
- type: pixelType,
|
|
|
- channels: EXRHeader.channels.length,
|
|
|
+ if ( EXRDecoder.outputChannels == 4 ) {
|
|
|
+ EXRDecoder.format = RGBAFormat;
|
|
|
+ EXRDecoder.encoding = ( outputType == UnsignedByteType ) ? RGBEEncoding : LinearEncoding;
|
|
|
+ } else {
|
|
|
+ EXRDecoder.format = RedFormat;
|
|
|
+ EXRDecoder.encoding = LinearEncoding;
|
|
|
+ }
|
|
|
|
|
|
- };
|
|
|
+ return EXRDecoder;
|
|
|
|
|
|
- var line;
|
|
|
- var size;
|
|
|
- var viewer;
|
|
|
- var tmpOffset = { value: 0 };
|
|
|
+ }
|
|
|
|
|
|
- for ( var scanlineBlockIdx = 0; scanlineBlockIdx < height / scanlineBlockSize; scanlineBlockIdx ++ ) {
|
|
|
+ // start parsing file [START]
|
|
|
|
|
|
- line = parseUint32( bufferDataView, offset ); // line_no
|
|
|
- size = parseUint32( bufferDataView, offset ); // data_len
|
|
|
+ const bufferDataView = new DataView( buffer );
|
|
|
+ const uInt8Array = new Uint8Array( buffer );
|
|
|
+ const offset = { value: 0 };
|
|
|
|
|
|
- compressionInfo.lines = ( line + scanlineBlockSize > height ) ? height - line : scanlineBlockSize;
|
|
|
- compressionInfo.offset = offset;
|
|
|
- compressionInfo.size = size;
|
|
|
+ // get header information and validate format.
|
|
|
+ const EXRHeader = parseHeader( bufferDataView, buffer, offset );
|
|
|
|
|
|
- viewer = uncompress( compressionInfo );
|
|
|
+ // get input compression information and prepare decoding.
|
|
|
+ const EXRDecoder = setupDecoder( EXRHeader, bufferDataView, uInt8Array, offset, this.type );
|
|
|
|
|
|
- offset.value += size;
|
|
|
+ const tmpOffset = { value: 0 };
|
|
|
+ const channelOffsets = { R: 0, G: 1, B: 2, A: 3, Y: 0 };
|
|
|
|
|
|
- for ( var line_y = 0; line_y < scanlineBlockSize; line_y ++ ) {
|
|
|
+ for ( let scanlineBlockIdx = 0; scanlineBlockIdx < EXRDecoder.height / EXRDecoder.scanlineBlockSize; scanlineBlockIdx ++ ) {
|
|
|
+
|
|
|
+ const line = parseUint32( bufferDataView, offset ); // line_no
|
|
|
+ EXRDecoder.size = parseUint32( bufferDataView, offset ); // data_len
|
|
|
+ EXRDecoder.lines = ( ( line + EXRDecoder.scanlineBlockSize > EXRDecoder.height ) ? (EXRDecoder.height-line) : EXRDecoder.scanlineBlockSize );
|
|
|
|
|
|
- var true_y = line_y + ( scanlineBlockIdx * scanlineBlockSize );
|
|
|
+ const isCompressed = EXRDecoder.size < EXRDecoder.lines * EXRDecoder.bytesPerLine;
|
|
|
+ const viewer = isCompressed ? EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder );
|
|
|
|
|
|
- if ( true_y >= height ) break;
|
|
|
+ offset.value += EXRDecoder.size;
|
|
|
|
|
|
- for ( var channelID = 0; channelID < EXRHeader.channels.length; channelID ++ ) {
|
|
|
+ for ( let line_y = 0; line_y < EXRDecoder.scanlineBlockSize; line_y ++ ) {
|
|
|
|
|
|
- var cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ];
|
|
|
+ const true_y = line_y + scanlineBlockIdx * EXRDecoder.scanlineBlockSize;
|
|
|
+ if ( true_y >= EXRDecoder.height ) break;
|
|
|
|
|
|
- for ( var x = 0; x < width; x ++ ) {
|
|
|
+ for ( let channelID = 0; channelID < EXRDecoder.channels; channelID ++ ) {
|
|
|
|
|
|
- var idx = ( line_y * ( EXRHeader.channels.length * width ) ) + ( channelID * width ) + x;
|
|
|
- tmpOffset.value = idx * size_t;
|
|
|
+ const cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ];
|
|
|
|
|
|
- var val = getValue( viewer, tmpOffset );
|
|
|
+ for ( let x = 0; x < EXRDecoder.width; x ++ ) {
|
|
|
|
|
|
- byteArray[ ( ( ( height - 1 - true_y ) * ( width * numChannels ) ) + ( x * numChannels ) ) + cOff ] = val;
|
|
|
+ tmpOffset.value = ( line_y * ( EXRDecoder.channels * EXRDecoder.width ) + channelID * EXRDecoder.width + x ) * EXRDecoder.inputSize;
|
|
|
+ const outIndex = ( EXRDecoder.height - 1 - true_y ) * ( EXRDecoder.width * EXRDecoder.outputChannels ) + x * EXRDecoder.outputChannels + cOff;
|
|
|
+ EXRDecoder.byteArray[ outIndex ] = EXRDecoder.getter( viewer, tmpOffset );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -2310,24 +2297,23 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( this.type === UnsignedByteType ) {
|
|
|
+ // convert to RGBE if user specifies Uint8 output on a RGB input texture
|
|
|
+ if ( EXRDecoder.encoding == RGBEEncoding ) {
|
|
|
|
|
|
let v, i;
|
|
|
- const size = byteArray.length;
|
|
|
+ const size = EXRDecoder.byteArray.length;
|
|
|
const RGBEArray = new Uint8Array( size );
|
|
|
|
|
|
- for ( let h = 0; h < height; ++ h ) {
|
|
|
+ for ( let h = 0; h < EXRDecoder.height; ++ h ) {
|
|
|
|
|
|
- for ( let w = 0; w < width; ++ w ) {
|
|
|
+ for ( let w = 0; w < EXRDecoder.width; ++ w ) {
|
|
|
|
|
|
- i = h * width * 4 + w * 4;
|
|
|
-
|
|
|
- const red = byteArray[ i ];
|
|
|
- const green = byteArray[ i + 1 ];
|
|
|
- const blue = byteArray[ i + 2 ];
|
|
|
-
|
|
|
- v = ( red > green ) ? red : green;
|
|
|
- v = ( blue > v ) ? blue : v;
|
|
|
+ i = h * EXRDecoder.width * 4 + w * 4;
|
|
|
+ const red = EXRDecoder.byteArray[ i ];
|
|
|
+ const green = EXRDecoder.byteArray[ i + 1 ];
|
|
|
+ const blue = EXRDecoder.byteArray[ i + 2 ];
|
|
|
+ v = red > green ? red : green;
|
|
|
+ v = blue > v ? blue : v;
|
|
|
|
|
|
if ( v < 1e-32 ) {
|
|
|
|
|
@@ -2337,7 +2323,6 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
const res = frexp( v );
|
|
|
v = res[ 0 ] * 256 / v;
|
|
|
-
|
|
|
RGBEArray[ i ] = red * v;
|
|
|
RGBEArray[ i + 1 ] = green * v;
|
|
|
RGBEArray[ i + 2 ] = blue * v;
|
|
@@ -2349,19 +2334,18 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
}
|
|
|
|
|
|
- byteArray = RGBEArray;
|
|
|
+ EXRDecoder.byteArray = RGBEArray;
|
|
|
|
|
|
}
|
|
|
-
|
|
|
- const format = ( this.type === UnsignedByteType ) ? RGBEFormat : ( numChannels === 4 ) ? RGBAFormat : RGBFormat;
|
|
|
-
|
|
|
+
|
|
|
return {
|
|
|
header: EXRHeader,
|
|
|
- width: width,
|
|
|
- height: height,
|
|
|
- data: byteArray,
|
|
|
- format: format,
|
|
|
- type: this.type
|
|
|
+ width: EXRDecoder.width,
|
|
|
+ height: EXRDecoder.height,
|
|
|
+ data: EXRDecoder.byteArray,
|
|
|
+ format: EXRDecoder.format,
|
|
|
+ encoding: EXRDecoder.encoding,
|
|
|
+ type: this.type,
|
|
|
};
|
|
|
|
|
|
}
|
|
@@ -2377,28 +2361,11 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
function onLoadCallback( texture, texData ) {
|
|
|
|
|
|
- switch ( texture.type ) {
|
|
|
-
|
|
|
- case UnsignedByteType:
|
|
|
-
|
|
|
- texture.encoding = RGBEEncoding;
|
|
|
- texture.minFilter = NearestFilter;
|
|
|
- texture.magFilter = NearestFilter;
|
|
|
- texture.generateMipmaps = false;
|
|
|
- texture.flipY = false;
|
|
|
- break;
|
|
|
-
|
|
|
- case FloatType:
|
|
|
- case HalfFloatType:
|
|
|
-
|
|
|
- texture.encoding = LinearEncoding;
|
|
|
- texture.minFilter = LinearFilter;
|
|
|
- texture.magFilter = LinearFilter;
|
|
|
- texture.generateMipmaps = false;
|
|
|
- texture.flipY = false;
|
|
|
- break;
|
|
|
-
|
|
|
- }
|
|
|
+ texture.encoding = texData.encoding;
|
|
|
+ texture.minFilter = ( texture.encoding == RGBEEncoding ) ? NearestFilter : LinearFilter;
|
|
|
+ texture.magFilter = ( texture.encoding == RGBEEncoding ) ? NearestFilter : LinearFilter;
|
|
|
+ texture.generateMipmaps = false;
|
|
|
+ texture.flipY = false;
|
|
|
|
|
|
if ( onLoad ) onLoad( texture, texData );
|
|
|
|