diff --git a/docs/examples/en/exporters/EXRExporter.html b/docs/examples/en/exporters/EXRExporter.html index fba1be4c981a52..21439b0b185d99 100644 --- a/docs/examples/en/exporters/EXRExporter.html +++ b/docs/examples/en/exporters/EXRExporter.html @@ -78,6 +78,15 @@
+ [page:Function dataTexture] — DataTexture containing data used for exporting EXR image.
+ [page:Options options] — Export options (details above).
+
+ Generates a .exr output from the input data texture. +
+diff --git a/examples/files.json b/examples/files.json index 34354521893aff..fca287ce853442 100644 --- a/examples/files.json +++ b/examples/files.json @@ -409,6 +409,7 @@ "misc_exporter_ply", "misc_exporter_stl", "misc_exporter_usdz", + "misc_exporter_exr", "misc_lookat" ], "css2d": [ diff --git a/examples/jsm/exporters/EXRExporter.js b/examples/jsm/exporters/EXRExporter.js index 388dfdf1a2a166..bd1d8202d2d83d 100644 --- a/examples/jsm/exporters/EXRExporter.js +++ b/examples/jsm/exporters/EXRExporter.js @@ -21,61 +21,107 @@ const ZIP_COMPRESSION = 3; class EXRExporter { - parse( renderer, renderTarget, options ) { + parse( arg1, arg2, arg3 ) { - if ( ! supported( renderer, renderTarget ) ) return undefined; + if ( ! arg1 || ! ( arg1.isWebGLRenderer || arg1.isDataTexture ) ) { - const info = buildInfo( renderTarget, options ), - dataBuffer = getPixelData( renderer, renderTarget, info ), - rawContentBuffer = reorganizeDataBuffer( dataBuffer, info ), - chunks = compressData( rawContentBuffer, info ); + throw Error( 'EXRExporter.parse: Unsupported first parameter, expected instance of WebGLRenderer or DataTexture.' ); - return fillData( chunks, info ); + } else if ( arg1.isWebGLRenderer ) { - } + const renderer = arg1, renderTarget = arg2, options = arg3; -} + supportedRTT( renderTarget ); + + const info = buildInfoRTT( renderTarget, options ), + dataBuffer = getPixelData( renderer, renderTarget, info ), + rawContentBuffer = reorganizeDataBuffer( dataBuffer, info ), + chunks = compressData( rawContentBuffer, info ); + + return fillData( chunks, info ); -function supported( renderer, renderTarget ) { + } else if ( arg1.isDataTexture ) { - if ( ! renderer || ! renderer.isWebGLRenderer ) { + const texture = arg1, options = arg2; - console.error( 'EXRExporter.parse: Unsupported first parameter, expected instance of WebGLRenderer.' ); + supportedDT( texture ); - return false; + const info = buildInfoDT( texture, options ), + dataBuffer = texture.image.data, + rawContentBuffer = reorganizeDataBuffer( dataBuffer, info ), + chunks = compressData( rawContentBuffer, info ); + + return fillData( chunks, info ); + + } } +} + +function supportedRTT( renderTarget ) { + if ( ! renderTarget || ! renderTarget.isWebGLRenderTarget ) { - console.error( 'EXRExporter.parse: Unsupported second parameter, expected instance of WebGLRenderTarget.' ); + throw Error( 'EXRExporter.parse: Unsupported second parameter, expected instance of WebGLRenderTarget.' ); + + } + + if ( renderTarget.isWebGLCubeRenderTarget || renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) { - return false; + throw Error( 'EXRExporter.parse: Unsupported render target type, expected instance of WebGLRenderTarget.' ); } if ( renderTarget.texture.type !== FloatType && renderTarget.texture.type !== HalfFloatType ) { - console.error( 'EXRExporter.parse: Unsupported WebGLRenderTarget texture type.' ); - - return false; + throw Error( 'EXRExporter.parse: Unsupported WebGLRenderTarget texture type.' ); } if ( renderTarget.texture.format !== RGBAFormat ) { - console.error( 'EXRExporter.parse: Unsupported WebGLRenderTarget texture format, expected RGBAFormat.' ); + throw Error( 'EXRExporter.parse: Unsupported WebGLRenderTarget texture format, expected RGBAFormat.' ); + + } + +} + +function supportedDT( texture ) { + + if ( texture.type !== FloatType && texture.type !== HalfFloatType ) { + + throw Error( 'EXRExporter.parse: Unsupported DataTexture texture type.' ); + + } + + if ( texture.format !== RGBAFormat ) { + + throw Error( 'EXRExporter.parse: Unsupported DataTexture texture format, expected RGBAFormat.' ); + + } + + if ( ! texture.image.data ) { + + throw Error( 'EXRExporter.parse: Invalid DataTexture image data.' ); + + } + + if ( texture.type === FloatType && texture.image.data.constructor.name !== 'Float32Array' ) { - return false; + throw Error( 'EXRExporter.parse: DataTexture image data doesn\'t match type, expected \'Float32Array\'.' ); } + if ( texture.type === HalfFloatType && texture.image.data.constructor.name !== 'Uint16Array' ) { - return true; + throw Error( 'EXRExporter.parse: DataTexture image data doesn\'t match type, expected \'Uint16Array\'.' ); + + } } -function buildInfo( renderTarget, options = {} ) { +function buildInfoRTT( renderTarget, options = {} ) { const compressionSizes = { 0: 1, @@ -87,7 +133,6 @@ function buildInfo( renderTarget, options = {} ) { HEIGHT = renderTarget.height, TYPE = renderTarget.texture.type, FORMAT = renderTarget.texture.format, - COLOR_SPACE = renderTarget.texture.colorSpace, COMPRESSION = ( options.compression !== undefined ) ? options.compression : ZIP_COMPRESSION, EXPORTER_TYPE = ( options.type !== undefined ) ? options.type : HalfFloatType, OUT_TYPE = ( EXPORTER_TYPE === FloatType ) ? 2 : 1, @@ -99,7 +144,40 @@ function buildInfo( renderTarget, options = {} ) { height: HEIGHT, type: TYPE, format: FORMAT, - colorSpace: COLOR_SPACE, + compression: COMPRESSION, + blockLines: COMPRESSION_SIZE, + dataType: OUT_TYPE, + dataSize: 2 * OUT_TYPE, + numBlocks: Math.ceil( HEIGHT / COMPRESSION_SIZE ), + numInputChannels: 4, + numOutputChannels: NUM_CHANNELS, + }; + +} + +function buildInfoDT( texture, options = {} ) { + + const compressionSizes = { + 0: 1, + 2: 1, + 3: 16 + }; + + const WIDTH = texture.image.width, + HEIGHT = texture.image.height, + TYPE = texture.type, + FORMAT = texture.format, + COMPRESSION = ( options.compression !== undefined ) ? options.compression : ZIP_COMPRESSION, + EXPORTER_TYPE = ( options.type !== undefined ) ? options.type : HalfFloatType, + OUT_TYPE = ( EXPORTER_TYPE === FloatType ) ? 2 : 1, + COMPRESSION_SIZE = compressionSizes[ COMPRESSION ], + NUM_CHANNELS = 4; + + return { + width: WIDTH, + height: HEIGHT, + type: TYPE, + format: FORMAT, compression: COMPRESSION, blockLines: COMPRESSION_SIZE, dataType: OUT_TYPE, diff --git a/examples/misc_exporter_exr.html b/examples/misc_exporter_exr.html new file mode 100644 index 00000000000000..3f2038014a4bc0 --- /dev/null +++ b/examples/misc_exporter_exr.html @@ -0,0 +1,224 @@ + + +
+