Skip to content

Commit

Permalink
WebGPURenderer: Iridescence (#26489)
Browse files Browse the repository at this point in the history
* LightingModel: New class struct

* cleanup

* cleanup

* AONode: Fix float value

* SpriteNodeMaterial: Force float type in rotation

* PhysicalLightingModel: Add iridescence

* Add webgpu_loader_gltf_iridescence example
  • Loading branch information
sunag committed Jul 25, 2023
1 parent 4a75811 commit ffd9884
Show file tree
Hide file tree
Showing 12 changed files with 355 additions and 76 deletions.
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@
"webgpu_lights_selective",
"webgpu_loader_gltf",
"webgpu_loader_gltf_compressed",
"webgpu_loader_gltf_iridescence",
"webgpu_loader_gltf_sheen",
"webgpu_materials",
"webgpu_materials_video",
Expand Down
68 changes: 27 additions & 41 deletions examples/jsm/nodes/accessors/MaterialNode.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Node, { addNodeClass } from '../core/Node.js';
import { reference } from './ReferenceNode.js';
import { materialReference } from './MaterialReferenceNode.js';
import { nodeImmutable, float } from '../shadernode/ShaderNode.js';

Expand All @@ -12,31 +13,6 @@ class MaterialNode extends Node {

}

getNodeType( builder ) {

const scope = this.scope;
const material = builder.context.material;

if ( scope === MaterialNode.COLOR ) {

return material.map !== null ? 'vec4' : 'vec3';

} else if ( scope === MaterialNode.OPACITY || scope === MaterialNode.ROTATION ) {

return 'float';

} else if ( scope === MaterialNode.EMISSIVE || scope === MaterialNode.SHEEN ) {

return 'vec3';

} else if ( scope === MaterialNode.ROUGHNESS || scope === MaterialNode.METALNESS || scope === MaterialNode.SPECULAR || scope === MaterialNode.SHININESS || scope === MaterialNode.CLEARCOAT_ROUGHNESS || scope === MaterialNode.SHEEN_ROUGHNESS ) {

return 'float';

}

}

getFloat( property ) {

//@TODO: Check if it can be cached by property name.
Expand Down Expand Up @@ -70,9 +46,13 @@ class MaterialNode extends Node {

let node = null;

if ( scope === MaterialNode.ALPHA_TEST ) {
if ( scope === MaterialNode.ALPHA_TEST || scope === MaterialNode.SHININESS || scope === MaterialNode.REFLECTIVITY || scope === MaterialNode.ROTATION || scope === MaterialNode.IRIDESCENCE || scope === MaterialNode.IRIDESCENCE_IOR ) {

node = this.getFloat( scope );

} else if ( scope === MaterialNode.SPECULAR_COLOR ) {

node = this.getFloat( 'alphaTest' );
node = this.getColor( 'specular' );

} else if ( scope === MaterialNode.COLOR ) {

Expand Down Expand Up @@ -102,14 +82,6 @@ class MaterialNode extends Node {

}

} else if ( scope === MaterialNode.SHININESS ) {

node = this.getFloat( 'shininess' );

} else if ( scope === MaterialNode.SPECULAR_COLOR ) {

node = this.getColor( 'specular' );

} else if ( scope === MaterialNode.SPECULAR_STRENGTH ) {

if ( material.specularMap && material.specularMap.isTexture === true ) {
Expand All @@ -122,10 +94,6 @@ class MaterialNode extends Node {

}

} else if ( scope === MaterialNode.REFLECTIVITY ) {

node = this.getFloat( 'reflectivity' );

} else if ( scope === MaterialNode.ROUGHNESS ) {

const roughnessNode = this.getFloat( 'roughness' );
Expand Down Expand Up @@ -226,9 +194,21 @@ class MaterialNode extends Node {

node = node.clamp( 0.07, 1.0 );

} else if ( scope === MaterialNode.ROTATION ) {
} else if ( scope === MaterialNode.IRIDESCENCE_THICKNESS ) {

const iridescenceThicknessMaximum = reference( 1, 'float', material.iridescenceThicknessRange );

if ( material.iridescenceThicknessMap ) {

const iridescenceThicknessMinimum = reference( 0, 'float', material.iridescenceThicknessRange );

node = iridescenceThicknessMaximum.sub( iridescenceThicknessMinimum ).mul( this.getTexture( 'iridescenceThicknessMap' ).g ).add( iridescenceThicknessMinimum );

node = this.getFloat( 'rotation' );
} else {

node = iridescenceThicknessMaximum;

}

} else {

Expand Down Expand Up @@ -259,6 +239,9 @@ MaterialNode.EMISSIVE = 'emissive';
MaterialNode.ROTATION = 'rotation';
MaterialNode.SHEEN = 'sheen';
MaterialNode.SHEEN_ROUGHNESS = 'sheenRoughness';
MaterialNode.IRIDESCENCE = 'iridescence';
MaterialNode.IRIDESCENCE_IOR = 'iridescenceIOR';
MaterialNode.IRIDESCENCE_THICKNESS = 'iridescenceThickness';

export default MaterialNode;

Expand All @@ -277,5 +260,8 @@ export const materialClearcoatRoughness = nodeImmutable( MaterialNode, MaterialN
export const materialRotation = nodeImmutable( MaterialNode, MaterialNode.ROTATION );
export const materialSheen = nodeImmutable( MaterialNode, MaterialNode.SHEEN );
export const materialSheenRoughness = nodeImmutable( MaterialNode, MaterialNode.SHEEN_ROUGHNESS );
export const materialIridescence = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE );
export const materialIridescenceIOR = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_IOR );
export const materialIridescenceThickness = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_THICKNESS );

addNodeClass( MaterialNode );
3 changes: 3 additions & 0 deletions examples/jsm/nodes/core/PropertyNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ export const clearcoat = nodeImmutable( PropertyNode, 'float', 'Clearcoat' );
export const clearcoatRoughness = nodeImmutable( PropertyNode, 'float', 'ClearcoatRoughness' );
export const sheen = nodeImmutable( PropertyNode, 'vec3', 'Sheen' );
export const sheenRoughness = nodeImmutable( PropertyNode, 'float', 'SheenRoughness' );
export const iridescence = nodeImmutable( PropertyNode, 'float', 'Iridescence' );
export const iridescenceIOR = nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' );
export const iridescenceThickness = nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' );
export const specularColor = nodeImmutable( PropertyNode, 'color', 'SpecularColor' );
export const shininess = nodeImmutable( PropertyNode, 'float', 'Shininess' );
export const output = nodeImmutable( PropertyNode, 'vec4', 'Output' );
Expand Down
12 changes: 10 additions & 2 deletions examples/jsm/nodes/functions/BSDF/BRDF_GGX.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import V_GGX_SmithCorrelated from './V_GGX_SmithCorrelated.js';
import D_GGX from './D_GGX.js';
import { transformedNormalView } from '../../accessors/NormalNode.js';
import { positionViewDirection } from '../../accessors/PositionNode.js';
import { iridescence } from '../../core/PropertyNode.js';
import { tslFn } from '../../shadernode/ShaderNode.js';

// GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility
const BRDF_GGX = tslFn( ( inputs ) => {

const { lightDirection, f0, f90, roughness } = inputs;
const { lightDirection, f0, f90, roughness, iridescenceFresnel } = inputs;

const normalView = inputs.normalView || transformedNormalView;

Expand All @@ -21,7 +22,14 @@ const BRDF_GGX = tslFn( ( inputs ) => {
const dotNH = normalView.dot( halfDir ).clamp();
const dotVH = positionViewDirection.dot( halfDir ).clamp();

const F = F_Schlick( { f0, f90, dotVH } );
let F = F_Schlick( { f0, f90, dotVH } );

if ( iridescenceFresnel ) {

F = iridescence.mix( F, iridescenceFresnel );

}

const V = V_GGX_SmithCorrelated( { alpha, dotNL, dotNV } );
const D = D_GGX( { alpha, dotNH } );

Expand Down
13 changes: 13 additions & 0 deletions examples/jsm/nodes/functions/BSDF/Schlick_to_F0.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { tslFn, vec3 } from '../../shadernode/ShaderNode.js';

const Schlick_to_F0 = tslFn( ( { f, f90, dotVH } ) => {

const x = dotVH.oneMinus().saturate();
const x2 = x.mul( x );
const x5 = x.mul( x2, x2 ).clamp( 0, .9999 );

return f.sub( vec3( f90 ).mul( x5 ) ).div( x5.oneMinus() );

} );

export default Schlick_to_F0;

0 comments on commit ffd9884

Please sign in to comment.