From fd5aea58e7171ddb2bb3e1bde19061d03f6a0393 Mon Sep 17 00:00:00 2001 From: Diego Teran Date: Thu, 29 Jun 2023 15:41:41 -0700 Subject: [PATCH] Add PBR Next properties API Missing: iridescene, next commit anisotropy, not supported by three.js yet. --- .../src/features/scene-graph/api.ts | 24 ++ .../src/features/scene-graph/material.ts | 260 +++++++++++++++++- .../src/features/scene-graph/texture-info.ts | 24 ++ 3 files changed, 298 insertions(+), 10 deletions(-) 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..f685657cb5 100644 --- a/packages/model-viewer/src/features/scene-graph/material.ts +++ b/packages/model-viewer/src/features/scene-graph/material.ts @@ -50,7 +50,12 @@ const $name = Symbol('name'); const $clearcoatTexture = Symbol('clearcoatTexture'); const $clearcoatRoughnessTexture = Symbol('clearcoatRoughnessTexture'); const $clearcoatNormalTexture = Symbol('clearcoatNormalTexture'); - +const $sheenColorTexture = Symbol('sheenColorTexture'); +const $sheenRoughnessTexture = Symbol('sheenRoughnessTexture'); +const $transmissionTexture = Symbol('transmissionTexture'); +const $thicknessTexture = Symbol('thicknessTexture'); +const $specularTexture = Symbol('specularTexture'); +const $specularColorTexture = Symbol('specularColorTexture'); /** * Material facade implementation for Three.js materials */ @@ -72,6 +77,12 @@ export class Material extends ThreeDOMElement implements MaterialInterface { private[$clearcoatTexture]!: TextureInfo; private[$clearcoatRoughnessTexture]!: TextureInfo; private[$clearcoatNormalTexture]!: TextureInfo; + private[$sheenColorTexture]!: TextureInfo; + private[$sheenRoughnessTexture]!: TextureInfo; + private[$transmissionTexture]!: TextureInfo; + private[$thicknessTexture]!: TextureInfo; + private[$specularTexture]!: TextureInfo; + private[$specularColorTexture]!: TextureInfo; get[$backingThreeMaterial](): MeshPhysicalMaterial { return (this[$correlatedObjects] as Set) @@ -154,6 +165,48 @@ export class Material extends ThreeDOMElement implements MaterialInterface { null, correlatedMaterials, ); + + this[$sheenColorTexture] = new TextureInfo( + onUpdate, + TextureUsage.SheenColor, + null, + correlatedMaterials, + ); + + this[$sheenRoughnessTexture] = new TextureInfo( + onUpdate, + TextureUsage.SheenRoughness, + null, + correlatedMaterials, + ); + + this[$transmissionTexture] = new TextureInfo( + onUpdate, + TextureUsage.Transmission, + null, + correlatedMaterials, + ); + + this[$thicknessTexture] = new TextureInfo( + onUpdate, + TextureUsage.Thickness, + null, + correlatedMaterials, + ); + + this[$specularTexture] = new TextureInfo( + onUpdate, + TextureUsage.Specular, + null, + correlatedMaterials, + ); + + this[$specularColorTexture] = new TextureInfo( + onUpdate, + TextureUsage.SpecularColor, + null, + correlatedMaterials, + ); } async[$getLoadedMaterial](): Promise { @@ -356,11 +409,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; @@ -391,15 +456,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 +483,188 @@ 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[$sheenColorTexture]; + } + + get sheenRoughnessFactor(): number { + this[$ensureMaterialIsLoaded](); + return this[$backingThreeMaterial].sheenRoughness; + } + + get sheenRoughnessTexture(): TextureInfo { + this[$ensureMaterialIsLoaded](); + return this[$sheenRoughnessTexture]; + } + + setSheenColorFactor(rgb: RGB|string) { + this[$ensureMaterialIsLoaded](); + const color = new Color(); + if (rgb instanceof Array) { + color.fromArray(rgb); + } else { + color.set(rgb as ColorRepresentation); + } + 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[$transmissionTexture]; + } + + 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[$thicknessTexture]; + } + + 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 = new Color(); + if (rgb instanceof Array) { + color.fromArray(rgb); + } else { + color.set(rgb as ColorRepresentation); + } + 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[$specularTexture]; + } + + get specularColorFactor(): RGB { + this[$ensureMaterialIsLoaded](); + return (this[$backingThreeMaterial].specularColor.toArray() as RGB); + } + + get specularColorTexture(): TextureInfo { + this[$ensureMaterialIsLoaded](); + return this[$specularColorTexture]; + } + + 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 = new Color(); + if (rgb instanceof Array) { + color.fromArray(rgb); + } else { + color.set(rgb as ColorRepresentation); + } + 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 393ff16cd7..85a51516b3 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;