Skip to content

Commit afb032b

Browse files
committed
USDZExporter: Refactored diffuse modulation code
1 parent 3e8694d commit afb032b

File tree

1 file changed

+61
-92
lines changed

1 file changed

+61
-92
lines changed

examples/jsm/exporters/USDZExporter.js

Lines changed: 61 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ class USDZExporter {
1414

1515
const materials = {};
1616
const textures = {};
17-
const materialsWithColor = new Set();
18-
const coloredTextures = new Map(); // material -> diffuse map file name
1917

2018
scene.traverseVisible( ( object ) => {
2119

@@ -36,20 +34,6 @@ class USDZExporter {
3634
if ( ! ( material.uuid in materials ) ) {
3735

3836
materials[ material.uuid ] = material;
39-
// note: material.colorWhite dows not work (always true for some reason)
40-
const materialIsNotWhite = material.color.r != 1 || material.color.g != 1 || material.color.b != 1;
41-
if ( material.map !== null ) {
42-
if(materialIsNotWhite) {
43-
materialsWithColor.add(material);
44-
} else {
45-
textures[ material.map.uuid ] = material.map;
46-
}
47-
}
48-
if ( material.normalMap !== null ) textures[ material.normalMap.uuid ] = material.normalMap;
49-
if ( material.aoMap !== null ) textures[ material.aoMap.uuid ] = material.aoMap;
50-
if ( material.roughnessMap !== null ) textures[ material.roughnessMap.uuid ] = material.roughnessMap;
51-
if ( material.metalnessMap !== null ) textures[ material.metalnessMap.uuid ] = material.metalnessMap;
52-
if ( material.emissiveMap !== null ) textures[ material.emissiveMap.uuid ] = material.emissiveMap;
5337

5438
}
5539

@@ -59,34 +43,19 @@ class USDZExporter {
5943

6044
} );
6145

62-
for (const material of materialsWithColor) {
63-
const color256 = {
64-
r: Math.floor(material.color.r * 256),
65-
g: Math.floor(material.color.g * 256),
66-
b: Math.floor(material.color.b * 256),
67-
};
68-
const textureSignature = `${material.map.id}_${color256.r}_${color256.g}_${color256.b}`;
69-
const texturePath = `textures/Texture_${textureSignature}.jpg`;
70-
71-
if (!files[texturePath]) {
72-
files[texturePath] = await imgToU8(material.map.image, color256);
73-
}
74-
75-
coloredTextures.set(material, textureSignature);
76-
}
77-
78-
output += buildMaterials( materials, coloredTextures );
46+
output += buildMaterials( materials, textures );
7947

8048
files[ modelFileName ] = fflate.strToU8( output );
8149
output = null;
8250

83-
for ( const uuid in textures ) {
51+
for ( const id in textures ) {
8452

85-
const texture = textures[ uuid ];
86-
files[ 'textures/Texture_' + texture.id + '.jpg' ] = await imgToU8( texture.image );
53+
const texture = textures[ id ];
54+
const color = id.split( '_' )[ 1 ];
8755

88-
}
56+
files[ 'textures/Texture_' + id + '.jpg' ] = await imgToU8( texture.image, color );
8957

58+
}
9059

9160
// 64 byte alignment
9261
// https://github.com/101arrowz/fflate/issues/39#issuecomment-777263109
@@ -115,12 +84,7 @@ class USDZExporter {
11584

11685
}
11786

118-
return await new Promise((resolve, reject) => {
119-
fflate.zip(files, { level: 0 }, (err, zipped) => {
120-
if (err) reject(err);
121-
else resolve(zipped);
122-
});
123-
});
87+
return fflate.zipSync( files, { level: 0 } );
12488

12589
}
12690

@@ -142,10 +106,12 @@ async function imgToU8( image, color ) {
142106
const context = canvas.getContext( '2d' );
143107
context.drawImage( image, 0, 0, canvas.width, canvas.height );
144108

145-
if(!!color) {
146-
context.globalCompositeOperation = "multiply";
147-
context.fillStyle = `rgb(${color.r}, ${color.g}, ${color.b})`;
148-
context.fillRect(0, 0, image.width, image.height);
109+
if ( color !== undefined ) {
110+
111+
context.globalCompositeOperation = 'multiply';
112+
context.fillStyle = `#${ color }`;
113+
context.fillRect( 0, 0, canvas.width, canvas.height );
114+
149115
}
150116

151117
const blob = await new Promise( resolve => canvas.toBlob( resolve, 'image/jpeg', 1 ) );
@@ -330,15 +296,15 @@ function buildVector2Array( attribute, count ) {
330296

331297
// Materials
332298

333-
function buildMaterials( materials, coloredTextures ) {
299+
function buildMaterials( materials, textures ) {
334300

335301
const array = [];
336302

337303
for ( const uuid in materials ) {
338304

339305
const material = materials[ uuid ];
340306

341-
array.push( buildMaterial( material, coloredTextures ) );
307+
array.push( buildMaterial( material, textures ) );
342308

343309
}
344310

@@ -351,17 +317,20 @@ ${ array.join( '' ) }
351317

352318
}
353319

354-
function buildMaterial( material, coloredTextures ) {
320+
function buildMaterial( material, textures ) {
355321

356322
// https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html
357323

358324
const pad = ' ';
359-
const parameters = [];
360-
const textures = [];
325+
const inputs = [];
326+
const samplers = [];
327+
328+
function buildTexture( texture, mapType, color ) {
329+
330+
const id = texture.id + ( color ? '_' + color.getHexString() : '' );
361331

362-
function buildTexture( texture, mapType, textureSignature ) {
332+
textures[ id ] = texture;
363333

364-
const textureId = textureSignature || texture.id;
365334
return `
366335
def Shader "Transform2d_${ mapType }" (
367336
sdrMetadata = {
@@ -379,7 +348,7 @@ function buildMaterial( material, coloredTextures ) {
379348
def Shader "Texture_${ texture.id }_${ mapType }"
380349
{
381350
uniform token info:id = "UsdUVTexture"
382-
asset inputs:file = @textures/Texture_${ textureId }.jpg@
351+
asset inputs:file = @textures/Texture_${ id }.jpg@
383352
float2 inputs:st.connect = </Materials/Material_${ material.id }/Transform2d_${ mapType }.outputs:result>
384353
token inputs:wrapS = "repeat"
385354
token inputs:wrapT = "repeat"
@@ -393,95 +362,95 @@ function buildMaterial( material, coloredTextures ) {
393362

394363
if ( material.map !== null ) {
395364

396-
parameters.push( `${ pad }color3f inputs:diffuseColor.connect = </Materials/Material_${ material.id }/Texture_${ material.map.id }_diffuse.outputs:rgb>` );
365+
inputs.push( `${ pad }color3f inputs:diffuseColor.connect = </Materials/Material_${ material.id }/Texture_${ material.map.id }_diffuse.outputs:rgb>` );
397366

398-
textures.push( buildTexture( material.map, 'diffuse', coloredTextures.get(material) ) );
367+
samplers.push( buildTexture( material.map, 'diffuse', material.color ) );
399368

400369
} else {
401370

402-
parameters.push( `${ pad }color3f inputs:diffuseColor = ${ buildColor( material.color ) }` );
371+
inputs.push( `${ pad }color3f inputs:diffuseColor = ${ buildColor( material.color ) }` );
403372

404373
}
405374

406375
if ( material.emissiveMap !== null ) {
407376

408-
parameters.push( `${ pad }color3f inputs:emissiveColor.connect = </Materials/Material_${ material.id }/Texture_${ material.emissiveMap.id }_emissive.outputs:rgb>` );
377+
inputs.push( `${ pad }color3f inputs:emissiveColor.connect = </Materials/Material_${ material.id }/Texture_${ material.emissiveMap.id }_emissive.outputs:rgb>` );
409378

410-
textures.push( buildTexture( material.emissiveMap, 'emissive' ) );
379+
samplers.push( buildTexture( material.emissiveMap, 'emissive' ) );
411380

412381
} else if ( material.emissive.getHex() > 0 ) {
413382

414-
parameters.push( `${ pad }color3f inputs:emissiveColor = ${ buildColor( material.emissive ) }` );
383+
inputs.push( `${ pad }color3f inputs:emissiveColor = ${ buildColor( material.emissive ) }` );
415384

416385
}
417386

418387
if ( material.normalMap !== null ) {
419388

420-
parameters.push( `${ pad }normal3f inputs:normal.connect = </Materials/Material_${ material.id }/Texture_${ material.normalMap.id }_normal.outputs:rgb>` );
389+
inputs.push( `${ pad }normal3f inputs:normal.connect = </Materials/Material_${ material.id }/Texture_${ material.normalMap.id }_normal.outputs:rgb>` );
421390

422-
textures.push( buildTexture( material.normalMap, 'normal' ) );
391+
samplers.push( buildTexture( material.normalMap, 'normal' ) );
423392

424393
}
425394

426395
if ( material.aoMap !== null ) {
427396

428-
parameters.push( `${ pad }float inputs:occlusion.connect = </Materials/Material_${ material.id }/Texture_${ material.aoMap.id }_occlusion.outputs:r>` );
397+
inputs.push( `${ pad }float inputs:occlusion.connect = </Materials/Material_${ material.id }/Texture_${ material.aoMap.id }_occlusion.outputs:r>` );
429398

430-
textures.push( buildTexture( material.aoMap, 'occlusion' ) );
399+
samplers.push( buildTexture( material.aoMap, 'occlusion' ) );
431400

432401
}
433402

434403
if ( material.roughnessMap !== null ) {
435404

436-
parameters.push( `${ pad }float inputs:roughness.connect = </Materials/Material_${ material.id }/Texture_${ material.roughnessMap.id }_roughness.outputs:g>` );
405+
inputs.push( `${ pad }float inputs:roughness.connect = </Materials/Material_${ material.id }/Texture_${ material.roughnessMap.id }_roughness.outputs:g>` );
437406

438-
textures.push( buildTexture( material.roughnessMap, 'roughness' ) );
407+
samplers.push( buildTexture( material.roughnessMap, 'roughness' ) );
439408

440409
} else {
441410

442-
parameters.push( `${ pad }float inputs:roughness = ${ material.roughness }` );
411+
inputs.push( `${ pad }float inputs:roughness = ${ material.roughness }` );
443412

444413
}
445414

446415
if ( material.metalnessMap !== null ) {
447416

448-
parameters.push( `${ pad }float inputs:metallic.connect = </Materials/Material_${ material.id }/Texture_${ material.metalnessMap.id }_metallic.outputs:b>` );
417+
inputs.push( `${ pad }float inputs:metallic.connect = </Materials/Material_${ material.id }/Texture_${ material.metalnessMap.id }_metallic.outputs:b>` );
449418

450-
textures.push( buildTexture( material.metalnessMap, 'metallic' ) );
419+
samplers.push( buildTexture( material.metalnessMap, 'metallic' ) );
451420

452421
} else {
453422

454-
parameters.push( `${ pad }float inputs:metallic = ${ material.metalness }` );
423+
inputs.push( `${ pad }float inputs:metallic = ${ material.metalness }` );
455424

456425
}
457426

458-
parameters.push( `${ pad }float inputs:opacity = ${ material.opacity }` );
427+
inputs.push( `${ pad }float inputs:opacity = ${ material.opacity }` );
459428

460429
return `
461-
def Material "Material_${ material.id }"
462-
{
463-
def Shader "PreviewSurface"
464-
{
465-
uniform token info:id = "UsdPreviewSurface"
466-
${ parameters.join( '\n' ) }
467-
int inputs:useSpecularWorkflow = 0
468-
token outputs:surface
469-
}
430+
def Material "Material_${ material.id }"
431+
{
432+
def Shader "PreviewSurface"
433+
{
434+
uniform token info:id = "UsdPreviewSurface"
435+
${ inputs.join( '\n' ) }
436+
int inputs:useSpecularWorkflow = 0
437+
token outputs:surface
438+
}
470439
471-
token outputs:surface.connect = </Materials/Material_${ material.id }/PreviewSurface.outputs:surface>
472-
token inputs:frame:stPrimvarName = "st"
440+
token outputs:surface.connect = </Materials/Material_${ material.id }/PreviewSurface.outputs:surface>
441+
token inputs:frame:stPrimvarName = "st"
473442
474-
def Shader "uvReader_st"
475-
{
476-
uniform token info:id = "UsdPrimvarReader_float2"
477-
token inputs:varname.connect = </Materials/Material_${ material.id }.inputs:frame:stPrimvarName>
478-
float2 inputs:fallback = (0.0, 0.0)
479-
float2 outputs:result
480-
}
443+
def Shader "uvReader_st"
444+
{
445+
uniform token info:id = "UsdPrimvarReader_float2"
446+
token inputs:varname.connect = </Materials/Material_${ material.id }.inputs:frame:stPrimvarName>
447+
float2 inputs:fallback = (0.0, 0.0)
448+
float2 outputs:result
449+
}
481450
482-
${ textures.join( '\n' ) }
451+
${ samplers.join( '\n' ) }
483452
484-
}
453+
}
485454
`;
486455

487456
}

0 commit comments

Comments
 (0)