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

MeshPhysicalMaterial: Support iridescence / thin-film materials #23869

Merged
merged 18 commits into from
May 25, 2022
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
1 change: 1 addition & 0 deletions docs/examples/en/loaders/GLTFLoader.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ <h2>Extensions</h2>
<li>KHR_materials_pbrSpecularGlossiness</li>
<li>KHR_materials_specular</li>
<li>KHR_materials_transmission</li>
<li>KHR_materials_iridescence</li>
<li>KHR_materials_unlit</li>
<li>KHR_materials_volume</li>
<li>KHR_mesh_quantization</li>
Expand Down
1 change: 1 addition & 0 deletions docs/examples/zh/loaders/GLTFLoader.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ <h2>扩展</h2>
<li>KHR_materials_pbrSpecularGlossiness</li>
<li>KHR_materials_specular</li>
<li>KHR_materials_transmission</li>
<li>KHR_materials_iridescence</li>
<li>KHR_materials_unlit</li>
<li>KHR_materials_volume</li>
<li>KHR_mesh_quantization</li>
Expand Down
52 changes: 51 additions & 1 deletion editor/js/Sidebar.Material.MapProperty.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as THREE from 'three';

import { UICheckbox, UINumber, UIRow, UIText } from './libs/ui.js';
import { UICheckbox, UIDiv, UINumber, UIRow, UIText } from './libs/ui.js';
import { UITexture } from './libs/ui.three.js';
import { SetMaterialMapCommand } from './commands/SetMaterialMapCommand.js';
import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
import { SetMaterialRangeCommand } from './commands/SetMaterialRangeCommand.js';
import { SetMaterialVectorCommand } from './commands/SetMaterialVectorCommand.js';

function SidebarMaterialMapProperty( editor, property, name ) {
Expand Down Expand Up @@ -51,6 +52,36 @@ function SidebarMaterialMapProperty( editor, property, name ) {

}

let rangeMin, rangeMax;

if ( property === 'iridescenceThicknessMap' ) {

const range = new UIDiv().setMarginLeft( '3px' );
container.add( range );

const rangeMinRow = new UIRow().setMarginBottom( '0px' ).setStyle( 'min-height', '0px' );
range.add( rangeMinRow );

rangeMinRow.add( new UIText( 'min:' ).setWidth( '35px' ) );

rangeMin = new UINumber().setWidth( '40px' ).onChange( onRangeChange );
rangeMinRow.add( rangeMin );

const rangeMaxRow = new UIRow().setMarginBottom( '6px' ).setStyle( 'min-height', '0px' );
range.add( rangeMaxRow );

rangeMaxRow.add( new UIText( 'max:' ).setWidth( '35px' ) );

rangeMax = new UINumber().setWidth( '40px' ).onChange( onRangeChange );
rangeMaxRow.add( rangeMax );

// Additional settings for iridescenceThicknessMap
// Please add conditional if more maps are having a range property
rangeMin.setPrecision( 0 ).setRange( 0, Infinity ).setNudge( 1 ).setStep( 10 ).setUnit( 'nm' );
rangeMax.setPrecision( 0 ).setRange( 0, Infinity ).setNudge( 1 ).setStep( 10 ).setUnit( 'nm' );

}

let object = null;
let material = null;

Expand Down Expand Up @@ -127,6 +158,18 @@ function SidebarMaterialMapProperty( editor, property, name ) {

}

function onRangeChange() {

const value = [ rangeMin.getValue(), rangeMax.getValue() ];

if ( material[ `${ mapType }Range` ][ 0 ] !== value[ 0 ] || material[ `${ mapType }Range` ][ 1 ] !== value[ 1 ] ) {

editor.execute( new SetMaterialRangeCommand( editor, object, `${ mapType }Range`, value[ 0 ], value[ 1 ], 0 /* TODOL currentMaterialSlot */ ) );

}

}

function update() {

if ( object === null ) return;
Expand Down Expand Up @@ -164,6 +207,13 @@ function SidebarMaterialMapProperty( editor, property, name ) {

}

if ( rangeMin !== undefined ) {

rangeMin.setValue( material[ `${ mapType }Range` ][ 0 ] );
rangeMax.setValue( material[ `${ mapType }Range` ][ 1 ] );

}

container.setDisplay( '' );

} else {
Expand Down
66 changes: 66 additions & 0 deletions editor/js/Sidebar.Material.RangeValueProperty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { UINumber, UIRow, UIText } from './libs/ui.js';
import { SetMaterialRangeCommand } from './commands/SetMaterialRangeCommand.js';

function SidebarMaterialRangeValueProperty( editor, property, name, isMin, range = [ - Infinity, Infinity ], precision = 2, step = 1, nudge = 0.01, unit = '' ) {

const signals = editor.signals;

const container = new UIRow();
container.add( new UIText( name ).setWidth( '90px' ) );

const number = new UINumber().setWidth( '60px' ).setRange( range[ 0 ], range[ 1 ] ).setPrecision( precision ).setStep( step ).setNudge( nudge ).setUnit( unit ).onChange( onChange );
container.add( number );

let object = null;
let material = null;

function onChange() {

if ( material[ property ][ isMin ? 0 : 1 ] !== number.getValue() ) {

const minValue = isMin ? number.getValue() : material[ property ][ 0 ];
const maxValue = isMin ? material[ property ][ 1 ] : number.getValue();

editor.execute( new SetMaterialRangeCommand( editor, object, property, minValue, maxValue, 0 /* TODO: currentMaterialSlot */ ) );

}

}

function update() {

if ( object === null ) return;
if ( object.material === undefined ) return;

material = object.material;

if ( property in material ) {

number.setValue( material[ property ][ isMin ? 0 : 1 ] );
container.setDisplay( '' );

} else {

container.setDisplay( 'none' );

}

}

//

signals.objectSelected.add( function ( selected ) {

object = selected;

update();

} );

signals.materialChanged.add( update );

return container;

}

export { SidebarMaterialRangeValueProperty };
26 changes: 26 additions & 0 deletions editor/js/Sidebar.Material.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { SidebarMaterialColorProperty } from './Sidebar.Material.ColorProperty.j
import { SidebarMaterialConstantProperty } from './Sidebar.Material.ConstantProperty.js';
import { SidebarMaterialMapProperty } from './Sidebar.Material.MapProperty.js';
import { SidebarMaterialNumberProperty } from './Sidebar.Material.NumberProperty.js';
import { SidebarMaterialRangeValueProperty } from './Sidebar.Material.RangeValueProperty.js';
import { SidebarMaterialProgram } from './Sidebar.Material.Program.js';

function SidebarMaterial( editor ) {
Expand Down Expand Up @@ -130,6 +131,21 @@ function SidebarMaterial( editor ) {
const materialClearcoatRoughness = new SidebarMaterialNumberProperty( editor, 'clearcoatRoughness', strings.getKey( 'sidebar/material/clearcoatroughness' ), [ 0, 1 ] );
container.add( materialClearcoatRoughness );

// iridescence

const materialIridescence = new SidebarMaterialNumberProperty( editor, 'iridescence', strings.getKey( 'sidebar/material/iridescence' ), [ 0, 1 ] );
container.add( materialIridescence );

// iridescenceIOR

const materialIridescenceIOR = new SidebarMaterialNumberProperty( editor, 'iridescenceIOR', strings.getKey( 'sidebar/material/iridescenceIOR' ), [ 1, 5 ] );
container.add( materialIridescenceIOR );

// iridescenceThicknessMax

const materialIridescenceThicknessMax = new SidebarMaterialRangeValueProperty( editor, 'iridescenceThicknessRange', strings.getKey( 'sidebar/material/iridescenceThicknessMax' ), false, [ 0, Infinity ], 0, 10, 1, 'nm' );
container.add( materialIridescenceThicknessMax );

// transmission

const materialTransmission = new SidebarMaterialNumberProperty( editor, 'transmission', strings.getKey( 'sidebar/material/transmission' ), [ 0, 1 ] );
Expand Down Expand Up @@ -220,6 +236,16 @@ function SidebarMaterial( editor ) {
const materialMetalnessMap = new SidebarMaterialMapProperty( editor, 'metalnessMap', strings.getKey( 'sidebar/material/metalnessmap' ) );
container.add( materialMetalnessMap );

// iridescence map

const materialIridescenceMap = new SidebarMaterialMapProperty( editor, 'iridescenceMap', strings.getKey( 'sidebar/material/iridescencemap' ) );
container.add( materialIridescenceMap );

// iridescence thickness map

const materialIridescenceThicknessMap = new SidebarMaterialMapProperty( editor, 'iridescenceThicknessMap', strings.getKey( 'sidebar/material/iridescencethicknessmap' ) );
container.add( materialIridescenceThicknessMap );

// env map

const materialEnvMap = new SidebarMaterialMapProperty( editor, 'envMap', strings.getKey( 'sidebar/material/envmap' ) );
Expand Down
5 changes: 5 additions & 0 deletions editor/js/Strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ function Strings( config ) {
'sidebar/material/shininess': 'Shininess',
'sidebar/material/clearcoat': 'Clearcoat',
'sidebar/material/clearcoatroughness': 'Clearcoat Roughness',
'sidebar/material/iridescence': 'Iridescence',
'sidebar/material/iridescenceIOR': 'Thin-Film IOR',
'sidebar/material/iridescenceThicknessMax': 'Thin-Film Thickness',
'sidebar/material/transmission': 'Transmission',
'sidebar/material/attenuationDistance': 'Attenuation Distance',
'sidebar/material/attenuationColor': 'Attenuation Color',
Expand All @@ -264,6 +267,8 @@ function Strings( config ) {
'sidebar/material/roughnessmap': 'Rough. Map',
'sidebar/material/metalnessmap': 'Metal. Map',
'sidebar/material/specularmap': 'Specular Map',
'sidebar/material/iridescencemap': 'Irid. Map',
'sidebar/material/iridescencethicknessmap': 'Thin-Film Thickness Map',
'sidebar/material/envmap': 'Env Map',
'sidebar/material/lightmap': 'Light Map',
'sidebar/material/aomap': 'AO Map',
Expand Down
83 changes: 83 additions & 0 deletions editor/js/commands/SetMaterialRangeCommand.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Command } from '../Command.js';

/**
* @param editor Editor
* @param object THREE.Object3D
* @param attributeName string
* @param newMinValue number
* @param newMaxValue number
* @constructor
*/
class SetMaterialRangeCommand extends Command {

constructor( editor, object, attributeName, newMinValue, newMaxValue, materialSlot ) {

super( editor );

this.type = 'SetMaterialRangeCommand';
this.name = `Set Material.${attributeName}`;
this.updatable = true;

this.object = object;
this.material = this.editor.getObjectMaterial( object, materialSlot );

this.oldRange = ( this.material !== undefined && this.material[ attributeName ] !== undefined ) ? [ ...this.material[ attributeName ] ] : undefined;
this.newRange = [ newMinValue, newMaxValue ];

this.attributeName = attributeName;

}

execute() {

this.material[ this.attributeName ] = [ ...this.newRange ];
this.material.needsUpdate = true;

this.editor.signals.objectChanged.dispatch( this.object );
this.editor.signals.materialChanged.dispatch( this.material );

}

undo() {

this.material[ this.attributeName ] = [ ...this.oldRange ];
this.material.needsUpdate = true;

this.editor.signals.objectChanged.dispatch( this.object );
this.editor.signals.materialChanged.dispatch( this.material );

}

update( cmd ) {

this.newRange = [ ...cmd.newRange ];

}

toJSON() {

const output = super.toJSON( this );

output.objectUuid = this.object.uuid;
output.attributeName = this.attributeName;
output.oldRange = [ ...this.oldRange ];
output.newRange = [ ...this.newRange ];

return output;

}

fromJSON( json ) {

super.fromJSON( json );

this.attributeName = json.attributeName;
this.oldRange = [ ...json.oldRange ];
this.newRange = [ ...json.newRange ];
this.object = this.editor.objectByUuid( json.objectUuid );

}

}

export { SetMaterialRangeCommand };
Loading