From a258713b0c07f6c153f173606d2a0b40aebc3e4b Mon Sep 17 00:00:00 2001 From: Michael Bond Date: Thu, 2 Nov 2023 16:51:39 -0700 Subject: [PATCH 1/9] WIP dispersion support --- .../Node/Blocks/PBR/subSurfaceBlock.ts | 17 +++- .../PBR/pbrSubSurfaceConfiguration.ts | 20 ++++ .../ShadersInclude/pbrBlockSubSurface.fx | 49 +++++----- .../ShadersInclude/pbrFragmentDeclaration.fx | 3 + packages/dev/core/src/Shaders/pbr.fragment.fx | 3 + .../pbrMaterialPropertyGridComponent.tsx | 21 +++++ .../actionTabs/tabs/tools/gltfComponent.tsx | 5 + .../inspector/src/components/globalState.ts | 1 + .../Extensions/KHR_animation_pointer.data.ts | 3 + .../Extensions/KHR_materials_dispersion.ts | 84 +++++++++++++++++ .../loaders/src/glTF/2.0/Extensions/index.ts | 1 + .../Extensions/KHR_materials_dispersion.ts | 94 +++++++++++++++++++ .../src/glTF/2.0/Extensions/index.ts | 1 + .../babylon.glTF2Interface.d.ts | 9 ++ 14 files changed, 287 insertions(+), 24 deletions(-) create mode 100644 packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts create mode 100644 packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts diff --git a/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts b/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts index 6daee5662e9..d6c023d11e1 100644 --- a/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts +++ b/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts @@ -37,6 +37,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock { NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("refraction", this, NodeMaterialConnectionPointDirection.Input, RefractionBlock, "RefractionBlock") ); + this.registerInput("dispersion", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment); this.registerOutput( "subsurface", @@ -55,6 +56,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock { state._excludeVariableName("vThicknessParam"); state._excludeVariableName("vTintColor"); state._excludeVariableName("vSubSurfaceIntensity"); + state._excludeVariableName("dispersion"); } /** @@ -100,6 +102,13 @@ export class SubSurfaceBlock extends NodeMaterialBlock { return this._inputs[4]; } + /** + * Gets the dispersion input component + */ + public get dispersion(): NodeMaterialConnectionPoint { + return this._inputs[5]; + } + /** * Gets the sub surface object output component */ @@ -127,6 +136,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock { defines.setValue("SS_TRANSLUCENCYINTENSITY_TEXTURE", false, true); defines.setValue("SS_MASK_FROM_THICKNESS_TEXTURE", false, true); defines.setValue("SS_USE_GLTF_TEXTURES", false, true); + defines.setValue("SS_DISPERSION", false, true); } /** @@ -151,6 +161,8 @@ export class SubSurfaceBlock extends NodeMaterialBlock { const refractionIntensity = refractionBlock?.intensity.isConnected ? refractionBlock.intensity.associatedVariableName : "1."; const refractionView = refractionBlock?.view.isConnected ? refractionBlock.view.associatedVariableName : ""; + const dispersion = ssBlock?.dispersion; + code += refractionBlock?.getCode(state) ?? ""; code += `subSurfaceOutParams subSurfaceOut; @@ -159,7 +171,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock { vec2 vThicknessParam = vec2(0., ${thickness}); vec4 vTintColor = vec4(${tintColor}, ${refractionTintAtDistance}); vec3 vSubSurfaceIntensity = vec3(${refractionIntensity}, ${translucencyIntensity}, 0.); - + float dispersion = ${dispersion}; subSurfaceBlock( vSubSurfaceIntensity, vThicknessParam, @@ -231,6 +243,9 @@ export class SubSurfaceBlock extends NodeMaterialBlock { vRefractionPosition, vRefractionSize, #endif + #ifdef SS_DISPERSION + dispersion, + #endif #endif #ifdef SS_TRANSLUCENCY ${translucencyDiffusionDistance}, diff --git a/packages/dev/core/src/Materials/PBR/pbrSubSurfaceConfiguration.ts b/packages/dev/core/src/Materials/PBR/pbrSubSurfaceConfiguration.ts index 773ae1c4b84..9df90711c33 100644 --- a/packages/dev/core/src/Materials/PBR/pbrSubSurfaceConfiguration.ts +++ b/packages/dev/core/src/Materials/PBR/pbrSubSurfaceConfiguration.ts @@ -33,6 +33,7 @@ export class MaterialSubSurfaceDefines extends MaterialDefines { public SS_TRANSLUCENCY = false; public SS_TRANSLUCENCY_USE_INTENSITY_FROM_TEXTURE = false; public SS_SCATTERING = false; + public SS_DISPERSION = false; public SS_THICKNESSANDMASK_TEXTURE = false; public SS_THICKNESSANDMASK_TEXTUREDIRECTUV = 0; @@ -80,6 +81,14 @@ export class PBRSubSurfaceConfiguration extends MaterialPluginBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public isTranslucencyEnabled = false; + private _isDispersionEnabled = false; + /** + * Defines if dispersion is enabled in the material. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public isDispersionEnabled = false; + private _isScatteringEnabled = false; /** * Defines if the sub surface scattering is enabled in the material. @@ -253,6 +262,12 @@ export class PBRSubSurfaceConfiguration extends MaterialPluginBase { @serialize() public tintColorAtDistance = 1; + /** + * Defines the Abbe number for the volume. + */ + @serialize() + public dispersion = 0; + /** * Defines how far each channel transmit through the media. * It is defined as a color to simplify it selection. @@ -354,6 +369,7 @@ export class PBRSubSurfaceConfiguration extends MaterialPluginBase { public prepareDefinesBeforeAttributes(defines: MaterialSubSurfaceDefines, scene: Scene): void { if (!this._isRefractionEnabled && !this._isTranslucencyEnabled && !this._isScatteringEnabled) { defines.SUBSURFACE = false; + defines.SS_DISPERSION = false; defines.SS_TRANSLUCENCY = false; defines.SS_SCATTERING = false; defines.SS_REFRACTION = false; @@ -385,6 +401,7 @@ export class PBRSubSurfaceConfiguration extends MaterialPluginBase { if (defines._areTexturesDirty) { defines.SUBSURFACE = true; + defines.SS_DISPERSION = this._isDispersionEnabled; defines.SS_TRANSLUCENCY = this._isTranslucencyEnabled; defines.SS_TRANSLUCENCY_USE_INTENSITY_FROM_TEXTURE = false; defines.SS_SCATTERING = this._isScatteringEnabled; @@ -562,6 +579,8 @@ export class PBRSubSurfaceConfiguration extends MaterialPluginBase { uniformBuffer.updateFloat4("vTintColor", this.tintColor.r, this.tintColor.g, this.tintColor.b, Math.max(0.00001, this.tintColorAtDistance)); uniformBuffer.updateFloat3("vSubSurfaceIntensity", this.refractionIntensity, this.translucencyIntensity, 0); + + uniformBuffer.updateFloat("dispersion", this.dispersion); } // Textures @@ -715,6 +734,7 @@ export class PBRSubSurfaceConfiguration extends MaterialPluginBase { { name: "vRefractionPosition", size: 3, type: "vec3" }, { name: "vRefractionSize", size: 3, type: "vec3" }, { name: "scatteringDiffusionProfile", size: 1, type: "float" }, + { name: "dispersion", size: 1, type: "float" }, ], }; } diff --git a/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx b/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx index b4933bc9fb9..f1edd448d3b 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx @@ -112,6 +112,9 @@ struct subSurfaceOutParams in vec3 refractionPosition, in vec3 refractionSize, #endif + #ifdef SS_DISPERSION + in float dispersion, + #endif #endif #ifdef SS_TRANSLUCENCY in vec3 vDiffusionDistance, @@ -192,6 +195,29 @@ struct subSurfaceOutParams #ifdef SS_REFRACTION vec4 environmentRefraction = vec4(0., 0., 0., 0.); + // vRefractionInfos.y is the IOR of the volume. + // vRefractionMicrosurfaceInfos.w is the IOR of the surface. + #ifdef SS_HAS_THICKNESS + float ior = vRefractionInfos.y; + #else + float ior = vRefractionMicrosurfaceInfos.w; + #endif + // Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and + // an IOR of 1.5 results in the default amount of microfacet refraction. + #ifdef SS_LODINREFRACTIONALPHA + float refractionAlphaG = alphaG; + refractionAlphaG = mix(alphaG, 0.0, clamp(ior * 3.0 - 2.0, 0.0, 1.0)); + float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, refractionAlphaG, NdotVUnclamped); + #elif defined(SS_LINEARSPECULARREFRACTION) + float refractionRoughness = alphaG; + refractionRoughness = mix(alphaG, 0.0, clamp(ior * 3.0 - 2.0, 0.0, 1.0)); + float refractionLOD = getLinearLodFromRoughness(vRefractionMicrosurfaceInfos.x, refractionRoughness); + #else + float refractionAlphaG = alphaG; + refractionAlphaG = mix(alphaG, 0.0, clamp(ior * 3.0 - 2.0, 0.0, 1.0)); + float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, refractionAlphaG); + #endif + #ifdef ANISOTROPIC vec3 refractionVector = refract(-viewDirectionW, anisotropicOut.anisotropicNormal, vRefractionInfos.y); #else @@ -220,29 +246,6 @@ struct subSurfaceOutParams refractionCoords.y = 1.0 - refractionCoords.y; #endif - // vRefractionInfos.y is the IOR of the volume. - // vRefractionMicrosurfaceInfos.w is the IOR of the surface. - #ifdef SS_HAS_THICKNESS - float ior = vRefractionInfos.y; - #else - float ior = vRefractionMicrosurfaceInfos.w; - #endif - // Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and - // an IOR of 1.5 results in the default amount of microfacet refraction. - #ifdef SS_LODINREFRACTIONALPHA - float refractionAlphaG = alphaG; - refractionAlphaG = mix(alphaG, 0.0, clamp(ior * 3.0 - 2.0, 0.0, 1.0)); - float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, refractionAlphaG, NdotVUnclamped); - #elif defined(SS_LINEARSPECULARREFRACTION) - float refractionRoughness = alphaG; - refractionRoughness = mix(alphaG, 0.0, clamp(ior * 3.0 - 2.0, 0.0, 1.0)); - float refractionLOD = getLinearLodFromRoughness(vRefractionMicrosurfaceInfos.x, refractionRoughness); - #else - float refractionAlphaG = alphaG; - refractionAlphaG = mix(alphaG, 0.0, clamp(ior * 3.0 - 2.0, 0.0, 1.0)); - float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, refractionAlphaG); - #endif - #ifdef LODBASEDMICROSFURACE // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection refractionLOD = refractionLOD * vRefractionMicrosurfaceInfos.y + vRefractionMicrosurfaceInfos.z; diff --git a/packages/dev/core/src/Shaders/ShadersInclude/pbrFragmentDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/pbrFragmentDeclaration.fx index c62b8ff9864..e5f379b8b52 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/pbrFragmentDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/pbrFragmentDeclaration.fx @@ -164,6 +164,9 @@ uniform mat4 view; #ifdef REALTIME_FILTERING uniform vec2 vRefractionFilteringInfo; #endif + #ifdef SS_DISPERSION + uniform float dispersion; + #endif #endif #ifdef SS_THICKNESSANDMASK_TEXTURE diff --git a/packages/dev/core/src/Shaders/pbr.fragment.fx b/packages/dev/core/src/Shaders/pbr.fragment.fx index 5b8666988f6..c3f5c2457ee 100644 --- a/packages/dev/core/src/Shaders/pbr.fragment.fx +++ b/packages/dev/core/src/Shaders/pbr.fragment.fx @@ -586,6 +586,9 @@ void main(void) { vRefractionPosition, vRefractionSize, #endif + #ifdef SS_DISPERSION + dispersion, + #endif #endif #ifdef SS_TRANSLUCENCY vDiffusionDistance, diff --git a/packages/dev/inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx b/packages/dev/inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx index 235dfd23be6..36cd81acd63 100644 --- a/packages/dev/inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx +++ b/packages/dev/inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx @@ -882,6 +882,27 @@ export class PBRMaterialPropertyGridComponent extends React.Component )} + this.forceUpdate()} + onPropertyChangedObservable={this.props.onPropertyChangedObservable} + /> + {material.subSurface.isDispersionEnabled && ( +
+ +
+ )} { isSelected={() => extensionStates["KHR_materials_volume"].enabled} onSelect={(value) => (extensionStates["KHR_materials_volume"].enabled = value)} /> + extensionStates["KHR_materials_dispersion"].enabled} + onSelect={(value) => (extensionStates["KHR_materials_dispersion"].enabled = value)} + /> extensionStates["KHR_mesh_quantization"].enabled} diff --git a/packages/dev/inspector/src/components/globalState.ts b/packages/dev/inspector/src/components/globalState.ts index 2853bdff98f..b31c1bf17d5 100644 --- a/packages/dev/inspector/src/components/globalState.ts +++ b/packages/dev/inspector/src/components/globalState.ts @@ -54,6 +54,7 @@ export class GlobalState { KHR_materials_transmission: { enabled: true }, KHR_materials_translucency: { enabled: true }, KHR_materials_volume: { enabled: true }, + KHR_materials_dispersion: { enabled: true }, KHR_lights_punctual: { enabled: true }, KHR_texture_basisu: { enabled: true }, KHR_texture_transform: { enabled: true }, diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.data.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.data.ts index b4e84ceebf7..fc5df6c87a4 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.data.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.data.ts @@ -161,6 +161,9 @@ const materialsTree = { attenuationDistance: [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, "subSurface.tintColorAtDistance", getFloat, () => 1)], thicknessFactor: [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, "subSurface.maximumThickness", getFloat, () => 1)], }, + KHR_materials_dispersion: { + dispersion: [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, "subSurface.dispersion", getFloat, () => 1)], + }, KHR_materials_iridescence: { iridescenceFactor: [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, "iridescence.intensity", getFloat, () => 1)], iridescenceIor: [new MaterialAnimationPropertyInfo(Animation.ANIMATIONTYPE_FLOAT, "iridescence.indexOfRefraction", getFloat, () => 1)], diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts new file mode 100644 index 00000000000..7bef35160e3 --- /dev/null +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts @@ -0,0 +1,84 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import type { Nullable } from "core/types"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { Material } from "core/Materials/material"; +import type { IMaterial } from "../glTFLoaderInterfaces"; +import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; +import { GLTFLoader } from "../glTFLoader"; +import type { IKHRMaterialsDispersion } from "babylonjs-gltf2interface"; + +const NAME = "KHR_materials_dispersion"; + +/** + * [Specification](TODO) + * @since 5.0.0 + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export class KHR_materials_dispersion implements IGLTFLoaderExtension { + /** + * The name of this extension. + */ + public readonly name = NAME; + + /** + * Defines whether this extension is enabled. + */ + public enabled: boolean; + + /** + * Defines a number that determines the order the extensions are applied. + */ + public order = 174; + + private _loader: GLTFLoader; + + /** + * @internal + */ + constructor(loader: GLTFLoader) { + this._loader = loader; + this.enabled = this._loader.isExtensionUsed(NAME); + if (this.enabled) { + // We need to disable instance usage because the attenuation factor depends on the node scale of each individual mesh + this._loader._disableInstancedMesh++; + } + } + + /** @internal */ + public dispose() { + if (this.enabled) { + this._loader._disableInstancedMesh--; + } + (this._loader as any) = null; + } + + /** + * @internal + */ + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + return GLTFLoader.LoadExtensionAsync(context, material, this.name, (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialBasePropertiesAsync(context, material, babylonMaterial)); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); + promises.push(this._loadDispersionPropertiesAsync(extensionContext, material, babylonMaterial, extension)); + return Promise.all(promises).then(() => {}); + }); + } + + private _loadDispersionPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDispersion): Promise { + if (!(babylonMaterial instanceof PBRMaterial)) { + throw new Error(`${context}: Material type not supported`); + } + + // If transparency isn't enabled already, this extension shouldn't do anything. + // i.e. it requires either the KHR_materials_transmission or KHR_materials_translucency extensions. + if ((!babylonMaterial.subSurface.isRefractionEnabled) || !extension.dispersion) { + return Promise.resolve(); + } + + babylonMaterial.subSurface.dispersion = extension.dispersion; + return Promise.resolve(); + } +} + +GLTFLoader.RegisterExtension(NAME, (loader) => new KHR_materials_dispersion(loader)); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts index 4c6068b79a6..3cc4b9fff16 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts @@ -17,6 +17,7 @@ export * from "./KHR_materials_variants"; export * from "./KHR_materials_transmission"; export * from "./KHR_materials_translucency"; export * from "./KHR_materials_volume"; +export * from "./KHR_materials_dispersion"; export * from "./KHR_mesh_quantization"; export * from "./KHR_texture_basisu"; export * from "./KHR_texture_transform"; diff --git a/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts b/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts new file mode 100644 index 00000000000..b4e190cc591 --- /dev/null +++ b/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts @@ -0,0 +1,94 @@ +import type { IMaterial, IKHRMaterialsDispersion } from "babylonjs-gltf2interface"; +import type { IGLTFExporterExtensionV2 } from "../glTFExporterExtension"; +import { _Exporter } from "../glTFExporter"; +import type { Material } from "core/Materials/material"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; + +const NAME = "KHR_materials_dispersion"; + +/** + * [Specification](TODO) + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export class KHR_materials_dispersion implements IGLTFExporterExtensionV2 { + /** Name of this extension */ + public readonly name = NAME; + + /** Defines whether this extension is enabled */ + public enabled = true; + + /** Defines whether this extension is required */ + public required = false; + + private _wasUsed = false; + + /** Constructor */ + constructor() { + } + + /** */ + public dispose() {} + + /** @internal */ + public get wasUsed() { + return this._wasUsed; + } + + // public postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[] { + // const additionalTextures: BaseTexture[] = []; + + // if (babylonMaterial instanceof PBRMaterial) { + // if (this._isExtensionEnabled(babylonMaterial)) { + // if (babylonMaterial.subSurface.thicknessTexture) { + // additionalTextures.push(babylonMaterial.subSurface.thicknessTexture); + // } + // return additionalTextures; + // } + // } + + // return additionalTextures; + // } + + private _isExtensionEnabled(mat: PBRMaterial): boolean { + // This extension must not be used on a material that also uses KHR_materials_unlit + if (mat.unlit) { + return false; + } + const subs = mat.subSurface; + // this extension requires refraction to be enabled. + if (!subs.isRefractionEnabled) { + return false; + } + return true; + } + + // private _hasTexturesExtension(mat: PBRMaterial): boolean { + // return mat.subSurface.thicknessTexture != null; + // } + + public postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise { + return new Promise((resolve) => { + if (babylonMaterial instanceof PBRMaterial && this._isExtensionEnabled(babylonMaterial)) { + this._wasUsed = true; + + // const subs = babylonMaterial.subSurface; + const dispersion = 0.0;//subs.dispersion; + + const dispersionInfo: IKHRMaterialsDispersion = { + dispersion: dispersion, + // thicknessTexture: thicknessTexture, + // attenuationDistance: attenuationDistance, + // attenuationColor: attenuationColor, + // hasTextures: () => { + // return this._hasTexturesExtension(babylonMaterial); + // }, + }; + node.extensions = node.extensions || {}; + node.extensions[NAME] = dispersionInfo; + } + resolve(node); + }); + } +} + +_Exporter.RegisterExtension(NAME, () => new KHR_materials_dispersion()); diff --git a/packages/dev/serializers/src/glTF/2.0/Extensions/index.ts b/packages/dev/serializers/src/glTF/2.0/Extensions/index.ts index 292e1f5e6cc..b992ff21e63 100644 --- a/packages/dev/serializers/src/glTF/2.0/Extensions/index.ts +++ b/packages/dev/serializers/src/glTF/2.0/Extensions/index.ts @@ -8,6 +8,7 @@ export * from "./KHR_materials_unlit"; export * from "./KHR_materials_ior"; export * from "./KHR_materials_specular"; export * from "./KHR_materials_volume"; +export * from "./KHR_materials_dispersion"; export * from "./KHR_materials_transmission"; export * from "./EXT_mesh_gpu_instancing"; export * from "./KHR_materials_emissive_strength"; diff --git a/packages/public/glTF2Interface/babylon.glTF2Interface.d.ts b/packages/public/glTF2Interface/babylon.glTF2Interface.d.ts index a6558fe036d..cc3747cf5b4 100644 --- a/packages/public/glTF2Interface/babylon.glTF2Interface.d.ts +++ b/packages/public/glTF2Interface/babylon.glTF2Interface.d.ts @@ -1088,6 +1088,15 @@ declare module BABYLON.GLTF2 { attenuationColor?: number[]; } + /** + * Interfaces from the KHR_materials_dispersion extension + */ + + /** @internal */ + interface IKHRMaterialsDispersion extends IMaterialExtension { + dispersion?: number; + } + /** * Interfaces from the KHR_materials_specular extension */ From 716efe041c8fd1dd2d20b4eab210e716fe8e155c Mon Sep 17 00:00:00 2001 From: Michael Bond Date: Tue, 7 Nov 2023 16:32:20 -0800 Subject: [PATCH 2/9] Finish initial test of dispersion in the shader --- .../ShadersInclude/pbrBlockSubSurface.fx | 249 ++++++++++++------ .../Extensions/KHR_materials_dispersion.ts | 2 +- .../Extensions/KHR_materials_dispersion.ts | 31 +-- 3 files changed, 178 insertions(+), 104 deletions(-) diff --git a/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx b/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx index f1edd448d3b..a89a1915285 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx @@ -32,6 +32,127 @@ struct subSurfaceOutParams #ifdef SUBSURFACE #define pbr_inline #define inline + #ifdef SS_REFRACTION + vec4 sampleEnvironmentRefraction( + in float ior + , in float thickness + , in float refractionLOD + , in vec3 normalW + , in vec3 vPositionW + , in vec3 viewDirectionW + , in mat4 view + , in vec4 vRefractionInfos + , in mat4 refractionMatrix + , in vec4 vRefractionMicrosurfaceInfos + , in float alphaG + #ifdef SS_REFRACTIONMAP_3D + , in samplerCube refractionSampler + #ifndef LODBASEDMICROSFURACE + , in samplerCube refractionSamplerLow + , in samplerCube refractionSamplerHigh + #endif + #else + , in sampler2D refractionSampler + #ifndef LODBASEDMICROSFURACE + , in sampler2D refractionSamplerLow + , in sampler2D refractionSamplerHigh + #endif + #endif + #ifdef ANISOTROPIC + , in anisotropicOutParams anisotropicOut + #endif + #ifdef REALTIME_FILTERING + , in vec2 vRefractionFilteringInfo + #endif + #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC + , in vec3 refractionPosition + , in vec3 refractionSize + #endif + ) { + vec4 environmentRefraction = vec4(0., 0., 0., 0.); + #ifdef ANISOTROPIC + vec3 refractionVector = refract(-viewDirectionW, anisotropicOut.anisotropicNormal, ior); + #else + vec3 refractionVector = refract(-viewDirectionW, normalW, ior); + #endif + + #ifdef SS_REFRACTIONMAP_OPPOSITEZ + refractionVector.z *= -1.0; + #endif + + // _____________________________ 2D vs 3D Maps ________________________________ + #ifdef SS_REFRACTIONMAP_3D + #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC + refractionVector = parallaxCorrectNormal(vPositionW, refractionVector, refractionSize, refractionPosition); + #endif + refractionVector.y = refractionVector.y * vRefractionInfos.w; + vec3 refractionCoords = refractionVector; + refractionCoords = vec3(refractionMatrix * vec4(refractionCoords, 0)); + #else + #ifdef SS_USE_THICKNESS_AS_DEPTH + vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * thickness, 1.0))); + #else + vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * vRefractionInfos.z, 1.0))); + #endif + vec2 refractionCoords = vRefractionUVW.xy / vRefractionUVW.z; + refractionCoords.y = 1.0 - refractionCoords.y; + #endif + + #ifdef LODBASEDMICROSFURACE + // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection + refractionLOD = refractionLOD * vRefractionMicrosurfaceInfos.y + vRefractionMicrosurfaceInfos.z; + + #ifdef SS_LODINREFRACTIONALPHA + // Automatic LOD adjustment to ensure that the smoothness-based environment LOD selection + // is constrained to appropriate LOD levels in order to prevent aliasing. + // The environment map is first sampled without custom LOD selection to determine + // the hardware-selected LOD, and this is then used to constrain the final LOD selection + // so that excessive surface smoothness does not cause aliasing (e.g. on curved geometry + // where the normal is varying rapidly). + + // Note: Shader Model 4.1 or higher can provide this directly via CalculateLevelOfDetail(), and + // manual calculation via derivatives is also possible, but for simplicity we use the + // hardware LOD calculation with the alpha channel containing the LOD for each mipmap. + float automaticRefractionLOD = UNPACK_LOD(sampleRefraction(refractionSampler, refractionCoords).a); + float requestedRefractionLOD = max(automaticRefractionLOD, refractionLOD); + #else + float requestedRefractionLOD = refractionLOD; + #endif + + #if defined(REALTIME_FILTERING) && defined(SS_REFRACTIONMAP_3D) + environmentRefraction = vec4(radiance(alphaG, refractionSampler, refractionCoords, vRefractionFilteringInfo), 1.0); + #else + environmentRefraction = sampleRefractionLod(refractionSampler, refractionCoords, requestedRefractionLOD); + #endif + #else + float lodRefractionNormalized = saturate(refractionLOD / log2(vRefractionMicrosurfaceInfos.x)); + float lodRefractionNormalizedDoubled = lodRefractionNormalized * 2.0; + + vec4 environmentRefractionMid = sampleRefraction(refractionSampler, refractionCoords); + if (lodRefractionNormalizedDoubled < 1.0){ + environmentRefraction = mix( + sampleRefraction(refractionSamplerHigh, refractionCoords), + environmentRefractionMid, + lodRefractionNormalizedDoubled + ); + } else { + environmentRefraction = mix( + environmentRefractionMid, + sampleRefraction(refractionSamplerLow, refractionCoords), + lodRefractionNormalizedDoubled - 1.0 + ); + } + #endif + #ifdef SS_RGBDREFRACTION + environmentRefraction.rgb = fromRGBD(environmentRefraction); + #endif + + #ifdef SS_GAMMAREFRACTION + environmentRefraction.rgb = toLinearSpace(environmentRefraction.rgb); + #endif + return environmentRefraction; + } + #endif void subSurfaceBlock( in vec3 vSubSurfaceIntensity, in vec2 vThicknessParam, @@ -218,86 +339,64 @@ struct subSurfaceOutParams float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, refractionAlphaG); #endif - #ifdef ANISOTROPIC - vec3 refractionVector = refract(-viewDirectionW, anisotropicOut.anisotropicNormal, vRefractionInfos.y); - #else - vec3 refractionVector = refract(-viewDirectionW, normalW, vRefractionInfos.y); - #endif - - #ifdef SS_REFRACTIONMAP_OPPOSITEZ - refractionVector.z *= -1.0; - #endif - - // _____________________________ 2D vs 3D Maps ________________________________ - #ifdef SS_REFRACTIONMAP_3D - #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC - refractionVector = parallaxCorrectNormal(vPositionW, refractionVector, refractionSize, refractionPosition); - #endif - refractionVector.y = refractionVector.y * vRefractionInfos.w; - vec3 refractionCoords = refractionVector; - refractionCoords = vec3(refractionMatrix * vec4(refractionCoords, 0)); + #ifdef SS_DISPERSION + float realIOR = 1.0 / ior; + float iorDispersionSpread = 0.02 * dispersion * (realIOR - 1.0); + vec3 iors = vec3(ior + iorDispersionSpread, ior, ior - iorDispersionSpread); + for (int i = 0; i < 3; i++) { + vec4 envSample = sampleEnvironmentRefraction(iors[i], thickness, refractionLOD, normalW, vPositionW, viewDirectionW, view, vRefractionInfos, refractionMatrix, vRefractionMicrosurfaceInfos, alphaG + #ifdef SS_REFRACTIONMAP_3D + , refractionSampler + #ifndef LODBASEDMICROSFURACE + , refractionSamplerLow + , refractionSamplerHigh + #endif + #else + , refractionSampler + #ifndef LODBASEDMICROSFURACE + , refractionSamplerLow + , refractionSamplerHigh + #endif + #endif + #ifdef ANISOTROPIC + , anisotropicOut + #endif + #ifdef REALTIME_FILTERING + , vRefractionFilteringInfo + #endif + #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC + , refractionPosition + , refractionSize + #endif + ); + environmentRefraction[i] = envSample[i]; + } #else - #ifdef SS_USE_THICKNESS_AS_DEPTH - vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * thickness, 1.0))); + environmentRefraction = sampleEnvironmentRefraction(ior, thickness, refractionLOD, normalW, vPositionW, viewDirectionW, view, vRefractionInfos, refractionMatrix, vRefractionMicrosurfaceInfos, alphaG + #ifdef SS_REFRACTIONMAP_3D + , refractionSampler + #ifndef LODBASEDMICROSFURACE + , refractionSamplerLow + , refractionSamplerHigh + #endif #else - vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * vRefractionInfos.z, 1.0))); + , refractionSampler + #ifndef LODBASEDMICROSFURACE + , refractionSamplerLow + , refractionSamplerHigh + #endif #endif - vec2 refractionCoords = vRefractionUVW.xy / vRefractionUVW.z; - refractionCoords.y = 1.0 - refractionCoords.y; - #endif - - #ifdef LODBASEDMICROSFURACE - // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection - refractionLOD = refractionLOD * vRefractionMicrosurfaceInfos.y + vRefractionMicrosurfaceInfos.z; - - #ifdef SS_LODINREFRACTIONALPHA - // Automatic LOD adjustment to ensure that the smoothness-based environment LOD selection - // is constrained to appropriate LOD levels in order to prevent aliasing. - // The environment map is first sampled without custom LOD selection to determine - // the hardware-selected LOD, and this is then used to constrain the final LOD selection - // so that excessive surface smoothness does not cause aliasing (e.g. on curved geometry - // where the normal is varying rapidly). - - // Note: Shader Model 4.1 or higher can provide this directly via CalculateLevelOfDetail(), and - // manual calculation via derivatives is also possible, but for simplicity we use the - // hardware LOD calculation with the alpha channel containing the LOD for each mipmap. - float automaticRefractionLOD = UNPACK_LOD(sampleRefraction(refractionSampler, refractionCoords).a); - float requestedRefractionLOD = max(automaticRefractionLOD, refractionLOD); - #else - float requestedRefractionLOD = refractionLOD; + #ifdef ANISOTROPIC + , anisotropicOut #endif - - #if defined(REALTIME_FILTERING) && defined(SS_REFRACTIONMAP_3D) - environmentRefraction = vec4(radiance(alphaG, refractionSampler, refractionCoords, vRefractionFilteringInfo), 1.0); - #else - environmentRefraction = sampleRefractionLod(refractionSampler, refractionCoords, requestedRefractionLOD); + #ifdef REALTIME_FILTERING + , vRefractionFilteringInfo #endif - #else - float lodRefractionNormalized = saturate(refractionLOD / log2(vRefractionMicrosurfaceInfos.x)); - float lodRefractionNormalizedDoubled = lodRefractionNormalized * 2.0; - - vec4 environmentRefractionMid = sampleRefraction(refractionSampler, refractionCoords); - if (lodRefractionNormalizedDoubled < 1.0){ - environmentRefraction = mix( - sampleRefraction(refractionSamplerHigh, refractionCoords), - environmentRefractionMid, - lodRefractionNormalizedDoubled - ); - } else { - environmentRefraction = mix( - environmentRefractionMid, - sampleRefraction(refractionSamplerLow, refractionCoords), - lodRefractionNormalizedDoubled - 1.0 - ); - } - #endif - - #ifdef SS_RGBDREFRACTION - environmentRefraction.rgb = fromRGBD(environmentRefraction); - #endif - - #ifdef SS_GAMMAREFRACTION - environmentRefraction.rgb = toLinearSpace(environmentRefraction.rgb); + #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC + , refractionPosition + , refractionSize + #endif + ); #endif // _____________________________ Levels _____________________________________ diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts index 7bef35160e3..3c24098f799 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts @@ -75,7 +75,7 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { if ((!babylonMaterial.subSurface.isRefractionEnabled) || !extension.dispersion) { return Promise.resolve(); } - + babylonMaterial.subSurface.isDispersionEnabled = true; babylonMaterial.subSurface.dispersion = extension.dispersion; return Promise.resolve(); } diff --git a/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts b/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts index b4e190cc591..388eac508ac 100644 --- a/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts +++ b/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts @@ -34,21 +34,6 @@ export class KHR_materials_dispersion implements IGLTFExporterExtensionV2 { return this._wasUsed; } - // public postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[] { - // const additionalTextures: BaseTexture[] = []; - - // if (babylonMaterial instanceof PBRMaterial) { - // if (this._isExtensionEnabled(babylonMaterial)) { - // if (babylonMaterial.subSurface.thicknessTexture) { - // additionalTextures.push(babylonMaterial.subSurface.thicknessTexture); - // } - // return additionalTextures; - // } - // } - - // return additionalTextures; - // } - private _isExtensionEnabled(mat: PBRMaterial): boolean { // This extension must not be used on a material that also uses KHR_materials_unlit if (mat.unlit) { @@ -56,32 +41,22 @@ export class KHR_materials_dispersion implements IGLTFExporterExtensionV2 { } const subs = mat.subSurface; // this extension requires refraction to be enabled. - if (!subs.isRefractionEnabled) { + if (!subs.isRefractionEnabled && !subs.isDispersionEnabled) { return false; } return true; } - // private _hasTexturesExtension(mat: PBRMaterial): boolean { - // return mat.subSurface.thicknessTexture != null; - // } - public postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise { return new Promise((resolve) => { if (babylonMaterial instanceof PBRMaterial && this._isExtensionEnabled(babylonMaterial)) { this._wasUsed = true; - // const subs = babylonMaterial.subSurface; - const dispersion = 0.0;//subs.dispersion; + const subs = babylonMaterial.subSurface; + const dispersion = subs.dispersion; const dispersionInfo: IKHRMaterialsDispersion = { dispersion: dispersion, - // thicknessTexture: thicknessTexture, - // attenuationDistance: attenuationDistance, - // attenuationColor: attenuationColor, - // hasTextures: () => { - // return this._hasTexturesExtension(babylonMaterial); - // }, }; node.extensions = node.extensions || {}; node.extensions[NAME] = dispersionInfo; From e94c5b7747509c047b06e2cf53eb85cf6a2c0ee6 Mon Sep 17 00:00:00 2001 From: Michael Bond Date: Wed, 8 Nov 2023 09:12:29 -0800 Subject: [PATCH 3/9] Make dispersion input optional --- .../core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts | 2 +- .../src/glTF/2.0/Extensions/KHR_materials_dispersion.ts | 2 +- .../src/glTF/2.0/Extensions/KHR_materials_dispersion.ts | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts b/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts index d6c023d11e1..f3209d0fa6c 100644 --- a/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts +++ b/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts @@ -37,7 +37,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock { NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("refraction", this, NodeMaterialConnectionPointDirection.Input, RefractionBlock, "RefractionBlock") ); - this.registerInput("dispersion", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment); + this.registerInput("dispersion", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment); this.registerOutput( "subsurface", diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts index 3c24098f799..87c5bc09680 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts @@ -72,7 +72,7 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { // If transparency isn't enabled already, this extension shouldn't do anything. // i.e. it requires either the KHR_materials_transmission or KHR_materials_translucency extensions. - if ((!babylonMaterial.subSurface.isRefractionEnabled) || !extension.dispersion) { + if (!babylonMaterial.subSurface.isRefractionEnabled || !extension.dispersion) { return Promise.resolve(); } babylonMaterial.subSurface.isDispersionEnabled = true; diff --git a/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts b/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts index 388eac508ac..483235400f9 100644 --- a/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts +++ b/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts @@ -23,8 +23,7 @@ export class KHR_materials_dispersion implements IGLTFExporterExtensionV2 { private _wasUsed = false; /** Constructor */ - constructor() { - } + constructor() {} /** */ public dispose() {} @@ -54,7 +53,7 @@ export class KHR_materials_dispersion implements IGLTFExporterExtensionV2 { const subs = babylonMaterial.subSurface; const dispersion = subs.dispersion; - + const dispersionInfo: IKHRMaterialsDispersion = { dispersion: dispersion, }; From 077d4ffede3cf603db403a19b2f80677de54f469 Mon Sep 17 00:00:00 2001 From: MiiBond Date: Thu, 9 Nov 2023 11:21:05 -0800 Subject: [PATCH 4/9] Update packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts Co-authored-by: Gary Hsu --- .../src/glTF/2.0/Extensions/KHR_materials_dispersion.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts index 87c5bc09680..6f453bcfce6 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts @@ -10,8 +10,8 @@ import type { IKHRMaterialsDispersion } from "babylonjs-gltf2interface"; const NAME = "KHR_materials_dispersion"; /** - * [Specification](TODO) - * @since 5.0.0 + * [Specification](https://github.com/KhronosGroup/glTF/blob/87bd64a7f5e23c84b6aef2e6082069583ed0ddb4/extensions/2.0/Khronos/KHR_materials_dispersion/README.md) + * @experimental */ // eslint-disable-next-line @typescript-eslint/naming-convention export class KHR_materials_dispersion implements IGLTFLoaderExtension { From adcbbf9b94c2dc555c03a8e4beefd56086110208 Mon Sep 17 00:00:00 2001 From: MiiBond Date: Thu, 9 Nov 2023 11:21:19 -0800 Subject: [PATCH 5/9] Update packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts Co-authored-by: Gary Hsu --- .../src/glTF/2.0/Extensions/KHR_materials_dispersion.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts b/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts index 483235400f9..16601bc3821 100644 --- a/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts +++ b/packages/dev/serializers/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts @@ -7,7 +7,8 @@ import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; const NAME = "KHR_materials_dispersion"; /** - * [Specification](TODO) + * [Specification](https://github.com/KhronosGroup/glTF/blob/87bd64a7f5e23c84b6aef2e6082069583ed0ddb4/extensions/2.0/Khronos/KHR_materials_dispersion/README.md) + * @experimental */ // eslint-disable-next-line @typescript-eslint/naming-convention export class KHR_materials_dispersion implements IGLTFExporterExtensionV2 { From e1b764e6b3c88097a4aba2fddede83f0bdb3b6d3 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Thu, 9 Nov 2023 14:40:10 -0800 Subject: [PATCH 6/9] Remove unneeded instance checks from KHR_materials_dispersion --- .../src/glTF/2.0/Extensions/KHR_materials_dispersion.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts index 6f453bcfce6..e36607a6088 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_dispersion.ts @@ -38,17 +38,10 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { constructor(loader: GLTFLoader) { this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); - if (this.enabled) { - // We need to disable instance usage because the attenuation factor depends on the node scale of each individual mesh - this._loader._disableInstancedMesh++; - } } /** @internal */ public dispose() { - if (this.enabled) { - this._loader._disableInstancedMesh--; - } (this._loader as any) = null; } From 82b6ffc53823ee2293576309957592966b21512a Mon Sep 17 00:00:00 2001 From: Michael Bond Date: Mon, 13 Nov 2023 10:04:53 -0800 Subject: [PATCH 7/9] Check for undefined dispersion prop --- .../Node/Blocks/PBR/subSurfaceBlock.ts | 2 +- .../ShadersInclude/pbrBlockSubSurface.fx | 38 +++++-------------- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts b/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts index f3209d0fa6c..ae5d2f942d5 100644 --- a/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts +++ b/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts @@ -161,7 +161,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock { const refractionIntensity = refractionBlock?.intensity.isConnected ? refractionBlock.intensity.associatedVariableName : "1."; const refractionView = refractionBlock?.view.isConnected ? refractionBlock.view.associatedVariableName : ""; - const dispersion = ssBlock?.dispersion; + const dispersion = ssBlock?.dispersion.isConnected ? ssBlock?.dispersion.associatedVariableName : "0.0"; code += refractionBlock?.getCode(state) ?? ""; diff --git a/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx b/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx index a89a1915285..bd1183faf0a 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx @@ -340,11 +340,13 @@ struct subSurfaceOutParams #endif #ifdef SS_DISPERSION - float realIOR = 1.0 / ior; - float iorDispersionSpread = 0.02 * dispersion * (realIOR - 1.0); - vec3 iors = vec3(ior + iorDispersionSpread, ior, ior - iorDispersionSpread); + float realIOR = 1.0 / ior; + float iorDispersionSpread = 0.025 * dispersion * (realIOR - 1.0); + vec3 iors = vec3(ior - iorDispersionSpread, ior, ior + iorDispersionSpread); for (int i = 0; i < 3; i++) { - vec4 envSample = sampleEnvironmentRefraction(iors[i], thickness, refractionLOD, normalW, vPositionW, viewDirectionW, view, vRefractionInfos, refractionMatrix, vRefractionMicrosurfaceInfos, alphaG + ior = iors[i]; + #endif + vec4 envSample = sampleEnvironmentRefraction(ior, thickness, refractionLOD, normalW, vPositionW, viewDirectionW, view, vRefractionInfos, refractionMatrix, vRefractionMicrosurfaceInfos, alphaG #ifdef SS_REFRACTIONMAP_3D , refractionSampler #ifndef LODBASEDMICROSFURACE @@ -369,34 +371,12 @@ struct subSurfaceOutParams , refractionSize #endif ); + + #ifdef SS_DISPERSION environmentRefraction[i] = envSample[i]; } #else - environmentRefraction = sampleEnvironmentRefraction(ior, thickness, refractionLOD, normalW, vPositionW, viewDirectionW, view, vRefractionInfos, refractionMatrix, vRefractionMicrosurfaceInfos, alphaG - #ifdef SS_REFRACTIONMAP_3D - , refractionSampler - #ifndef LODBASEDMICROSFURACE - , refractionSamplerLow - , refractionSamplerHigh - #endif - #else - , refractionSampler - #ifndef LODBASEDMICROSFURACE - , refractionSamplerLow - , refractionSamplerHigh - #endif - #endif - #ifdef ANISOTROPIC - , anisotropicOut - #endif - #ifdef REALTIME_FILTERING - , vRefractionFilteringInfo - #endif - #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC - , refractionPosition - , refractionSize - #endif - ); + environmentRefraction = envSample; #endif // _____________________________ Levels _____________________________________ From 1589230677527a1f441d0930d84b4cecaa31b080 Mon Sep 17 00:00:00 2001 From: Michael Bond Date: Mon, 4 Dec 2023 09:26:12 -0800 Subject: [PATCH 8/9] Correction for dispersion ior computation --- .../core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx b/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx index bd1183faf0a..221f89a781e 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockSubSurface.fx @@ -341,8 +341,9 @@ struct subSurfaceOutParams #ifdef SS_DISPERSION float realIOR = 1.0 / ior; - float iorDispersionSpread = 0.025 * dispersion * (realIOR - 1.0); - vec3 iors = vec3(ior - iorDispersionSpread, ior, ior + iorDispersionSpread); + // The 0.04 value is completely empirical + float iorDispersionSpread = 0.04 * dispersion * (realIOR - 1.0); + vec3 iors = vec3(1.0/(realIOR - iorDispersionSpread), ior, 1.0/(realIOR + iorDispersionSpread)); for (int i = 0; i < 3; i++) { ior = iors[i]; #endif From 89b1e384ee175a79cd0a7c5944a555f2b35312fa Mon Sep 17 00:00:00 2001 From: Michael Bond Date: Tue, 5 Dec 2023 21:58:49 -0800 Subject: [PATCH 9/9] Minor fix for dispersion define --- .../dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts b/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts index f3209d0fa6c..f6cc4073bd2 100644 --- a/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts +++ b/packages/dev/core/src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts @@ -136,7 +136,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock { defines.setValue("SS_TRANSLUCENCYINTENSITY_TEXTURE", false, true); defines.setValue("SS_MASK_FROM_THICKNESS_TEXTURE", false, true); defines.setValue("SS_USE_GLTF_TEXTURES", false, true); - defines.setValue("SS_DISPERSION", false, true); + defines.setValue("SS_DISPERSION", this.dispersion.isConnected, true); } /**