|
|
@@ -7,6 +7,7 @@ import {
|
|
|
LinearFilter,
|
|
|
LinearSRGBColorSpace,
|
|
|
RedFormat,
|
|
|
+ RGFormat,
|
|
|
RGBAFormat
|
|
|
} from 'three';
|
|
|
import * as fflate from '../libs/fflate.module.js';
|
|
|
@@ -113,6 +114,14 @@ class EXRLoader extends DataTextureLoader {
|
|
|
*/
|
|
|
this.type = HalfFloatType;
|
|
|
|
|
|
+ /**
|
|
|
+ * Texture output format.
|
|
|
+ *
|
|
|
+ * @type {(RGBAFormat|RGFormat|RedFormat)}
|
|
|
+ * @default RGBAFormat
|
|
|
+ */
|
|
|
+ this.outputFormat = RGBAFormat;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -2374,7 +2383,7 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
}
|
|
|
|
|
|
- function setupDecoder( EXRHeader, dataView, uInt8Array, offset, outputType ) {
|
|
|
+ function setupDecoder( EXRHeader, dataView, uInt8Array, offset, outputType, outputFormat ) {
|
|
|
|
|
|
const EXRDecoder = {
|
|
|
size: 0,
|
|
|
@@ -2385,6 +2394,7 @@ class EXRLoader extends DataTextureLoader {
|
|
|
height: EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1,
|
|
|
inputChannels: EXRHeader.channels,
|
|
|
channelByteOffsets: {},
|
|
|
+ shouldExpand: false,
|
|
|
scanOrder: null,
|
|
|
totalBytes: null,
|
|
|
columns: null,
|
|
|
@@ -2462,17 +2472,16 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
// RGB images will be converted to RGBA format, preventing software emulation in select devices.
|
|
|
let fillAlpha = false;
|
|
|
+ let invalidOutput = false;
|
|
|
|
|
|
+ // Validate if input texture contain supported channels
|
|
|
if ( channels.R && channels.G && channels.B ) {
|
|
|
|
|
|
- fillAlpha = ! channels.A;
|
|
|
EXRDecoder.outputChannels = 4;
|
|
|
- EXRDecoder.decodeChannels = { R: 0, G: 1, B: 2, A: 3 };
|
|
|
|
|
|
} else if ( channels.Y ) {
|
|
|
|
|
|
EXRDecoder.outputChannels = 1;
|
|
|
- EXRDecoder.decodeChannels = { Y: 0 };
|
|
|
|
|
|
} else {
|
|
|
|
|
|
@@ -2480,6 +2489,83 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ // Setup output texture configuration
|
|
|
+ switch ( EXRDecoder.outputChannels ) {
|
|
|
+
|
|
|
+ case 4:
|
|
|
+
|
|
|
+ if ( outputFormat == RGBAFormat ) {
|
|
|
+
|
|
|
+ fillAlpha = ! channels.A;
|
|
|
+ EXRDecoder.format = RGBAFormat;
|
|
|
+ EXRDecoder.colorSpace = LinearSRGBColorSpace;
|
|
|
+ EXRDecoder.outputChannels = 4;
|
|
|
+ EXRDecoder.decodeChannels = { R: 0, G: 1, B: 2, A: 3 };
|
|
|
+
|
|
|
+ } else if ( outputFormat == RGFormat ) {
|
|
|
+
|
|
|
+ EXRDecoder.format = RGFormat;
|
|
|
+ EXRDecoder.colorSpace = NoColorSpace;
|
|
|
+ EXRDecoder.outputChannels = 2;
|
|
|
+ EXRDecoder.decodeChannels = { R: 0, G: 1 };
|
|
|
+
|
|
|
+ } else if ( outputFormat == RedFormat ) {
|
|
|
+
|
|
|
+ EXRDecoder.format = RedFormat;
|
|
|
+ EXRDecoder.colorSpace = NoColorSpace;
|
|
|
+ EXRDecoder.outputChannels = 1;
|
|
|
+ EXRDecoder.decodeChannels = { R: 0 };
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ invalidOutput = true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 1:
|
|
|
+
|
|
|
+ if ( outputFormat == RGBAFormat ) {
|
|
|
+
|
|
|
+ fillAlpha = true;
|
|
|
+ EXRDecoder.format = RGBAFormat;
|
|
|
+ EXRDecoder.colorSpace = LinearSRGBColorSpace;
|
|
|
+ EXRDecoder.outputChannels = 4;
|
|
|
+ EXRDecoder.shouldExpand = true;
|
|
|
+ EXRDecoder.decodeChannels = { Y: 0 };
|
|
|
+
|
|
|
+ } else if ( outputFormat == RGFormat ) {
|
|
|
+
|
|
|
+ EXRDecoder.format = RGFormat;
|
|
|
+ EXRDecoder.colorSpace = NoColorSpace;
|
|
|
+ EXRDecoder.outputChannels = 2;
|
|
|
+ EXRDecoder.shouldExpand = true;
|
|
|
+ EXRDecoder.decodeChannels = { Y: 0 };
|
|
|
+
|
|
|
+ } else if ( outputFormat == RedFormat ) {
|
|
|
+
|
|
|
+ EXRDecoder.format = RedFormat;
|
|
|
+ EXRDecoder.colorSpace = NoColorSpace;
|
|
|
+ EXRDecoder.outputChannels = 1;
|
|
|
+ EXRDecoder.decodeChannels = { Y: 0 };
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ invalidOutput = true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+
|
|
|
+ invalidOutput = true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (invalidOutput) throw new Error( 'EXRLoader.parse: invalid output format for specified file.' );
|
|
|
+
|
|
|
if ( EXRDecoder.type == 1 ) {
|
|
|
|
|
|
// half
|
|
|
@@ -2569,18 +2655,6 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( EXRDecoder.outputChannels == 4 ) {
|
|
|
-
|
|
|
- EXRDecoder.format = RGBAFormat;
|
|
|
- EXRDecoder.colorSpace = LinearSRGBColorSpace;
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- EXRDecoder.format = RedFormat;
|
|
|
- EXRDecoder.colorSpace = NoColorSpace;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
if ( EXRHeader.spec.singleTile ) {
|
|
|
|
|
|
EXRDecoder.blockHeight = EXRHeader.tiles.ySize;
|
|
|
@@ -2626,11 +2700,30 @@ class EXRLoader extends DataTextureLoader {
|
|
|
const EXRHeader = parseHeader( bufferDataView, buffer, offset );
|
|
|
|
|
|
// get input compression information and prepare decoding.
|
|
|
- const EXRDecoder = setupDecoder( EXRHeader, bufferDataView, uInt8Array, offset, this.type );
|
|
|
+ const EXRDecoder = setupDecoder( EXRHeader, bufferDataView, uInt8Array, offset, this.type, this.outputFormat );
|
|
|
|
|
|
// parse input data
|
|
|
EXRDecoder.decode();
|
|
|
|
|
|
+ // output texture post-processing
|
|
|
+ if ( EXRDecoder.shouldExpand ) {
|
|
|
+
|
|
|
+ const byteArray = EXRDecoder.byteArray;
|
|
|
+
|
|
|
+ if ( this.outputFormat == RGBAFormat ) {
|
|
|
+
|
|
|
+ for ( let i = 0; i < byteArray.length; i += 4 )
|
|
|
+ byteArray [i + 2 ] = ( byteArray [ i + 1 ] = byteArray[ i ] );
|
|
|
+
|
|
|
+ } else if ( this.outputFormat == RGFormat ) {
|
|
|
+
|
|
|
+ for ( let i = 0; i < byteArray.length; i += 2 )
|
|
|
+ byteArray [ i + 1 ] = byteArray[ i ] ;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
return {
|
|
|
header: EXRHeader,
|
|
|
width: EXRDecoder.width,
|
|
|
@@ -2647,7 +2740,7 @@ class EXRLoader extends DataTextureLoader {
|
|
|
* Sets the texture type.
|
|
|
*
|
|
|
* @param {(HalfFloatType|FloatType)} value - The texture type to set.
|
|
|
- * @return {RGBMLoader} A reference to this loader.
|
|
|
+ * @return {EXRLoader} A reference to this loader.
|
|
|
*/
|
|
|
setDataType( value ) {
|
|
|
|
|
|
@@ -2656,6 +2749,19 @@ class EXRLoader extends DataTextureLoader {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Sets texture output format. Defaults to `RGBAFormat`.
|
|
|
+ *
|
|
|
+ * @param {(RGBAFormat|RGFormat|RedFormat)} value - Texture output format.
|
|
|
+ * @return {EXRLoader} A reference to this loader.
|
|
|
+ */
|
|
|
+ setOutputFormat( value ) {
|
|
|
+
|
|
|
+ this.outputFormat = value;
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
load( url, onLoad, onProgress, onError ) {
|
|
|
|
|
|
function onLoadCallback( texture, texData ) {
|