diff --git a/packages/model-viewer/src/features/scene-graph/api.ts b/packages/model-viewer/src/features/scene-graph/api.ts index 5455b0b0e0..a1ad2e8e52 100644 --- a/packages/model-viewer/src/features/scene-graph/api.ts +++ b/packages/model-viewer/src/features/scene-graph/api.ts @@ -126,11 +126,35 @@ export declare interface Material { readonly clearcoatRoughnessTexture: TextureInfo|null; readonly clearcoatNormalTexture: TextureInfo|null; readonly clearcoatNormalScale: number; + readonly ior: number; + readonly sheenColorFactor: Readonly; + readonly sheenColorTexture: TextureInfo|null; + readonly sheenRoughnessFactor: number; + readonly sheenRoughnessTexture: TextureInfo|null; + readonly transmissionFactor: number; + readonly transmissionTexture: TextureInfo|null; + readonly thicknessFactor: number; + readonly thicknessTexture: TextureInfo|null; + readonly attenuationDistance: number; + readonly attenuationColor: Readonly; + readonly specularFactor: number; + readonly specularTexture: TextureInfo|null; + readonly specularColorFactor: Readonly; + readonly specularColorTexture: TextureInfo|null; setEmissiveStrength(emissiveStrength: number): void; setClearcoatFactor(clearcoatFactor: number): void; setClearcoatRoughnessFactor(clearcoatRoughnessFactor: number): void; setClearcoatNormalScale(clearcoatNormalScale: number): void; + setIor(ior: number): void; + setSheenColorFactor(rgb: RGB|string): void; + setSheenRoughnessFactor(roughness: number): void; + setTransmissionFactor(transmission: number): void; + setThicknessFactor(thickness: number): void; + setAttenuationDistance(attenuationDistance: number): void; + setAttenuationColor(rgb: RGB|string): void; + setSpecularFactor(specularFactor: number): void; + setSpecularColorFactor(rgb: RGB|string): void; /** * The PBRMetallicRoughness configuration of the material. diff --git a/packages/model-viewer/src/features/scene-graph/material.ts b/packages/model-viewer/src/features/scene-graph/material.ts index bacb685a5d..5f11aec018 100644 --- a/packages/model-viewer/src/features/scene-graph/material.ts +++ b/packages/model-viewer/src/features/scene-graph/material.ts @@ -43,13 +43,7 @@ const $isActive = Symbol('isActive'); export const $variantSet = Symbol('variantSet'); const $modelVariants = Symbol('modelVariants'); const $name = Symbol('name'); - -/** - * PBR Next properties. - */ -const $clearcoatTexture = Symbol('clearcoatTexture'); -const $clearcoatRoughnessTexture = Symbol('clearcoatRoughnessTexture'); -const $clearcoatNormalTexture = Symbol('clearcoatNormalTexture'); +const $pbrTextures = Symbol('pbrTextures'); /** * Material facade implementation for Three.js materials @@ -65,13 +59,7 @@ export class Material extends ThreeDOMElement implements MaterialInterface { private[$variantSet] = new Set(); private[$name]?: string; readonly[$modelVariants]: Map; - - /** - * PBR Next properties. - */ - private[$clearcoatTexture]!: TextureInfo; - private[$clearcoatRoughnessTexture]!: TextureInfo; - private[$clearcoatNormalTexture]!: TextureInfo; + private[$pbrTextures] = new Map(); get[$backingThreeMaterial](): MeshPhysicalMaterial { return (this[$correlatedObjects] as Set) @@ -134,26 +122,26 @@ export class Material extends ThreeDOMElement implements MaterialInterface { correlatedMaterials, ); - this[$clearcoatTexture] = new TextureInfo( - onUpdate, - TextureUsage.Clearcoat, - null, - correlatedMaterials, - ); - - this[$clearcoatRoughnessTexture] = new TextureInfo( - onUpdate, - TextureUsage.ClearcoatRoughness, - null, - correlatedMaterials, - ); - - this[$clearcoatNormalTexture] = new TextureInfo( - onUpdate, - TextureUsage.ClearcoatNormal, - null, - correlatedMaterials, - ); + const createTextureInfo = (usage: TextureUsage) => { + this[$pbrTextures].set( + usage, + new TextureInfo( + onUpdate, + usage, + null, + correlatedMaterials, + )); + }; + + createTextureInfo(TextureUsage.Clearcoat); + createTextureInfo(TextureUsage.ClearcoatRoughness); + createTextureInfo(TextureUsage.ClearcoatNormal); + createTextureInfo(TextureUsage.SheenColor); + createTextureInfo(TextureUsage.SheenRoughness); + createTextureInfo(TextureUsage.Transmission); + createTextureInfo(TextureUsage.Thickness); + createTextureInfo(TextureUsage.Specular); + createTextureInfo(TextureUsage.SpecularColor); } async[$getLoadedMaterial](): Promise { @@ -173,6 +161,16 @@ export class Material extends ThreeDOMElement implements MaterialInterface { return this[$correlatedObjects]!.values().next().value; } + private colorFromRgb(rgb: RGB|string): Color { + const color = new Color(); + if (rgb instanceof Array) { + color.fromArray(rgb); + } else { + color.set(rgb as ColorRepresentation); + } + return color; + } + [$ensureMaterialIsLoaded]() { if (this[$lazyLoadGLTFInfo] == null) { return; @@ -250,12 +248,7 @@ export class Material extends ThreeDOMElement implements MaterialInterface { setEmissiveFactor(rgb: RGB|string) { this[$ensureMaterialIsLoaded](); - const color = new Color(); - if (rgb instanceof Array) { - color.fromArray(rgb); - } else { - color.set(rgb as ColorRepresentation); - } + const color = this.colorFromRgb(rgb); for (const material of this[$correlatedObjects] as Set) { material.emissive.set(color); @@ -356,11 +349,23 @@ export class Material extends ThreeDOMElement implements MaterialInterface { /** * PBR Next properties. */ + + // KHR_materials_emissive_strength get emissiveStrength(): number { this[$ensureMaterialIsLoaded](); return this[$backingThreeMaterial].emissiveIntensity; } + setEmissiveStrength(emissiveStrength: number) { + this[$ensureMaterialIsLoaded](); + for (const material of this[$correlatedObjects] as + Set) { + material.emissiveIntensity = emissiveStrength; + } + this[$onUpdate](); + } + + // KHR_materials_clearcoat get clearcoatFactor(): number { this[$ensureMaterialIsLoaded](); return this[$backingThreeMaterial].clearcoat; @@ -373,17 +378,17 @@ export class Material extends ThreeDOMElement implements MaterialInterface { get clearcoatTexture(): TextureInfo { this[$ensureMaterialIsLoaded](); - return this[$clearcoatTexture]; + return this[$pbrTextures].get(TextureUsage.Clearcoat)!; } get clearcoatRoughnessTexture(): TextureInfo { this[$ensureMaterialIsLoaded](); - return this[$clearcoatRoughnessTexture]; + return this[$pbrTextures].get(TextureUsage.ClearcoatRoughness)!; } get clearcoatNormalTexture(): TextureInfo { this[$ensureMaterialIsLoaded](); - return this[$clearcoatNormalTexture]; + return this[$pbrTextures].get(TextureUsage.ClearcoatNormal)!; } get clearcoatNormalScale(): number { @@ -391,15 +396,6 @@ export class Material extends ThreeDOMElement implements MaterialInterface { return this[$backingThreeMaterial].clearcoatNormalScale.x; } - setEmissiveStrength(emissiveStrength: number) { - this[$ensureMaterialIsLoaded](); - for (const material of this[$correlatedObjects] as - Set) { - material.emissiveIntensity = emissiveStrength; - } - this[$onUpdate](); - } - setClearcoatFactor(clearcoatFactor: number) { this[$ensureMaterialIsLoaded](); for (const material of this[$correlatedObjects] as @@ -427,4 +423,173 @@ export class Material extends ThreeDOMElement implements MaterialInterface { } this[$onUpdate](); } + + // KHR_materials_ior + get ior(): number { + this[$ensureMaterialIsLoaded](); + return this[$backingThreeMaterial].ior; + } + + setIor(ior: number) { + this[$ensureMaterialIsLoaded](); + for (const material of this[$correlatedObjects] as + Set) { + material.ior = ior; + } + this[$onUpdate](); + } + + // KHR_materials_sheen + get sheenColorFactor(): RGB { + this[$ensureMaterialIsLoaded](); + return (this[$backingThreeMaterial].sheenColor.toArray() as RGB); + } + get sheenColorTexture(): TextureInfo { + this[$ensureMaterialIsLoaded](); + return this[$pbrTextures].get(TextureUsage.SheenColor)!; + } + + get sheenRoughnessFactor(): number { + this[$ensureMaterialIsLoaded](); + return this[$backingThreeMaterial].sheenRoughness; + } + + get sheenRoughnessTexture(): TextureInfo { + this[$ensureMaterialIsLoaded](); + return this[$pbrTextures].get(TextureUsage.SheenRoughness)!; + } + + setSheenColorFactor(rgb: RGB|string) { + this[$ensureMaterialIsLoaded](); + const color = this.colorFromRgb(rgb); + for (const material of this[$correlatedObjects] as + Set) { + material.sheenColor.set(color); + // Three.js GLTFExporter checks for internal sheen value. + material.sheen = 1; + } + this[$onUpdate](); + } + + setSheenRoughnessFactor(roughness: number) { + this[$ensureMaterialIsLoaded](); + for (const material of this[$correlatedObjects] as + Set) { + material.sheenRoughness = roughness; + // Three.js GLTFExporter checks for internal sheen value. + material.sheen = 1; + } + this[$onUpdate](); + } + + // KHR_materials_transmission + get transmissionFactor(): number { + this[$ensureMaterialIsLoaded](); + return this[$backingThreeMaterial].transmission; + } + + get transmissionTexture(): TextureInfo { + this[$ensureMaterialIsLoaded](); + return this[$pbrTextures].get(TextureUsage.Transmission)!; + } + + setTransmissionFactor(transmission: number) { + this[$ensureMaterialIsLoaded](); + for (const material of this[$correlatedObjects] as + Set) { + material.transmission = transmission; + } + this[$onUpdate](); + } + + // KHR_materials_volume + get thicknessFactor(): number { + this[$ensureMaterialIsLoaded](); + return this[$backingThreeMaterial].thickness; + } + + get thicknessTexture(): TextureInfo { + this[$ensureMaterialIsLoaded](); + return this[$pbrTextures].get(TextureUsage.Thickness)!; + } + + get attenuationDistance(): number { + this[$ensureMaterialIsLoaded](); + return this[$backingThreeMaterial].attenuationDistance; + } + + get attenuationColor(): RGB { + this[$ensureMaterialIsLoaded](); + return (this[$backingThreeMaterial].attenuationColor.toArray() as RGB); + } + + setThicknessFactor(thickness: number) { + this[$ensureMaterialIsLoaded](); + for (const material of this[$correlatedObjects] as + Set) { + material.thickness = thickness; + } + this[$onUpdate](); + } + + setAttenuationDistance(attenuationDistance: number) { + this[$ensureMaterialIsLoaded](); + for (const material of this[$correlatedObjects] as + Set) { + material.attenuationDistance = attenuationDistance; + } + this[$onUpdate](); + } + + setAttenuationColor(rgb: RGB|string) { + this[$ensureMaterialIsLoaded](); + const color = this.colorFromRgb(rgb); + for (const material of this[$correlatedObjects] as + Set) { + material.attenuationColor.set(color); + } + this[$onUpdate](); + } + + // KHR_materials_specular + get specularFactor(): number { + this[$ensureMaterialIsLoaded](); + return this[$backingThreeMaterial].specularIntensity; + } + + get specularTexture(): TextureInfo { + this[$ensureMaterialIsLoaded](); + return this[$pbrTextures].get(TextureUsage.Specular)!; + } + + get specularColorFactor(): RGB { + this[$ensureMaterialIsLoaded](); + return (this[$backingThreeMaterial].specularColor.toArray() as RGB); + } + + get specularColorTexture(): TextureInfo { + this[$ensureMaterialIsLoaded](); + return this[$pbrTextures].get(TextureUsage.SheenColor)!; + } + + setSpecularFactor(specularFactor: number) { + this[$ensureMaterialIsLoaded](); + for (const material of this[$correlatedObjects] as + Set) { + material.specularIntensity = specularFactor; + } + this[$onUpdate](); + } + + setSpecularColorFactor(rgb: RGB|string) { + this[$ensureMaterialIsLoaded](); + const color = this.colorFromRgb(rgb); + for (const material of this[$correlatedObjects] as + Set) { + material.specularColor.set(color); + } + this[$onUpdate](); + } + + // KHR_materials_iridescence } diff --git a/packages/model-viewer/src/features/scene-graph/texture-info.ts b/packages/model-viewer/src/features/scene-graph/texture-info.ts index ecdf468e5e..761a7c6f8d 100644 --- a/packages/model-viewer/src/features/scene-graph/texture-info.ts +++ b/packages/model-viewer/src/features/scene-graph/texture-info.ts @@ -36,6 +36,12 @@ export enum TextureUsage { Clearcoat, ClearcoatRoughness, ClearcoatNormal, + SheenColor, + SheenRoughness, + Transmission, + Thickness, + Specular, + SpecularColor, } interface TextureTransform { @@ -157,6 +163,24 @@ export class TextureInfo implements TextureInfoInterface { case TextureUsage.ClearcoatNormal: material.clearcoatNormalMap = threeTexture; break; + case TextureUsage.SheenColor: + material.sheenColorMap = threeTexture; + break; + case TextureUsage.SheenRoughness: + material.sheenRoughnessMap = threeTexture; + break; + case TextureUsage.Transmission: + material.transmissionMap = threeTexture; + break; + case TextureUsage.Thickness: + material.thicknessMap = threeTexture; + break; + case TextureUsage.Specular: + material.specularIntensityMap = threeTexture; + break; + case TextureUsage.SpecularColor: + material.specularColorMap = threeTexture; + break; default: } material.needsUpdate = true;