Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRACOLoader, DRACOExporter: Convert vertex colors to/from Linear-sRGB #25390

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion editor/js/Loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ function Loader( editor ) {

const loader = new DRACOLoader();
loader.setDecoderPath( '../examples/jsm/libs/draco/' );
loader.decodeDracoFile( contents, function ( geometry ) {
loader.parse( contents, function ( geometry ) {

let object;

Expand Down
43 changes: 41 additions & 2 deletions examples/jsm/exporters/DRACOExporter.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Color } from 'three';

/**
* Export draco compressed files from threejs geometry objects.
*
Expand Down Expand Up @@ -100,7 +102,9 @@ class DRACOExporter {

if ( colors !== undefined ) {

builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array );
const array = createVertexColorSRGBArray( colors );

builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, array );

}

Expand All @@ -120,7 +124,9 @@ class DRACOExporter {

if ( colors !== undefined ) {

builder.AddFloatAttribute( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array );
const array = createVertexColorSRGBArray( colors );

builder.AddFloatAttribute( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, array );

}

Expand Down Expand Up @@ -206,6 +212,39 @@ class DRACOExporter {

}

function createVertexColorSRGBArray( attribute ) {

// While .drc files do not specify colorspace, the only 'official' tooling
// is PLY and OBJ converters, which use sRGB. We'll assume sRGB is expected
// for .drc files, but note that Draco buffers embedded in glTF files will
// be Linear-sRGB instead.

const _color = new Color();

const count = attribute.count;
const itemSize = attribute.itemSize;
const array = new Float32Array( count * itemSize );

for ( let i = 0, il = count; i < il; i ++ ) {

_color.fromBufferAttribute( attribute, i ).convertLinearToSRGB();

array[ i * itemSize ] = _color.r;
array[ i * itemSize + 1 ] = _color.g;
array[ i * itemSize + 2 ] = _color.b;

if ( itemSize === 4 ) {

array[ i * itemSize + 3 ] = attribute.getW( i );

}

}

return array;

}

// Encoder methods

DRACOExporter.MESH_EDGEBREAKER_ENCODING = 1;
Expand Down
66 changes: 56 additions & 10 deletions examples/jsm/loaders/DRACOLoader.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {
BufferAttribute,
BufferGeometry,
Color,
FileLoader,
Loader
Loader,
LinearSRGBColorSpace,
SRGBColorSpace
} from 'three';

const _taskCache = new WeakMap();
Expand Down Expand Up @@ -73,18 +76,25 @@ class DRACOLoader extends Loader {

loader.load( url, ( buffer ) => {

this.decodeDracoFile( buffer, onLoad ).catch( onError );
this.parse( buffer, onLoad, onError );

}, onProgress, onError );

}

decodeDracoFile( buffer, callback, attributeIDs, attributeTypes ) {
parse ( buffer, onLoad, onError ) {

this.decodeDracoFile( buffer, onLoad, null, null, SRGBColorSpace ).catch( onError );

}

decodeDracoFile( buffer, callback, attributeIDs, attributeTypes, vertexColorSpace = LinearSRGBColorSpace ) {

const taskConfig = {
attributeIDs: attributeIDs || this.defaultAttributeIDs,
attributeTypes: attributeTypes || this.defaultAttributeTypes,
useUniqueIDs: !! attributeIDs
useUniqueIDs: !! attributeIDs,
vertexColorSpace: vertexColorSpace,
};

return this.decodeGeometry( buffer, taskConfig ).then( callback );
Expand Down Expand Up @@ -188,19 +198,47 @@ class DRACOLoader extends Loader {

for ( let i = 0; i < geometryData.attributes.length; i ++ ) {

const attribute = geometryData.attributes[ i ];
const name = attribute.name;
const array = attribute.array;
const itemSize = attribute.itemSize;
const result = geometryData.attributes[ i ];
const name = result.name;
const array = result.array;
const itemSize = result.itemSize;

const attribute = new BufferAttribute( array, itemSize );

if ( name === 'color' ) {

geometry.setAttribute( name, new BufferAttribute( array, itemSize ) );
this._assignVertexColorSpace( attribute, result.vertexColorSpace );

}

geometry.setAttribute( name, attribute );

}

return geometry;

}

_assignVertexColorSpace( attribute, inputColorSpace ) {

// While .drc files do not specify colorspace, the only 'official' tooling
// is PLY and OBJ converters, which use sRGB. We'll assume sRGB when a .drc
// file is passed into .load() or .parse(). GLTFLoader uses internal APIs
// to decode geometry, and vertex colors are already Linear-sRGB in there.

if ( inputColorSpace !== SRGBColorSpace ) return;

const _color = new Color();

for ( let i = 0, il = attribute.count; i < il; i ++ ) {

_color.fromBufferAttribute( attribute, i ).convertSRGBToLinear();
attribute.setXYZ( i, _color.r, _color.g, _color.b );

}

}

_loadLibrary( url, responseType ) {

const loader = new FileLoader( this.manager );
Expand Down Expand Up @@ -493,7 +531,15 @@ function DRACOWorker() {

}

geometry.attributes.push( decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) );
const attributeResult = decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute );

if ( attributeName === 'color' ) {

attributeResult.vertexColorSpace = taskConfig.vertexColorSpace;

}

geometry.attributes.push( attributeResult );

}

Expand Down