Skip to content

Commit

Permalink
EXRExporter: implements support for DataTexture export (#26810)
Browse files Browse the repository at this point in the history
* EXRExporter: DataTexture support

Signed-off-by: Guilherme Avila <[email protected]>

* EXRExporter: update API & docs

Signed-off-by: Guilherme Avila <[email protected]>

* Examples: add misc_exporter_exr

Signed-off-by: Guilherme Avila <[email protected]>

* fix MIME-type

Signed-off-by: Guilherme Avila <[email protected]>

* update DataTexture usage example

Signed-off-by: Guilherme Avila <[email protected]>

* update screenshot

Signed-off-by: Guilherme Avila <[email protected]>

---------

Signed-off-by: Guilherme Avila <[email protected]>
  • Loading branch information
sciecode authored Sep 24, 2023
1 parent c3a746a commit 53ee377
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 24 deletions.
9 changes: 9 additions & 0 deletions docs/examples/en/exporters/EXRExporter.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ <h3>[method:null parse]( [param:WebGLRenderer renderer], [param:WebGLRenderTarge
Generates a .exr output from the input render target.
</p>

<h3>[method:null parse]( [param:DataTexture dataTexture], [param:Object options] )</h3>
<p>
[page:Function dataTexture] — DataTexture containing data used for exporting EXR image.<br />
[page:Options options] — Export options (details above).<br />
</p>
<p>
Generates a .exr output from the input data texture.
</p>

<h2>Source</h2>

<p>
Expand Down
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@
"misc_exporter_ply",
"misc_exporter_stl",
"misc_exporter_usdz",
"misc_exporter_exr",
"misc_lookat"
],
"css2d": [
Expand Down
126 changes: 102 additions & 24 deletions examples/jsm/exporters/EXRExporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
Loading

0 comments on commit 53ee377

Please sign in to comment.