From 97a5c69c83c3b6f0269d6f1bee3fe29090503501 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Thu, 19 Jun 2025 13:20:41 -0700 Subject: [PATCH 01/23] Added PBR2 material and option to load using glTF --- packages/dev/core/src/Materials/PBR/index.ts | 5 + .../core/src/Materials/PBR/pbrMaterial2.ts | 2138 +++++++++++++++++ .../dev/core/src/Shaders/pbr2.fragment.fx | 692 ++++++ packages/dev/core/src/Shaders/pbr2.vertex.fx | 312 +++ .../dev/core/src/ShadersWGSL/pbr2.fragment.fx | 688 ++++++ .../dev/core/src/ShadersWGSL/pbr2.vertex.fx | 295 +++ .../EXT_materials_diffuse_roughness.ts | 3 +- .../Extensions/KHR_materials_anisotropy.ts | 3 +- .../2.0/Extensions/KHR_materials_clearcoat.ts | 3 +- .../KHR_materials_diffuse_transmission.ts | 3 +- .../Extensions/KHR_materials_dispersion.ts | 3 +- .../KHR_materials_emissive_strength.ts | 3 +- .../glTF/2.0/Extensions/KHR_materials_ior.ts | 3 +- .../Extensions/KHR_materials_iridescence.ts | 3 +- .../KHR_materials_pbrSpecularGlossiness.ts | 3 +- .../2.0/Extensions/KHR_materials_sheen.ts | 3 +- .../2.0/Extensions/KHR_materials_specular.ts | 3 +- .../Extensions/KHR_materials_transmission.ts | 3 +- .../2.0/Extensions/KHR_materials_unlit.ts | 3 +- .../2.0/Extensions/KHR_materials_volume.ts | 3 +- .../glTF/2.0/Extensions/MSFT_minecraftMesh.ts | 3 +- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 3 +- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 14 +- .../dev/loaders/src/glTF/glTFFileLoader.ts | 6 + 24 files changed, 4178 insertions(+), 20 deletions(-) create mode 100644 packages/dev/core/src/Materials/PBR/pbrMaterial2.ts create mode 100644 packages/dev/core/src/Shaders/pbr2.fragment.fx create mode 100644 packages/dev/core/src/Shaders/pbr2.vertex.fx create mode 100644 packages/dev/core/src/ShadersWGSL/pbr2.fragment.fx create mode 100644 packages/dev/core/src/ShadersWGSL/pbr2.vertex.fx diff --git a/packages/dev/core/src/Materials/PBR/index.ts b/packages/dev/core/src/Materials/PBR/index.ts index f97e5346890..a04f9cd3f91 100644 --- a/packages/dev/core/src/Materials/PBR/index.ts +++ b/packages/dev/core/src/Materials/PBR/index.ts @@ -5,6 +5,7 @@ export * from "./pbrBRDFConfiguration"; export * from "./pbrClearCoatConfiguration"; export * from "./pbrIridescenceConfiguration"; export * from "./pbrMaterial"; +export * from "./pbrMaterial2"; export * from "./pbrMetallicRoughnessMaterial"; export * from "./pbrSpecularGlossinessMaterial"; export * from "./pbrSheenConfiguration"; @@ -15,3 +16,7 @@ export * from "../../ShadersWGSL/pbr.vertex"; export * from "../../ShadersWGSL/pbr.fragment"; export * from "../../Shaders/pbr.vertex"; export * from "../../Shaders/pbr.fragment"; +export * from "../../ShadersWGSL/pbr2.vertex"; +export * from "../../ShadersWGSL/pbr2.fragment"; +export * from "../../Shaders/pbr2.vertex"; +export * from "../../Shaders/pbr2.fragment"; diff --git a/packages/dev/core/src/Materials/PBR/pbrMaterial2.ts b/packages/dev/core/src/Materials/PBR/pbrMaterial2.ts new file mode 100644 index 00000000000..39ef0957c06 --- /dev/null +++ b/packages/dev/core/src/Materials/PBR/pbrMaterial2.ts @@ -0,0 +1,2138 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { serialize, serializeAsColor3, expandToProperty, serializeAsTexture } from "../../Misc/decorators"; +import { GetEnvironmentBRDFTexture } from "../../Misc/brdfTextureTools"; +import type { Nullable } from "../../types"; +import type { Scene } from "../../scene"; +import { Color3 } from "../../Maths/math.color"; +import { ImageProcessingConfiguration } from "../../Materials/imageProcessingConfiguration"; +import type { ColorCurves } from "../../Materials/colorCurves"; +import type { BaseTexture } from "../../Materials/Textures/baseTexture"; +import { PBRBaseMaterial } from "./pbrBaseMaterial"; +import { RegisterClass } from "../../Misc/typeStore"; +import { Material } from "../material"; +import { SerializationHelper } from "../../Misc/decorators.serialization"; + +import type { AbstractMesh } from "../../Meshes/abstractMesh"; +import type { Effect, IEffectCreationOptions } from "../../Materials/effect"; +import { MaterialDefines } from "../../Materials/materialDefines"; +import type { IImageProcessingConfigurationDefines } from "../../Materials/imageProcessingConfiguration.defines"; +import { EffectFallbacks } from "../effectFallbacks"; +import { AddClipPlaneUniforms } from "../clipPlaneMaterialHelper"; +import { + // BindBonesParameters, + // BindFogParameters, + // BindLights, + // BindLogDepth, + // BindMorphTargetParameters, + // BindTextureMatrix, + HandleFallbacksForShadows, + PrepareAttributesForBakedVertexAnimation, + PrepareAttributesForBones, + PrepareAttributesForInstances, + PrepareAttributesForMorphTargets, + PrepareDefinesForAttributes, + PrepareDefinesForFrameBoundValues, + PrepareDefinesForLights, + PrepareDefinesForMergedUV, + PrepareDefinesForMisc, + PrepareDefinesForMultiview, + PrepareDefinesForOIT, + PrepareDefinesForPrePass, + PrepareUniformsAndSamplersList, +} from "../materialHelper.functions"; +import { Constants } from "../../Engines/constants"; +import { VertexBuffer } from "../../Buffers/buffer"; +import { MaterialPluginEvent } from "../materialPluginEvent"; +import { MaterialHelperGeometryRendering } from "../materialHelper.geometryrendering"; +import { PrePassConfiguration } from "../prePassConfiguration"; +import type { IMaterialCompilationOptions, ICustomShaderNameResolveOptions } from "../../Materials/material"; +import { ShaderLanguage } from "../shaderLanguage"; +import { MaterialFlags } from "../materialFlags"; +import { Texture } from "../../Materials/Textures/texture"; +import type { SubMesh } from "../../Meshes/subMesh"; +import { Logger } from "core/Misc/logger"; + +const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; +/** + * Manages the defines for the PBR Material. + * @internal + */ +export class PBRMaterial2Defines extends MaterialDefines implements IImageProcessingConfigurationDefines { + public PBR = true; + + public NUM_SAMPLES = "0"; + public REALTIME_FILTERING = false; + public IBL_CDF_FILTERING = false; + public MAINUV1 = false; + public MAINUV2 = false; + public MAINUV3 = false; + public MAINUV4 = false; + public MAINUV5 = false; + public MAINUV6 = false; + public UV1 = false; + public UV2 = false; + public UV3 = false; + public UV4 = false; + public UV5 = false; + public UV6 = false; + + public ALBEDO = false; + public GAMMAALBEDO = false; + public ALBEDODIRECTUV = 0; + public VERTEXCOLOR = false; + + public BASE_WEIGHT = false; + public BASE_WEIGHTDIRECTUV = 0; + public BASE_DIFFUSE_ROUGHNESS = false; + public BASE_DIFFUSE_ROUGHNESSDIRECTUV = 0; + + public BAKED_VERTEX_ANIMATION_TEXTURE = false; + + public AMBIENT = false; + public AMBIENTDIRECTUV = 0; + public AMBIENTINGRAYSCALE = false; + + public OPACITY = false; + public VERTEXALPHA = false; + public OPACITYDIRECTUV = 0; + public OPACITYRGB = false; + public ALPHATEST = false; + public DEPTHPREPASS = false; + public ALPHABLEND = false; + public ALPHAFROMALBEDO = false; + public ALPHATESTVALUE = "0.5"; + public SPECULAROVERALPHA = false; + public RADIANCEOVERALPHA = false; + public ALPHAFRESNEL = false; + public LINEARALPHAFRESNEL = false; + public PREMULTIPLYALPHA = false; + + public EMISSIVE = false; + public EMISSIVEDIRECTUV = 0; + public GAMMAEMISSIVE = false; + + public REFLECTIVITY = false; + public REFLECTIVITY_GAMMA = false; + public REFLECTIVITYDIRECTUV = 0; + public SPECULARTERM = false; + + public MICROSURFACEFROMREFLECTIVITYMAP = false; + public MICROSURFACEAUTOMATIC = false; + public LODBASEDMICROSFURACE = false; + public MICROSURFACEMAP = false; + public MICROSURFACEMAPDIRECTUV = 0; + + public METALLICWORKFLOW = false; + public ROUGHNESSSTOREINMETALMAPALPHA = false; + public ROUGHNESSSTOREINMETALMAPGREEN = false; + public METALLNESSSTOREINMETALMAPBLUE = false; + public AOSTOREINMETALMAPRED = false; + public METALLIC_REFLECTANCE = false; + public METALLIC_REFLECTANCE_GAMMA = false; + public METALLIC_REFLECTANCEDIRECTUV = 0; + public METALLIC_REFLECTANCE_USE_ALPHA_ONLY = false; + public REFLECTANCE = false; + public REFLECTANCE_GAMMA = false; + public REFLECTANCEDIRECTUV = 0; + + public ENVIRONMENTBRDF = false; + public ENVIRONMENTBRDF_RGBD = false; + + public NORMAL = false; + public TANGENT = false; + public BUMP = false; + public BUMPDIRECTUV = 0; + public OBJECTSPACE_NORMALMAP = false; + public PARALLAX = false; + public PARALLAX_RHS = false; + public PARALLAXOCCLUSION = false; + public NORMALXYSCALE = true; + + public LIGHTMAP = false; + public LIGHTMAPDIRECTUV = 0; + public USELIGHTMAPASSHADOWMAP = false; + public GAMMALIGHTMAP = false; + public RGBDLIGHTMAP = false; + + public REFLECTION = false; + public REFLECTIONMAP_3D = false; + public REFLECTIONMAP_SPHERICAL = false; + public REFLECTIONMAP_PLANAR = false; + public REFLECTIONMAP_CUBIC = false; + public USE_LOCAL_REFLECTIONMAP_CUBIC = false; + public REFLECTIONMAP_PROJECTION = false; + public REFLECTIONMAP_SKYBOX = false; + public REFLECTIONMAP_EXPLICIT = false; + public REFLECTIONMAP_EQUIRECTANGULAR = false; + public REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; + public REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; + public INVERTCUBICMAP = false; + public USESPHERICALFROMREFLECTIONMAP = false; + public USEIRRADIANCEMAP = false; + public USE_IRRADIANCE_DOMINANT_DIRECTION = false; + public USESPHERICALINVERTEX = false; + public REFLECTIONMAP_OPPOSITEZ = false; + public LODINREFLECTIONALPHA = false; + public GAMMAREFLECTION = false; + public RGBDREFLECTION = false; + public LINEARSPECULARREFLECTION = false; + public RADIANCEOCCLUSION = false; + public HORIZONOCCLUSION = false; + + public INSTANCES = false; + public THIN_INSTANCES = false; + public INSTANCESCOLOR = false; + + public PREPASS = false; + public PREPASS_COLOR = false; + public PREPASS_COLOR_INDEX = -1; + public PREPASS_IRRADIANCE = false; + public PREPASS_IRRADIANCE_INDEX = -1; + public PREPASS_ALBEDO = false; + public PREPASS_ALBEDO_INDEX = -1; + public PREPASS_ALBEDO_SQRT = false; + public PREPASS_ALBEDO_SQRT_INDEX = -1; + public PREPASS_DEPTH = false; + public PREPASS_DEPTH_INDEX = -1; + public PREPASS_SCREENSPACE_DEPTH = false; + public PREPASS_SCREENSPACE_DEPTH_INDEX = -1; + public PREPASS_NORMALIZED_VIEW_DEPTH = false; + public PREPASS_NORMALIZED_VIEW_DEPTH_INDEX = -1; + public PREPASS_NORMAL = false; + public PREPASS_NORMAL_INDEX = -1; + public PREPASS_NORMAL_WORLDSPACE = false; + public PREPASS_WORLD_NORMAL = false; + public PREPASS_WORLD_NORMAL_INDEX = -1; + public PREPASS_POSITION = false; + public PREPASS_POSITION_INDEX = -1; + public PREPASS_LOCAL_POSITION = false; + public PREPASS_LOCAL_POSITION_INDEX = -1; + public PREPASS_VELOCITY = false; + public PREPASS_VELOCITY_INDEX = -1; + public PREPASS_VELOCITY_LINEAR = false; + public PREPASS_VELOCITY_LINEAR_INDEX = -1; + public PREPASS_REFLECTIVITY = false; + public PREPASS_REFLECTIVITY_INDEX = -1; + public SCENE_MRT_COUNT = 0; + + public NUM_BONE_INFLUENCERS = 0; + public BonesPerMesh = 0; + public BONETEXTURE = false; + public BONES_VELOCITY_ENABLED = false; + + public NONUNIFORMSCALING = false; + + public MORPHTARGETS = false; + public MORPHTARGETS_POSITION = false; + public MORPHTARGETS_NORMAL = false; + public MORPHTARGETS_TANGENT = false; + public MORPHTARGETS_UV = false; + public MORPHTARGETS_UV2 = false; + public MORPHTARGETS_COLOR = false; + public MORPHTARGETTEXTURE_HASPOSITIONS = false; + public MORPHTARGETTEXTURE_HASNORMALS = false; + public MORPHTARGETTEXTURE_HASTANGENTS = false; + public MORPHTARGETTEXTURE_HASUVS = false; + public MORPHTARGETTEXTURE_HASUV2S = false; + public MORPHTARGETTEXTURE_HASCOLORS = false; + public NUM_MORPH_INFLUENCERS = 0; + public MORPHTARGETS_TEXTURE = false; + + public IMAGEPROCESSING = false; + public VIGNETTE = false; + public VIGNETTEBLENDMODEMULTIPLY = false; + public VIGNETTEBLENDMODEOPAQUE = false; + public TONEMAPPING = 0; + public CONTRAST = false; + public COLORCURVES = false; + public COLORGRADING = false; + public COLORGRADING3D = false; + public SAMPLER3DGREENDEPTH = false; + public SAMPLER3DBGRMAP = false; + public DITHER = false; + public IMAGEPROCESSINGPOSTPROCESS = false; + public SKIPFINALCOLORCLAMP = false; + public EXPOSURE = false; + public MULTIVIEW = false; + public ORDER_INDEPENDENT_TRANSPARENCY = false; + public ORDER_INDEPENDENT_TRANSPARENCY_16BITS = false; + + public USEPHYSICALLIGHTFALLOFF = false; + public USEGLTFLIGHTFALLOFF = false; + public TWOSIDEDLIGHTING = false; + public MIRRORED = false; + public SHADOWFLOAT = false; + public CLIPPLANE = false; + public CLIPPLANE2 = false; + public CLIPPLANE3 = false; + public CLIPPLANE4 = false; + public CLIPPLANE5 = false; + public CLIPPLANE6 = false; + public POINTSIZE = false; + public FOG = false; + public LOGARITHMICDEPTH = false; + public CAMERA_ORTHOGRAPHIC = false; + public CAMERA_PERSPECTIVE = false; + public AREALIGHTSUPPORTED = true; + + public FORCENORMALFORWARD = false; + + public SPECULARAA = false; + + public UNLIT = false; + + public DECAL_AFTER_DETAIL = false; + + public DEBUGMODE = 0; + + /** + * Initializes the PBR Material defines. + * @param externalProperties The external properties + */ + constructor(externalProperties?: { [name: string]: { type: string; default: any } }) { + super(externalProperties); + this.rebuild(); + } + + /** + * Resets the PBR Material defines. + */ + public override reset(): void { + super.reset(); + this.ALPHATESTVALUE = "0.5"; + this.PBR = true; + this.NORMALXYSCALE = true; + } +} + +/** + * The Physically based material of BJS. + * + * This offers the main features of a standard PBR material. + * For more information, please refer to the documentation : + * https://doc.babylonjs.com/features/featuresDeepDive/materials/using/introToPBR + */ +export class PBRMaterial2 extends PBRBaseMaterial { + /** + * PBRMaterial2TransparencyMode: No transparency mode, Alpha channel is not use. + */ + public static override readonly PBRMATERIAL_OPAQUE = PBRBaseMaterial.PBRMATERIAL_OPAQUE; + + /** + * PBRMaterial2TransparencyMode: Alpha Test mode, pixel are discarded below a certain threshold defined by the alpha cutoff value. + */ + public static override readonly PBRMATERIAL_ALPHATEST = PBRBaseMaterial.PBRMATERIAL_ALPHATEST; + + /** + * PBRMaterial2TransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. + */ + public static override readonly PBRMATERIAL_ALPHABLEND = PBRBaseMaterial.PBRMATERIAL_ALPHABLEND; + + /** + * PBRMaterial2TransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. + * They are also discarded below the alpha cutoff threshold to improve performances. + */ + public static override readonly PBRMATERIAL_ALPHATESTANDBLEND = PBRBaseMaterial.PBRMATERIAL_ALPHATESTANDBLEND; + + /** + * Defines the default value of how much AO map is occluding the analytical lights + * (point spot...). + */ + public static override DEFAULT_AO_ON_ANALYTICAL_LIGHTS = PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; + + /** + * Intensity of the direct lights e.g. the four lights available in your scene. + * This impacts both the direct diffuse and specular highlights. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public directIntensity: number = 1.0; + + /** + * Intensity of the emissive part of the material. + * This helps controlling the emissive effect without modifying the emissive color. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public emissiveIntensity: number = 1.0; + + /** + * Intensity of the environment e.g. how much the environment will light the object + * either through harmonics for rough material or through the reflection for shiny ones. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public environmentIntensity: number = 1.0; + + /** + * This is a special control allowing the reduction of the specular highlights coming from the + * four lights of the scene. Those highlights may not be needed in full environment lighting. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public specularIntensity: number = 1.0; + + /** + * Debug Control allowing disabling the bump map on this material. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public disableBumpMap: boolean = false; + + /** + * AKA Diffuse Texture in standard nomenclature. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public albedoTexture: Nullable; + + /** + * OpenPBR Base Weight texture (multiplier to the diffuse and metal lobes). + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public baseWeightTexture: Nullable; + + /** + * OpenPBR Base Diffuse Roughness texture (roughness of the diffuse lobe). + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public baseDiffuseRoughnessTexture: Nullable; + + /** + * AKA Occlusion Texture in other nomenclature. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public ambientTexture: Nullable; + + /** + * AKA Occlusion Texture Intensity in other nomenclature. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public ambientTextureStrength: number = 1.0; + + /** + * Defines how much the AO map is occluding the analytical lights (point spot...). + * 1 means it completely occludes it + * 0 mean it has no impact + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public ambientTextureImpactOnAnalyticalLights: number = PBRMaterial2.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; + + /** + * Stores the alpha values in a texture. Use luminance if texture.getAlphaFromRGB is true. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesAndMiscDirty") + public opacityTexture: Nullable; + + /** + * Stores the reflection values in a texture. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public reflectionTexture: Nullable; + + /** + * Stores the emissive values in a texture. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public emissiveTexture: Nullable; + + /** + * AKA Specular texture in other nomenclature. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public reflectivityTexture: Nullable; + + /** + * Used to switch from specular/glossiness to metallic/roughness workflow. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public metallicTexture: Nullable; + + /** + * Specifies the metallic scalar of the metallic/roughness workflow. + * Can also be used to scale the metalness values of the metallic texture. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public metallic: Nullable; + + /** + * Specifies the roughness scalar of the metallic/roughness workflow. + * Can also be used to scale the roughness values of the metallic texture. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public roughness: Nullable; + + /** + * In metallic workflow, specifies an F0 factor to help configuring the material F0. + * By default the indexOfrefraction is used to compute F0; + * + * This is used as a factor against the default reflectance at normal incidence to tweak it. + * + * F0 = defaultF0 * metallicF0Factor * metallicReflectanceColor; + * F90 = metallicReflectanceColor; + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public metallicF0Factor = 1; + + /** + * In metallic workflow, specifies an F0 color. + * By default the F90 is always 1; + * + * Please note that this factor is also used as a factor against the default reflectance at normal incidence. + * + * F0 = defaultF0_from_IOR * metallicF0Factor * metallicReflectanceColor + * F90 = metallicF0Factor; + */ + @serializeAsColor3() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public metallicReflectanceColor = Color3.White(); + + /** + * Specifies that only the A channel from metallicReflectanceTexture should be used. + * If false, both RGB and A channels will be used + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useOnlyMetallicFromMetallicReflectanceTexture = false; + + /** + * Defines to store metallicReflectanceColor in RGB and metallicF0Factor in A + * This is multiplied against the scalar values defined in the material. + * If useOnlyMetallicFromMetallicReflectanceTexture is true, don't use the RGB channels, only A + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public metallicReflectanceTexture: Nullable; + + /** + * Defines to store reflectanceColor in RGB + * This is multiplied against the scalar values defined in the material. + * If both reflectanceTexture and metallicReflectanceTexture textures are provided and useOnlyMetallicFromMetallicReflectanceTexture + * is false, metallicReflectanceTexture takes priority and reflectanceTexture is not used + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public reflectanceTexture: Nullable; + + /** + * Used to enable roughness/glossiness fetch from a separate channel depending on the current mode. + * Gray Scale represents roughness in metallic mode and glossiness in specular mode. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public microSurfaceTexture: Nullable; + + /** + * Stores surface normal data used to displace a mesh in a texture. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public bumpTexture: Nullable; + + /** + * Stores the pre-calculated light information of a mesh in a texture. + */ + @serializeAsTexture() + @expandToProperty("_markAllSubMeshesAsTexturesDirty", null) + public lightmapTexture: Nullable; + + /** + * Stores the refracted light information in a texture. + */ + public get refractionTexture(): Nullable { + return this.subSurface.refractionTexture; + } + public set refractionTexture(value: Nullable) { + this.subSurface.refractionTexture = value; + if (value) { + this.subSurface.isRefractionEnabled = true; + } else if (!this.subSurface.linkRefractionWithTransparency) { + this.subSurface.isRefractionEnabled = false; + } + } + + /** + * The color of a material in ambient lighting. + */ + @serializeAsColor3("ambient") + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public ambientColor = new Color3(0, 0, 0); + + /** + * AKA Diffuse Color in other nomenclature. + */ + @serializeAsColor3("albedo") + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public albedoColor = new Color3(1, 1, 1); + + /** + * OpenPBR Base Weight (multiplier to the diffuse and metal lobes). + */ + @serialize("baseWeight") + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public baseWeight = 1; + + /** + * OpenPBR Base Diffuse Roughness (roughness of the diffuse lobe). + */ + @serialize("baseDiffuseRoughness") + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public baseDiffuseRoughness: Nullable; + + /** + * AKA Specular Color in other nomenclature. + */ + @serializeAsColor3("reflectivity") + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public reflectivityColor = new Color3(1, 1, 1); + + /** + * The color reflected from the material. + */ + @serializeAsColor3("reflection") + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public reflectionColor = new Color3(1.0, 1.0, 1.0); + + /** + * The color emitted from the material. + */ + @serializeAsColor3("emissive") + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public emissiveColor = new Color3(0, 0, 0); + + /** + * AKA Glossiness in other nomenclature. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public microSurface = 1.0; + + /** + * Index of refraction of the material base layer. + * https://en.wikipedia.org/wiki/List_of_refractive_indices + * + * This does not only impact refraction but also the Base F0 of Dielectric Materials. + * + * From dielectric fresnel rules: F0 = square((iorT - iorI) / (iorT + iorI)) + */ + public get indexOfRefraction(): number { + return this.subSurface.indexOfRefraction; + } + public set indexOfRefraction(value: number) { + this.subSurface.indexOfRefraction = value; + } + + /** + * Controls if refraction needs to be inverted on Y. This could be useful for procedural texture. + */ + public get invertRefractionY(): boolean { + return this.subSurface.invertRefractionY; + } + public set invertRefractionY(value: boolean) { + this.subSurface.invertRefractionY = value; + } + + /** + * This parameters will make the material used its opacity to control how much it is refracting against not. + * Materials half opaque for instance using refraction could benefit from this control. + */ + public get linkRefractionWithTransparency(): boolean { + return this.subSurface.linkRefractionWithTransparency; + } + public set linkRefractionWithTransparency(value: boolean) { + this.subSurface.linkRefractionWithTransparency = value; + if (value) { + this.subSurface.isRefractionEnabled = true; + } + } + + /** + * If true, the light map contains occlusion information instead of lighting info. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useLightmapAsShadowmap = false; + + /** + * Specifies that the alpha is coming form the albedo channel alpha channel for alpha blending. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesAndMiscDirty") + public useAlphaFromAlbedoTexture = false; + + /** + * Enforces alpha test in opaque or blend mode in order to improve the performances of some situations. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesAndMiscDirty") + public forceAlphaTest = false; + + /** + * Defines the alpha limits in alpha test mode. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesAndMiscDirty") + public alphaCutOff = 0.4; + + /** + * Specifies that the material will keep the specular highlights over a transparent surface (only the most luminous ones). + * A car glass is a good example of that. When sun reflects on it you can not see what is behind. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useSpecularOverAlpha = true; + + /** + * Specifies if the reflectivity texture contains the glossiness information in its alpha channel. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useMicroSurfaceFromReflectivityMapAlpha = false; + + /** + * Specifies if the metallic texture contains the roughness information in its alpha channel. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useRoughnessFromMetallicTextureAlpha = true; + + /** + * Specifies if the metallic texture contains the roughness information in its green channel. + * Needs useRoughnessFromMetallicTextureAlpha to be false. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useRoughnessFromMetallicTextureGreen = false; + + /** + * Specifies if the metallic texture contains the metallness information in its blue channel. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useMetallnessFromMetallicTextureBlue = false; + + /** + * Specifies if the metallic texture contains the ambient occlusion information in its red channel. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useAmbientOcclusionFromMetallicTextureRed = false; + + /** + * Specifies if the ambient texture contains the ambient occlusion information in its red channel only. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useAmbientInGrayScale = false; + + /** + * In case the reflectivity map does not contain the microsurface information in its alpha channel, + * The material will try to infer what glossiness each pixel should be. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useAutoMicroSurfaceFromReflectivityMap = false; + + /** + * BJS is using an hardcoded light falloff based on a manually sets up range. + * In PBR, one way to represents the falloff is to use the inverse squared root algorithm. + * This parameter can help you switch back to the BJS mode in order to create scenes using both materials. + */ + @serialize() + public get usePhysicalLightFalloff(): boolean { + return this._lightFalloff === PBRBaseMaterial.LIGHTFALLOFF_PHYSICAL; + } + + /** + * BJS is using an hardcoded light falloff based on a manually sets up range. + * In PBR, one way to represents the falloff is to use the inverse squared root algorithm. + * This parameter can help you switch back to the BJS mode in order to create scenes using both materials. + */ + public set usePhysicalLightFalloff(value: boolean) { + if (value !== this.usePhysicalLightFalloff) { + // Ensure the effect will be rebuilt. + this._markAllSubMeshesAsTexturesDirty(); + + if (value) { + this._lightFalloff = PBRBaseMaterial.LIGHTFALLOFF_PHYSICAL; + } else { + this._lightFalloff = PBRBaseMaterial.LIGHTFALLOFF_STANDARD; + } + } + } + + /** + * In order to support the falloff compatibility with gltf, a special mode has been added + * to reproduce the gltf light falloff. + */ + @serialize() + public get useGLTFLightFalloff(): boolean { + return this._lightFalloff === PBRBaseMaterial.LIGHTFALLOFF_GLTF; + } + + /** + * In order to support the falloff compatibility with gltf, a special mode has been added + * to reproduce the gltf light falloff. + */ + public set useGLTFLightFalloff(value: boolean) { + if (value !== this.useGLTFLightFalloff) { + // Ensure the effect will be rebuilt. + this._markAllSubMeshesAsTexturesDirty(); + + if (value) { + this._lightFalloff = PBRBaseMaterial.LIGHTFALLOFF_GLTF; + } else { + this._lightFalloff = PBRBaseMaterial.LIGHTFALLOFF_STANDARD; + } + } + } + + /** + * Specifies that the material will keeps the reflection highlights over a transparent surface (only the most luminous ones). + * A car glass is a good example of that. When the street lights reflects on it you can not see what is behind. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useRadianceOverAlpha = true; + + /** + * Allows using an object space normal map (instead of tangent space). + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useObjectSpaceNormalMap = false; + + /** + * Allows using the bump map in parallax mode. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useParallax = false; + + /** + * Allows using the bump map in parallax occlusion mode. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useParallaxOcclusion = false; + + /** + * Controls the scale bias of the parallax mode. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public parallaxScaleBias = 0.05; + + /** + * If sets to true, disables all the lights affecting the material. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsLightsDirty") + public disableLighting = false; + + /** + * Force the shader to compute irradiance in the fragment shader in order to take bump in account. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public forceIrradianceInFragment = false; + + /** + * Number of Simultaneous lights allowed on the material. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsLightsDirty") + public maxSimultaneousLights = 4; + + /** + * If sets to true, x component of normal map value will invert (x = 1.0 - x). + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public invertNormalMapX = false; + + /** + * If sets to true, y component of normal map value will invert (y = 1.0 - y). + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public invertNormalMapY = false; + + /** + * If sets to true and backfaceCulling is false, normals will be flipped on the backside. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public twoSidedLighting = false; + + /** + * A fresnel is applied to the alpha of the model to ensure grazing angles edges are not alpha tested. + * And/Or occlude the blended part. (alpha is converted to gamma to compute the fresnel) + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useAlphaFresnel = false; + + /** + * A fresnel is applied to the alpha of the model to ensure grazing angles edges are not alpha tested. + * And/Or occlude the blended part. (alpha stays linear to compute the fresnel) + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useLinearAlphaFresnel = false; + + /** + * Let user defines the brdf lookup texture used for IBL. + * A default 8bit version is embedded but you could point at : + * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF_RGBD.png + * * Default 16bit pixel depth texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.dds + * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF_RGBD.png + * * LEGACY Default None correlated 16bit pixel depth https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds + */ + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public environmentBRDFTexture: Nullable = null; + + /** + * Force normal to face away from face. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public forceNormalForward = false; + + /** + * Enables specular anti aliasing in the PBR shader. + * It will both interacts on the Geometry for analytical and IBL lighting. + * It also prefilter the roughness map based on the bump values. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public enableSpecularAntiAliasing = false; + + /** + * This parameters will enable/disable Horizon occlusion to prevent normal maps to look shiny when the normal + * makes the reflect vector face the model (under horizon). + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useHorizonOcclusion = true; + + /** + * This parameters will enable/disable radiance occlusion by preventing the radiance to lit + * too much the area relying on ambient texture to define their ambient occlusion. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsTexturesDirty") + public useRadianceOcclusion = true; + + /** + * If set to true, no lighting calculations will be applied. + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsMiscDirty") + public unlit = false; + + /** + * If sets to true, the decal map will be applied after the detail map. Else, it is applied before (default: false) + */ + @serialize() + @expandToProperty("_markAllSubMeshesAsMiscDirty") + public applyDecalMapAfterDetailMap = false; + + /** + * Gets the image processing configuration used either in this material. + */ + public get imageProcessingConfiguration(): ImageProcessingConfiguration { + return this._imageProcessingConfiguration; + } + + /** + * Sets the Default image processing configuration used either in the this material. + * + * If sets to null, the scene one is in use. + */ + public set imageProcessingConfiguration(value: ImageProcessingConfiguration) { + this._attachImageProcessingConfiguration(value); + + // Ensure the effect will be rebuilt. + this._markAllSubMeshesAsImageProcessingDirty(); + } + + /** + * Gets whether the color curves effect is enabled. + */ + public get cameraColorCurvesEnabled(): boolean { + return this.imageProcessingConfiguration.colorCurvesEnabled; + } + /** + * Sets whether the color curves effect is enabled. + */ + public set cameraColorCurvesEnabled(value: boolean) { + this.imageProcessingConfiguration.colorCurvesEnabled = value; + } + + /** + * Gets whether the color grading effect is enabled. + */ + public get cameraColorGradingEnabled(): boolean { + return this.imageProcessingConfiguration.colorGradingEnabled; + } + /** + * Gets whether the color grading effect is enabled. + */ + public set cameraColorGradingEnabled(value: boolean) { + this.imageProcessingConfiguration.colorGradingEnabled = value; + } + + /** + * Gets whether tonemapping is enabled or not. + */ + public get cameraToneMappingEnabled(): boolean { + return this._imageProcessingConfiguration.toneMappingEnabled; + } + /** + * Sets whether tonemapping is enabled or not + */ + public set cameraToneMappingEnabled(value: boolean) { + this._imageProcessingConfiguration.toneMappingEnabled = value; + } + + /** + * The camera exposure used on this material. + * This property is here and not in the camera to allow controlling exposure without full screen post process. + * This corresponds to a photographic exposure. + */ + public get cameraExposure(): number { + return this._imageProcessingConfiguration.exposure; + } + /** + * The camera exposure used on this material. + * This property is here and not in the camera to allow controlling exposure without full screen post process. + * This corresponds to a photographic exposure. + */ + public set cameraExposure(value: number) { + this._imageProcessingConfiguration.exposure = value; + } + + /** + * Gets The camera contrast used on this material. + */ + public get cameraContrast(): number { + return this._imageProcessingConfiguration.contrast; + } + + /** + * Sets The camera contrast used on this material. + */ + public set cameraContrast(value: number) { + this._imageProcessingConfiguration.contrast = value; + } + + /** + * Gets the Color Grading 2D Lookup Texture. + */ + public get cameraColorGradingTexture(): Nullable { + return this._imageProcessingConfiguration.colorGradingTexture; + } + /** + * Sets the Color Grading 2D Lookup Texture. + */ + public set cameraColorGradingTexture(value: Nullable) { + this._imageProcessingConfiguration.colorGradingTexture = value; + } + + /** + * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). + * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. + * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; + * corresponding to low luminance, medium luminance, and high luminance areas respectively. + */ + public get cameraColorCurves(): Nullable { + return this._imageProcessingConfiguration.colorCurves; + } + /** + * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). + * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. + * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; + * corresponding to low luminance, medium luminance, and high luminance areas respectively. + */ + public set cameraColorCurves(value: Nullable) { + this._imageProcessingConfiguration.colorCurves = value; + } + + /** + * Instantiates a new PBRMaterial2 instance. + * + * @param name The material name + * @param scene The scene the material will be use in. + * @param forceGLSL Use the GLSL code generation for the shader (even on WebGPU). Default is false + */ + constructor(name: string, scene?: Scene, forceGLSL = false) { + super(name, scene, forceGLSL); + + this._environmentBRDFTexture = GetEnvironmentBRDFTexture(this.getScene()); + } + + /** + * @returns the name of this material class. + */ + public override getClassName(): string { + return "PBRMaterial2"; + } + + /** + * Makes a duplicate of the current material. + * @param name - name to use for the new material. + * @param cloneTexturesOnlyOnce - if a texture is used in more than one channel (e.g diffuse and opacity), only clone it once and reuse it on the other channels. Default false. + * @param rootUrl defines the root URL to use to load textures + * @returns cloned material instance + */ + public override clone(name: string, cloneTexturesOnlyOnce: boolean = true, rootUrl = ""): PBRMaterial2 { + const clone = SerializationHelper.Clone(() => new PBRMaterial2(name, this.getScene()), this, { cloneTexturesOnlyOnce }); + + clone.id = name; + clone.name = name; + + this.stencil.copyTo(clone.stencil); + + this._clonePlugins(clone, rootUrl); + + return clone; + } + + /** + * Serializes this PBR Material. + * @returns - An object with the serialized material. + */ + public override serialize(): any { + const serializationObject = super.serialize(); + serializationObject.customType = "BABYLON.PBRMaterial2"; + + return serializationObject; + } + + // Statics + /** + * Parses a PBR Material from a serialized object. + * @param source - Serialized object. + * @param scene - BJS scene instance. + * @param rootUrl - url for the scene object + * @returns - PBRMaterial2 + */ + public static override Parse(source: any, scene: Scene, rootUrl: string): PBRMaterial2 { + const material = SerializationHelper.Parse(() => new PBRMaterial2(source.name, scene), source, scene, rootUrl); + + if (source.stencil) { + material.stencil.parse(source.stencil, scene, rootUrl); + } + + Material._ParsePlugins(source, material, scene, rootUrl); + + // The code block below ensures backward compatibility with serialized materials before plugins are automatically serialized. + if (source.clearCoat) { + material.clearCoat.parse(source.clearCoat, scene, rootUrl); + } + if (source.anisotropy) { + material.anisotropy.parse(source.anisotropy, scene, rootUrl); + } + if (source.brdf) { + material.brdf.parse(source.brdf, scene, rootUrl); + } + if (source.sheen) { + material.sheen.parse(source.sheen, scene, rootUrl); + } + if (source.subSurface) { + material.subSurface.parse(source.subSurface, scene, rootUrl); + } + if (source.iridescence) { + material.iridescence.parse(source.iridescence, scene, rootUrl); + } + + return material; + } + + /** + * Force shader compilation + * @param mesh - Define the mesh we want to force the compilation for + * @param onCompiled - Define a callback triggered when the compilation completes + * @param options - Define the options used to create the compilation + */ + public override forceCompilation(mesh: AbstractMesh, onCompiled?: (material: Material) => void, options?: Partial): void { + const localOptions = { + clipPlane: false, + useInstances: false, + ...options, + }; + + if (!this._uniformBufferLayoutBuilt) { + this.buildUniformLayout(); + } + + this._callbackPluginEventGeneric(MaterialPluginEvent.GetDefineNames, this._eventInfo); + const checkReady = () => { + if (this._breakShaderLoadedCheck2) { + return; + } + const defines = new PBRMaterial2Defines(this._eventInfo.defineNames); + const effect = this._prepareEffect2(mesh, defines, undefined, undefined, localOptions.useInstances, localOptions.clipPlane, mesh.hasThinInstances)!; + if (this._onEffectCreatedObservable) { + onCreatedEffectParameters.effect = effect; + onCreatedEffectParameters.subMesh = null; + this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters); + } + if (effect.isReady()) { + if (onCompiled) { + onCompiled(this); + } + } else { + effect.onCompileObservable.add(() => { + if (onCompiled) { + onCompiled(this); + } + }); + } + }; + checkReady(); + } + + /** + * Specifies that the submesh is ready to be used. + * @param mesh - BJS mesh. + * @param subMesh - A submesh of the BJS mesh. Used to check if it is ready. + * @param useInstances - Specifies that instances should be used. + * @returns - boolean indicating that the submesh is ready or not. + */ + public override isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean { + if (!this._uniformBufferLayoutBuilt) { + this.buildUniformLayout(); + } + + const drawWrapper = subMesh._drawWrapper; + + if (drawWrapper.effect && this.isFrozen) { + if (drawWrapper._wasPreviouslyReady && drawWrapper._wasPreviouslyUsingInstances === useInstances) { + return true; + } + } + + if (!subMesh.materialDefines) { + this._callbackPluginEventGeneric(MaterialPluginEvent.GetDefineNames, this._eventInfo); + subMesh.materialDefines = new PBRMaterial2Defines(this._eventInfo.defineNames); + } + + const defines = subMesh.materialDefines; + if (this._isReadyForSubMesh(subMesh)) { + return true; + } + + const scene = this.getScene(); + const engine = scene.getEngine(); + + if (defines._areTexturesDirty) { + this._eventInfo.hasRenderTargetTextures = false; + this._callbackPluginEventHasRenderTargetTextures(this._eventInfo); + this._cacheHasRenderTargetTextures = this._eventInfo.hasRenderTargetTextures; + if (scene.texturesEnabled) { + if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { + if (!this._albedoTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { + if (!this._baseWeightTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._baseDiffuseRoughnessTexture && MaterialFlags.BaseDiffuseRoughnessTextureEnabled) { + if (!this._baseDiffuseRoughnessTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { + if (!this._ambientTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._opacityTexture && MaterialFlags.OpacityTextureEnabled) { + if (!this._opacityTexture.isReadyOrNotBlocking()) { + return false; + } + } + + const reflectionTexture = this._getReflectionTexture2(); + if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { + if (!reflectionTexture.isReadyOrNotBlocking()) { + return false; + } + if (reflectionTexture.irradianceTexture) { + if (!reflectionTexture.irradianceTexture.isReadyOrNotBlocking()) { + return false; + } + } else { + // Not ready until spherical are ready too. + if (!reflectionTexture.sphericalPolynomial && reflectionTexture.getInternalTexture()?._sphericalPolynomialPromise) { + return false; + } + } + } + + if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { + if (!this._lightmapTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { + if (!this._emissiveTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (MaterialFlags.SpecularTextureEnabled) { + if (this._metallicTexture) { + if (!this._metallicTexture.isReadyOrNotBlocking()) { + return false; + } + } else if (this._reflectivityTexture) { + if (!this._reflectivityTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._metallicReflectanceTexture) { + if (!this._metallicReflectanceTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._reflectanceTexture) { + if (!this._reflectanceTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._microSurfaceTexture) { + if (!this._microSurfaceTexture.isReadyOrNotBlocking()) { + return false; + } + } + } + + if (engine.getCaps().standardDerivatives && this._bumpTexture && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { + // Bump texture cannot be not blocking. + if (!this._bumpTexture.isReady()) { + return false; + } + } + + if (this._environmentBRDFTexture && MaterialFlags.ReflectionTextureEnabled) { + // This is blocking. + if (!this._environmentBRDFTexture.isReady()) { + return false; + } + } + } + } + + this._eventInfo.isReadyForSubMesh = true; + this._eventInfo.defines = defines; + this._eventInfo.subMesh = subMesh; + this._callbackPluginEventIsReadyForSubMesh(this._eventInfo); + + if (!this._eventInfo.isReadyForSubMesh) { + return false; + } + + if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) { + if (!this._imageProcessingConfiguration.isReady()) { + return false; + } + } + + // Check if Area Lights have LTC texture. + if (defines["AREALIGHTUSED"]) { + for (let index = 0; index < mesh.lightSources.length; index++) { + if (!mesh.lightSources[index]._isReady()) { + return false; + } + } + } + + if (!engine.getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) { + mesh.createNormals(true); + Logger.Warn("PBRMaterial2: Normals have been created for the mesh: " + mesh.name); + } + + const previousEffect = subMesh.effect; + const lightDisposed = defines._areLightsDisposed; + let effect = this._prepareEffect2(mesh, defines, this.onCompiled, this.onError, useInstances, null, subMesh.getRenderingMesh().hasThinInstances); + + let forceWasNotReadyPreviously = false; + + if (effect) { + if (this._onEffectCreatedObservable) { + onCreatedEffectParameters.effect = effect; + onCreatedEffectParameters.subMesh = subMesh; + this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters); + } + + // Use previous effect while new one is compiling + if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) { + effect = previousEffect; + defines.markAsUnprocessed(); + + forceWasNotReadyPreviously = this.isFrozen; + + if (lightDisposed) { + // re register in case it takes more than one frame. + defines._areLightsDisposed = true; + return false; + } + } else { + scene.resetCachedMaterial(); + subMesh.setEffect(effect, defines, this._materialContext); + } + } + + if (!subMesh.effect || !subMesh.effect.isReady()) { + return false; + } + + defines._renderId = scene.getRenderId(); + drawWrapper._wasPreviouslyReady = forceWasNotReadyPreviously ? false : true; + drawWrapper._wasPreviouslyUsingInstances = !!useInstances; + + this._checkScenePerformancePriority(); + + return true; + } + + private _prepareEffect2( + mesh: AbstractMesh, + defines: PBRMaterial2Defines, + onCompiled: Nullable<(effect: Effect) => void> = null, + onError: Nullable<(effect: Effect, errors: string) => void> = null, + useInstances: Nullable = null, + useClipPlane: Nullable = null, + useThinInstances: boolean + ): Nullable { + this._prepareDefines2(mesh, defines, useInstances, useClipPlane, useThinInstances); + + if (!defines.isDirty) { + return null; + } + + defines.markAsProcessed(); + + const scene = this.getScene(); + const engine = scene.getEngine(); + + // Fallbacks + const fallbacks = new EffectFallbacks(); + let fallbackRank = 0; + if (defines.USESPHERICALINVERTEX) { + fallbacks.addFallback(fallbackRank++, "USESPHERICALINVERTEX"); + } + + if (defines.FOG) { + fallbacks.addFallback(fallbackRank, "FOG"); + } + if (defines.SPECULARAA) { + fallbacks.addFallback(fallbackRank, "SPECULARAA"); + } + if (defines.POINTSIZE) { + fallbacks.addFallback(fallbackRank, "POINTSIZE"); + } + if (defines.LOGARITHMICDEPTH) { + fallbacks.addFallback(fallbackRank, "LOGARITHMICDEPTH"); + } + if (defines.PARALLAX) { + fallbacks.addFallback(fallbackRank, "PARALLAX"); + } + if (defines.PARALLAX_RHS) { + fallbacks.addFallback(fallbackRank, "PARALLAX_RHS"); + } + if (defines.PARALLAXOCCLUSION) { + fallbacks.addFallback(fallbackRank++, "PARALLAXOCCLUSION"); + } + + if (defines.ENVIRONMENTBRDF) { + fallbacks.addFallback(fallbackRank++, "ENVIRONMENTBRDF"); + } + + if (defines.TANGENT) { + fallbacks.addFallback(fallbackRank++, "TANGENT"); + } + + if (defines.BUMP) { + fallbacks.addFallback(fallbackRank++, "BUMP"); + } + + fallbackRank = HandleFallbacksForShadows(defines, fallbacks, this._maxSimultaneousLights, fallbackRank++); + + if (defines.SPECULARTERM) { + fallbacks.addFallback(fallbackRank++, "SPECULARTERM"); + } + + if (defines.USESPHERICALFROMREFLECTIONMAP) { + fallbacks.addFallback(fallbackRank++, "USESPHERICALFROMREFLECTIONMAP"); + } + + if (defines.USEIRRADIANCEMAP) { + fallbacks.addFallback(fallbackRank++, "USEIRRADIANCEMAP"); + } + + if (defines.LIGHTMAP) { + fallbacks.addFallback(fallbackRank++, "LIGHTMAP"); + } + + if (defines.NORMAL) { + fallbacks.addFallback(fallbackRank++, "NORMAL"); + } + + if (defines.AMBIENT) { + fallbacks.addFallback(fallbackRank++, "AMBIENT"); + } + + if (defines.EMISSIVE) { + fallbacks.addFallback(fallbackRank++, "EMISSIVE"); + } + + if (defines.VERTEXCOLOR) { + fallbacks.addFallback(fallbackRank++, "VERTEXCOLOR"); + } + + if (defines.MORPHTARGETS) { + fallbacks.addFallback(fallbackRank++, "MORPHTARGETS"); + } + + if (defines.MULTIVIEW) { + fallbacks.addFallback(0, "MULTIVIEW"); + } + + //Attributes + const attribs = [VertexBuffer.PositionKind]; + + if (defines.NORMAL) { + attribs.push(VertexBuffer.NormalKind); + } + + if (defines.TANGENT) { + attribs.push(VertexBuffer.TangentKind); + } + + for (let i = 1; i <= Constants.MAX_SUPPORTED_UV_SETS; ++i) { + if (defines["UV" + i]) { + attribs.push(`uv${i === 1 ? "" : i}`); + } + } + + if (defines.VERTEXCOLOR) { + attribs.push(VertexBuffer.ColorKind); + } + + PrepareAttributesForBones(attribs, mesh, defines, fallbacks); + PrepareAttributesForInstances(attribs, defines); + PrepareAttributesForMorphTargets(attribs, mesh, defines); + PrepareAttributesForBakedVertexAnimation(attribs, mesh, defines); + + let shaderName = "pbr2"; + + const uniforms = [ + "world", + "view", + "viewProjection", + "vEyePosition", + "vLightsType", + "vAmbientColor", + "vAlbedoColor", + "baseWeight", + "baseDiffuseRoughness", + "vReflectivityColor", + "vMetallicReflectanceFactors", + "vEmissiveColor", + "visibility", + "vReflectionColor", + "vFogInfos", + "vFogColor", + "pointSize", + "vAlbedoInfos", + "vBaseWeightInfos", + "vBaseDiffuseRoughnessInfos", + "vAmbientInfos", + "vOpacityInfos", + "vReflectionInfos", + "vReflectionPosition", + "vReflectionSize", + "vEmissiveInfos", + "vReflectivityInfos", + "vReflectionFilteringInfo", + "vMetallicReflectanceInfos", + "vReflectanceInfos", + "vMicroSurfaceSamplerInfos", + "vBumpInfos", + "vLightmapInfos", + "mBones", + "albedoMatrix", + "baseWeightMatrix", + "baseDiffuseRoughnessMatrix", + "ambientMatrix", + "opacityMatrix", + "reflectionMatrix", + "emissiveMatrix", + "reflectivityMatrix", + "normalMatrix", + "microSurfaceSamplerMatrix", + "bumpMatrix", + "lightmapMatrix", + "metallicReflectanceMatrix", + "reflectanceMatrix", + "vLightingIntensity", + "logarithmicDepthConstant", + "vSphericalX", + "vSphericalY", + "vSphericalZ", + "vSphericalXX_ZZ", + "vSphericalYY_ZZ", + "vSphericalZZ", + "vSphericalXY", + "vSphericalYZ", + "vSphericalZX", + "vSphericalL00", + "vSphericalL1_1", + "vSphericalL10", + "vSphericalL11", + "vSphericalL2_2", + "vSphericalL2_1", + "vSphericalL20", + "vSphericalL21", + "vSphericalL22", + "vReflectionMicrosurfaceInfos", + "vReflectionDominantDirection", + "vTangentSpaceParams", + "boneTextureWidth", + "vDebugMode", + "morphTargetTextureInfo", + "morphTargetTextureIndices", + "cameraInfo", + ]; + + const samplers = [ + "albedoSampler", + "baseWeightSampler", + "baseDiffuseRoughnessSampler", + "reflectivitySampler", + "ambientSampler", + "emissiveSampler", + "bumpSampler", + "lightmapSampler", + "opacitySampler", + "reflectionSampler", + "reflectionSamplerLow", + "reflectionSamplerHigh", + "irradianceSampler", + "microSurfaceSampler", + "environmentBrdfSampler", + "boneSampler", + "metallicReflectanceSampler", + "reflectanceSampler", + "morphTargets", + "oitDepthSampler", + "oitFrontColorSampler", + "icdfSampler", + "areaLightsLTC1Sampler", + "areaLightsLTC2Sampler", + ]; + + const uniformBuffers = ["Material", "Scene", "Mesh"]; + + const indexParameters = { maxSimultaneousLights: this._maxSimultaneousLights, maxSimultaneousMorphTargets: defines.NUM_MORPH_INFLUENCERS }; + + this._eventInfo.fallbacks = fallbacks; + this._eventInfo.fallbackRank = fallbackRank; + this._eventInfo.defines = defines; + this._eventInfo.uniforms = uniforms; + this._eventInfo.attributes = attribs; + this._eventInfo.samplers = samplers; + this._eventInfo.uniformBuffersNames = uniformBuffers; + this._eventInfo.customCode = undefined; + this._eventInfo.mesh = mesh; + this._eventInfo.indexParameters = indexParameters; + this._callbackPluginEventGeneric(MaterialPluginEvent.PrepareEffect, this._eventInfo); + + MaterialHelperGeometryRendering.AddUniformsAndSamplers(uniforms, samplers); + + PrePassConfiguration.AddUniforms(uniforms); + PrePassConfiguration.AddSamplers(samplers); + AddClipPlaneUniforms(uniforms); + + if (ImageProcessingConfiguration) { + ImageProcessingConfiguration.PrepareUniforms(uniforms, defines); + ImageProcessingConfiguration.PrepareSamplers(samplers, defines); + } + + PrepareUniformsAndSamplersList({ + uniformsNames: uniforms, + uniformBuffersNames: uniformBuffers, + samplers: samplers, + defines: defines, + maxSimultaneousLights: this._maxSimultaneousLights, + }); + + const csnrOptions: ICustomShaderNameResolveOptions = {}; + + if (this.customShaderNameResolve) { + shaderName = this.customShaderNameResolve(shaderName, uniforms, uniformBuffers, samplers, defines, attribs, csnrOptions); + } + + const join = defines.toString(); + const effect = engine.createEffect( + shaderName, + { + attributes: attribs, + uniformsNames: uniforms, + uniformBuffersNames: uniformBuffers, + samplers: samplers, + defines: join, + fallbacks: fallbacks, + onCompiled: onCompiled, + onError: onError, + indexParameters, + processFinalCode: csnrOptions.processFinalCode, + processCodeAfterIncludes: this._eventInfo.customCode, + multiTarget: defines.PREPASS, + shaderLanguage: this._shaderLanguage, + extraInitializationsAsync: this._shadersLoaded2 + ? undefined + : async () => { + if (this.shaderLanguage === ShaderLanguage.WGSL) { + await Promise.all([import("../../ShadersWGSL/pbr2.vertex"), import("../../ShadersWGSL/pbr2.fragment")]); + } else { + await Promise.all([import("../../Shaders/pbr2.vertex"), import("../../Shaders/pbr2.fragment")]); + } + + this._shadersLoaded2 = true; + }, + }, + engine + ); + + this._eventInfo.customCode = undefined; + + return effect; + } + + private _prepareDefines2( + mesh: AbstractMesh, + defines: PBRMaterial2Defines, + useInstances: Nullable = null, + useClipPlane: Nullable = null, + useThinInstances: boolean = false + ): void { + const scene = this.getScene(); + const engine = scene.getEngine(); + + // Lights + PrepareDefinesForLights(scene, mesh, defines, true, this._maxSimultaneousLights, this._disableLighting); + defines._needNormals = true; + + // Multiview + PrepareDefinesForMultiview(scene, defines); + + // PrePass + const oit = this.needAlphaBlendingForMesh(mesh) && this.getScene().useOrderIndependentTransparency; + PrepareDefinesForPrePass(scene, defines, this.canRenderToMRT && !oit); + + // Order independant transparency + PrepareDefinesForOIT(scene, defines, oit); + + MaterialHelperGeometryRendering.PrepareDefines(engine.currentRenderPassId, mesh, defines); + + // Textures + defines.METALLICWORKFLOW = this.isMetallicWorkflow(); + if (defines._areTexturesDirty) { + defines._needUVs = false; + for (let i = 1; i <= Constants.MAX_SUPPORTED_UV_SETS; ++i) { + defines["MAINUV" + i] = false; + } + if (scene.texturesEnabled) { + defines.ALBEDODIRECTUV = 0; + defines.BASE_WEIGHTDIRECTUV = 0; + defines.BASE_DIFFUSE_ROUGHNESSDIRECTUV = 0; + defines.AMBIENTDIRECTUV = 0; + defines.OPACITYDIRECTUV = 0; + defines.EMISSIVEDIRECTUV = 0; + defines.REFLECTIVITYDIRECTUV = 0; + defines.MICROSURFACEMAPDIRECTUV = 0; + defines.METALLIC_REFLECTANCEDIRECTUV = 0; + defines.REFLECTANCEDIRECTUV = 0; + defines.BUMPDIRECTUV = 0; + defines.LIGHTMAPDIRECTUV = 0; + + if (engine.getCaps().textureLOD) { + defines.LODBASEDMICROSFURACE = true; + } + + if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { + PrepareDefinesForMergedUV(this._albedoTexture, defines, "ALBEDO"); + defines.GAMMAALBEDO = this._albedoTexture.gammaSpace; + } else { + defines.ALBEDO = false; + } + + if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { + PrepareDefinesForMergedUV(this._baseWeightTexture, defines, "BASE_WEIGHT"); + } else { + defines.BASE_WEIGHT = false; + } + + if (this._baseDiffuseRoughnessTexture && MaterialFlags.BaseDiffuseRoughnessTextureEnabled) { + PrepareDefinesForMergedUV(this._baseDiffuseRoughnessTexture, defines, "BASE_DIFFUSE_ROUGHNESS"); + } else { + defines.BASE_DIFFUSE_ROUGHNESS = false; + } + + if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { + PrepareDefinesForMergedUV(this._ambientTexture, defines, "AMBIENT"); + defines.AMBIENTINGRAYSCALE = this._useAmbientInGrayScale; + } else { + defines.AMBIENT = false; + } + + if (this._opacityTexture && MaterialFlags.OpacityTextureEnabled) { + PrepareDefinesForMergedUV(this._opacityTexture, defines, "OPACITY"); + defines.OPACITYRGB = this._opacityTexture.getAlphaFromRGB; + } else { + defines.OPACITY = false; + } + + const reflectionTexture = this._getReflectionTexture2(); + if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { + defines.REFLECTION = true; + defines.GAMMAREFLECTION = reflectionTexture.gammaSpace; + defines.RGBDREFLECTION = reflectionTexture.isRGBD; + defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha; + defines.LINEARSPECULARREFLECTION = reflectionTexture.linearSpecularLOD; + defines.USEIRRADIANCEMAP = false; + + if (this.realTimeFiltering && this.realTimeFilteringQuality > 0) { + defines.NUM_SAMPLES = "" + this.realTimeFilteringQuality; + if (engine._features.needTypeSuffixInShaderConstants) { + defines.NUM_SAMPLES = defines.NUM_SAMPLES + "u"; + } + + defines.REALTIME_FILTERING = true; + if (this.getScene().iblCdfGenerator) { + defines.IBL_CDF_FILTERING = true; + } + } else { + defines.REALTIME_FILTERING = false; + } + + defines.INVERTCUBICMAP = reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE; + defines.REFLECTIONMAP_3D = reflectionTexture.isCube; + defines.REFLECTIONMAP_OPPOSITEZ = defines.REFLECTIONMAP_3D && this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ; + + defines.REFLECTIONMAP_CUBIC = false; + defines.REFLECTIONMAP_EXPLICIT = false; + defines.REFLECTIONMAP_PLANAR = false; + defines.REFLECTIONMAP_PROJECTION = false; + defines.REFLECTIONMAP_SKYBOX = false; + defines.REFLECTIONMAP_SPHERICAL = false; + defines.REFLECTIONMAP_EQUIRECTANGULAR = false; + defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; + defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; + + switch (reflectionTexture.coordinatesMode) { + case Texture.EXPLICIT_MODE: + defines.REFLECTIONMAP_EXPLICIT = true; + break; + case Texture.PLANAR_MODE: + defines.REFLECTIONMAP_PLANAR = true; + break; + case Texture.PROJECTION_MODE: + defines.REFLECTIONMAP_PROJECTION = true; + break; + case Texture.SKYBOX_MODE: + defines.REFLECTIONMAP_SKYBOX = true; + break; + case Texture.SPHERICAL_MODE: + defines.REFLECTIONMAP_SPHERICAL = true; + break; + case Texture.EQUIRECTANGULAR_MODE: + defines.REFLECTIONMAP_EQUIRECTANGULAR = true; + break; + case Texture.FIXED_EQUIRECTANGULAR_MODE: + defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true; + break; + case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE: + defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true; + break; + case Texture.CUBIC_MODE: + case Texture.INVCUBIC_MODE: + default: + defines.REFLECTIONMAP_CUBIC = true; + defines.USE_LOCAL_REFLECTIONMAP_CUBIC = (reflectionTexture).boundingBoxSize ? true : false; + break; + } + + if (reflectionTexture.coordinatesMode !== Texture.SKYBOX_MODE) { + if (reflectionTexture.irradianceTexture) { + defines.USEIRRADIANCEMAP = true; + defines.USESPHERICALFROMREFLECTIONMAP = false; + defines.USESPHERICALINVERTEX = false; + if (reflectionTexture.irradianceTexture._dominantDirection) { + defines.USE_IRRADIANCE_DOMINANT_DIRECTION = true; + } + } + // Assume using spherical polynomial if the reflection texture is a cube map + else if (reflectionTexture.isCube) { + defines.USESPHERICALFROMREFLECTIONMAP = true; + defines.USEIRRADIANCEMAP = false; + defines.USE_IRRADIANCE_DOMINANT_DIRECTION = false; + if ( + this._forceIrradianceInFragment || + this.realTimeFiltering || + this._twoSidedLighting || + engine.getCaps().maxVaryingVectors <= 8 || + this._baseDiffuseRoughnessTexture + ) { + defines.USESPHERICALINVERTEX = false; + } else { + defines.USESPHERICALINVERTEX = true; + } + } + } + } else { + defines.REFLECTION = false; + defines.REFLECTIONMAP_3D = false; + defines.REFLECTIONMAP_SPHERICAL = false; + defines.REFLECTIONMAP_PLANAR = false; + defines.REFLECTIONMAP_CUBIC = false; + defines.USE_LOCAL_REFLECTIONMAP_CUBIC = false; + defines.REFLECTIONMAP_PROJECTION = false; + defines.REFLECTIONMAP_SKYBOX = false; + defines.REFLECTIONMAP_EXPLICIT = false; + defines.REFLECTIONMAP_EQUIRECTANGULAR = false; + defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; + defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; + defines.INVERTCUBICMAP = false; + defines.USESPHERICALFROMREFLECTIONMAP = false; + defines.USEIRRADIANCEMAP = false; + defines.USE_IRRADIANCE_DOMINANT_DIRECTION = false; + defines.USESPHERICALINVERTEX = false; + defines.REFLECTIONMAP_OPPOSITEZ = false; + defines.LODINREFLECTIONALPHA = false; + defines.GAMMAREFLECTION = false; + defines.RGBDREFLECTION = false; + defines.LINEARSPECULARREFLECTION = false; + } + + if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { + PrepareDefinesForMergedUV(this._lightmapTexture, defines, "LIGHTMAP"); + defines.USELIGHTMAPASSHADOWMAP = this._useLightmapAsShadowmap; + defines.GAMMALIGHTMAP = this._lightmapTexture.gammaSpace; + defines.RGBDLIGHTMAP = this._lightmapTexture.isRGBD; + } else { + defines.LIGHTMAP = false; + } + + if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { + PrepareDefinesForMergedUV(this._emissiveTexture, defines, "EMISSIVE"); + defines.GAMMAEMISSIVE = this._emissiveTexture.gammaSpace; + } else { + defines.EMISSIVE = false; + } + + if (MaterialFlags.SpecularTextureEnabled) { + if (this._metallicTexture) { + PrepareDefinesForMergedUV(this._metallicTexture, defines, "REFLECTIVITY"); + defines.ROUGHNESSSTOREINMETALMAPALPHA = this._useRoughnessFromMetallicTextureAlpha; + defines.ROUGHNESSSTOREINMETALMAPGREEN = !this._useRoughnessFromMetallicTextureAlpha && this._useRoughnessFromMetallicTextureGreen; + defines.METALLNESSSTOREINMETALMAPBLUE = this._useMetallnessFromMetallicTextureBlue; + defines.AOSTOREINMETALMAPRED = this._useAmbientOcclusionFromMetallicTextureRed; + defines.REFLECTIVITY_GAMMA = false; + } else if (this._reflectivityTexture) { + PrepareDefinesForMergedUV(this._reflectivityTexture, defines, "REFLECTIVITY"); + defines.MICROSURFACEFROMREFLECTIVITYMAP = this._useMicroSurfaceFromReflectivityMapAlpha; + defines.MICROSURFACEAUTOMATIC = this._useAutoMicroSurfaceFromReflectivityMap; + defines.REFLECTIVITY_GAMMA = this._reflectivityTexture.gammaSpace; + } else { + defines.REFLECTIVITY = false; + } + + if (this._metallicReflectanceTexture || this._reflectanceTexture) { + defines.METALLIC_REFLECTANCE_USE_ALPHA_ONLY = this._useOnlyMetallicFromMetallicReflectanceTexture; + if (this._metallicReflectanceTexture) { + PrepareDefinesForMergedUV(this._metallicReflectanceTexture, defines, "METALLIC_REFLECTANCE"); + defines.METALLIC_REFLECTANCE_GAMMA = this._metallicReflectanceTexture.gammaSpace; + } else { + defines.METALLIC_REFLECTANCE = false; + } + if ( + this._reflectanceTexture && + (!this._metallicReflectanceTexture || (this._metallicReflectanceTexture && this._useOnlyMetallicFromMetallicReflectanceTexture)) + ) { + PrepareDefinesForMergedUV(this._reflectanceTexture, defines, "REFLECTANCE"); + defines.REFLECTANCE_GAMMA = this._reflectanceTexture.gammaSpace; + } else { + defines.REFLECTANCE = false; + } + } else { + defines.METALLIC_REFLECTANCE = false; + defines.REFLECTANCE = false; + } + + if (this._microSurfaceTexture) { + PrepareDefinesForMergedUV(this._microSurfaceTexture, defines, "MICROSURFACEMAP"); + } else { + defines.MICROSURFACEMAP = false; + } + } else { + defines.REFLECTIVITY = false; + defines.MICROSURFACEMAP = false; + } + + if (engine.getCaps().standardDerivatives && this._bumpTexture && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { + PrepareDefinesForMergedUV(this._bumpTexture, defines, "BUMP"); + + if (this._useParallax && this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { + defines.PARALLAX = true; + defines.PARALLAX_RHS = scene.useRightHandedSystem; + defines.PARALLAXOCCLUSION = !!this._useParallaxOcclusion; + } else { + defines.PARALLAX = false; + } + + defines.OBJECTSPACE_NORMALMAP = this._useObjectSpaceNormalMap; + } else { + defines.BUMP = false; + defines.PARALLAX = false; + defines.PARALLAX_RHS = false; + defines.PARALLAXOCCLUSION = false; + defines.OBJECTSPACE_NORMALMAP = false; + } + + if (this._environmentBRDFTexture && MaterialFlags.ReflectionTextureEnabled) { + defines.ENVIRONMENTBRDF = true; + defines.ENVIRONMENTBRDF_RGBD = this._environmentBRDFTexture.isRGBD; + } else { + defines.ENVIRONMENTBRDF = false; + defines.ENVIRONMENTBRDF_RGBD = false; + } + + if (this._shouldUseAlphaFromAlbedoTexture()) { + defines.ALPHAFROMALBEDO = true; + } else { + defines.ALPHAFROMALBEDO = false; + } + } + + defines.SPECULAROVERALPHA = this._useSpecularOverAlpha; + + if (this._lightFalloff === PBRBaseMaterial.LIGHTFALLOFF_STANDARD) { + defines.USEPHYSICALLIGHTFALLOFF = false; + defines.USEGLTFLIGHTFALLOFF = false; + } else if (this._lightFalloff === PBRBaseMaterial.LIGHTFALLOFF_GLTF) { + defines.USEPHYSICALLIGHTFALLOFF = false; + defines.USEGLTFLIGHTFALLOFF = true; + } else { + defines.USEPHYSICALLIGHTFALLOFF = true; + defines.USEGLTFLIGHTFALLOFF = false; + } + + defines.RADIANCEOVERALPHA = this._useRadianceOverAlpha; + + if (!this.backFaceCulling && this._twoSidedLighting) { + defines.TWOSIDEDLIGHTING = true; + } else { + defines.TWOSIDEDLIGHTING = false; + } + + // We need it to not invert normals in two sided lighting mode (based on the winding of the face) + defines.MIRRORED = !!scene._mirroredCameraPosition; + + defines.SPECULARAA = engine.getCaps().standardDerivatives && this._enableSpecularAntiAliasing; + } + + if (defines._areTexturesDirty || defines._areMiscDirty) { + defines.ALPHATESTVALUE = `${this._alphaCutOff}${this._alphaCutOff % 1 === 0 ? "." : ""}`; + defines.PREMULTIPLYALPHA = this.alphaMode === Constants.ALPHA_PREMULTIPLIED || this.alphaMode === Constants.ALPHA_PREMULTIPLIED_PORTERDUFF; + defines.ALPHABLEND = this.needAlphaBlendingForMesh(mesh); + defines.ALPHAFRESNEL = this._useAlphaFresnel || this._useLinearAlphaFresnel; + defines.LINEARALPHAFRESNEL = this._useLinearAlphaFresnel; + } + + if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) { + this._imageProcessingConfiguration.prepareDefines(defines); + } + + defines.FORCENORMALFORWARD = this._forceNormalForward; + + defines.RADIANCEOCCLUSION = this._useRadianceOcclusion; + + defines.HORIZONOCCLUSION = this._useHorizonOcclusion; + + // Misc. + if (defines._areMiscDirty) { + PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, this.needAlphaTestingForMesh(mesh), defines, false); + defines.UNLIT = this._unlit2 || ((this.pointsCloud || this.wireframe) && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)); + defines.DEBUGMODE = this._debugMode2; + } + + // Values that need to be evaluated on every frame + PrepareDefinesForFrameBoundValues(scene, engine, this, defines, useInstances ? true : false, useClipPlane, useThinInstances); + + // External config + this._eventInfo.defines = defines; + this._eventInfo.mesh = mesh; + this._callbackPluginEventPrepareDefinesBeforeAttributes(this._eventInfo); + + // Attribs + PrepareDefinesForAttributes(mesh, defines, true, true, true, this._transparencyMode !== PBRBaseMaterial.PBRMATERIAL_OPAQUE); + + // External config + this._callbackPluginEventPrepareDefines(this._eventInfo); + } + + /** + * Returns the texture used for reflections. + * @returns - Reflection texture if present. Otherwise, returns the environment texture. + */ + private _getReflectionTexture2(): Nullable { + if (this._reflectionTexture) { + return this._reflectionTexture; + } + + return this.getScene().environmentTexture; + } + + private _shadersLoaded2 = false; + + /** + * If set to true, no lighting calculations will be applied. + */ + private _unlit2 = false; + + private _debugMode2 = 0; + + private _breakShaderLoadedCheck2 = false; +} + +RegisterClass("BABYLON.PBRMaterial2", PBRMaterial2); diff --git a/packages/dev/core/src/Shaders/pbr2.fragment.fx b/packages/dev/core/src/Shaders/pbr2.fragment.fx new file mode 100644 index 00000000000..ac621aa07b2 --- /dev/null +++ b/packages/dev/core/src/Shaders/pbr2.fragment.fx @@ -0,0 +1,692 @@ +#define PBR_FRAGMENT_SHADER + +#define CUSTOM_FRAGMENT_EXTENSION + +#if defined(BUMP) || !defined(NORMAL) || defined(FORCENORMALFORWARD) || defined(SPECULARAA) || defined(CLEARCOAT_BUMP) || defined(ANISOTROPIC) +#extension GL_OES_standard_derivatives : enable +#endif + +#ifdef LODBASEDMICROSFURACE +#extension GL_EXT_shader_texture_lod : enable +#endif + +#define CUSTOM_FRAGMENT_BEGIN + +#ifdef LOGARITHMICDEPTH +#extension GL_EXT_frag_depth : enable +#endif + +#include[SCENE_MRT_COUNT] + +precision highp float; +#include + +// Forces linear space for image processing +#ifndef FROMLINEARSPACE + #define FROMLINEARSPACE +#endif + +// Declaration +#include<__decl__pbrFragment> + +#include +#include<__decl__lightFragment>[0..maxSimultaneousLights] +#include +#include +#include +#include +#include + +// Helper Functions +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef REFLECTION + #include +#endif + +#define CUSTOM_FRAGMENT_DEFINITIONS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// _____________________________ MAIN FUNCTION ____________________________ +void main(void) { + + #define CUSTOM_FRAGMENT_MAIN_BEGIN + + #include + + // _____________________________ Geometry Information ____________________________ + #include + + #include + + #include + + // _____________________________ Albedo & Opacity ______________________________ + albedoOpacityOutParams albedoOpacityOut; + +#ifdef ALBEDO + vec4 albedoTexture = texture2D(albedoSampler, vAlbedoUV + uvOffset); +#endif + +#ifdef BASE_WEIGHT + vec4 baseWeightTexture = texture2D(baseWeightSampler, vBaseWeightUV + uvOffset); +#endif + +#ifdef OPACITY + vec4 opacityMap = texture2D(opacitySampler, vOpacityUV + uvOffset); +#endif + +#ifdef DECAL + vec4 decalColor = texture2D(decalSampler, vDecalUV + uvOffset); +#endif + + albedoOpacityOut = albedoOpacityBlock( + vAlbedoColor + #ifdef ALBEDO + , albedoTexture + , vAlbedoInfos + #endif + , baseWeight + #ifdef BASE_WEIGHT + , baseWeightTexture + , vBaseWeightInfos + #endif + #ifdef OPACITY + , opacityMap + , vOpacityInfos + #endif + #ifdef DETAIL + , detailColor + , vDetailInfos + #endif + #ifdef DECAL + , decalColor + , vDecalInfos + #endif + ); + + vec3 surfaceAlbedo = albedoOpacityOut.surfaceAlbedo; + float alpha = albedoOpacityOut.alpha; + + #define CUSTOM_FRAGMENT_UPDATE_ALPHA + + #include + + #define CUSTOM_FRAGMENT_BEFORE_LIGHTS + + // _____________________________ AO _______________________________ + ambientOcclusionOutParams aoOut; + +#ifdef AMBIENT + vec3 ambientOcclusionColorMap = texture2D(ambientSampler, vAmbientUV + uvOffset).rgb; +#endif + + aoOut = ambientOcclusionBlock( + #ifdef AMBIENT + ambientOcclusionColorMap, + vAmbientInfos + #endif + ); + + #include + +#ifdef UNLIT + vec3 diffuseBase = vec3(1., 1., 1.); +#else // !UNLIT + + // _____________________________ Reflectivity _______________________________ + vec3 baseColor = surfaceAlbedo; + + reflectivityOutParams reflectivityOut; + +#if defined(REFLECTIVITY) + vec4 surfaceMetallicOrReflectivityColorMap = texture2D(reflectivitySampler, vReflectivityUV + uvOffset); + vec4 baseReflectivity = surfaceMetallicOrReflectivityColorMap; + #ifndef METALLICWORKFLOW + #ifdef REFLECTIVITY_GAMMA + surfaceMetallicOrReflectivityColorMap = toLinearSpace(surfaceMetallicOrReflectivityColorMap); + #endif + surfaceMetallicOrReflectivityColorMap.rgb *= vReflectivityInfos.y; + #endif +#endif + +#if defined(MICROSURFACEMAP) + vec4 microSurfaceTexel = texture2D(microSurfaceSampler, vMicroSurfaceSamplerUV + uvOffset) * vMicroSurfaceSamplerInfos.y; +#endif + +#ifdef METALLICWORKFLOW + vec4 metallicReflectanceFactors = vMetallicReflectanceFactors; + #ifdef REFLECTANCE + vec4 reflectanceFactorsMap = texture2D(reflectanceSampler, vReflectanceUV + uvOffset); + #ifdef REFLECTANCE_GAMMA + reflectanceFactorsMap = toLinearSpace(reflectanceFactorsMap); + #endif + + metallicReflectanceFactors.rgb *= reflectanceFactorsMap.rgb; + #endif + #ifdef METALLIC_REFLECTANCE + vec4 metallicReflectanceFactorsMap = texture2D(metallicReflectanceSampler, vMetallicReflectanceUV + uvOffset); + #ifdef METALLIC_REFLECTANCE_GAMMA + metallicReflectanceFactorsMap = toLinearSpace(metallicReflectanceFactorsMap); + #endif + + #ifndef METALLIC_REFLECTANCE_USE_ALPHA_ONLY + metallicReflectanceFactors.rgb *= metallicReflectanceFactorsMap.rgb; + #endif + metallicReflectanceFactors.a *= metallicReflectanceFactorsMap.a; + #endif +#endif + +#ifdef BASE_DIFFUSE_ROUGHNESS + float baseDiffuseRoughnessTexture = texture2D(baseDiffuseRoughnessSampler, vBaseDiffuseRoughnessUV + uvOffset).r; +#endif + + reflectivityOut = reflectivityBlock( + vReflectivityColor + #ifdef METALLICWORKFLOW + , surfaceAlbedo + , metallicReflectanceFactors + #endif + , baseDiffuseRoughness + #ifdef BASE_DIFFUSE_ROUGHNESS + , baseDiffuseRoughnessTexture + , vBaseDiffuseRoughnessInfos + #endif + #ifdef REFLECTIVITY + , vReflectivityInfos + , surfaceMetallicOrReflectivityColorMap + #endif + #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED) + , aoOut.ambientOcclusionColor + #endif + #ifdef MICROSURFACEMAP + , microSurfaceTexel + #endif + #ifdef DETAIL + , detailColor + , vDetailInfos + #endif + ); + + float microSurface = reflectivityOut.microSurface; + float roughness = reflectivityOut.roughness; + float diffuseRoughness = reflectivityOut.diffuseRoughness; + + #ifdef METALLICWORKFLOW + surfaceAlbedo = reflectivityOut.surfaceAlbedo; + #endif + #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED) + aoOut.ambientOcclusionColor = reflectivityOut.ambientOcclusionColor; + #endif + + // _____________________________ Alpha Fresnel ___________________________________ + #ifdef ALPHAFRESNEL + #if defined(ALPHATEST) || defined(ALPHABLEND) + alphaFresnelOutParams alphaFresnelOut; + + alphaFresnelOut = alphaFresnelBlock( + normalW, + viewDirectionW, + alpha, + microSurface + ); + + alpha = alphaFresnelOut.alpha; + #endif + #endif + + // _____________________________ Compute Geometry info _________________________________ + #include + + // _____________________________ Anisotropy _______________________________________ + #ifdef ANISOTROPIC + anisotropicOutParams anisotropicOut; + + #ifdef ANISOTROPIC_TEXTURE + vec3 anisotropyMapData = texture2D(anisotropySampler, vAnisotropyUV + uvOffset).rgb * vAnisotropyInfos.y; + #endif + + anisotropicOut = anisotropicBlock( + vAnisotropy, + roughness, + #ifdef ANISOTROPIC_TEXTURE + anisotropyMapData, + #endif + TBN, + normalW, + viewDirectionW + ); + #endif + + // _____________________________ Reflection Info _______________________________________ + #ifdef REFLECTION + reflectionOutParams reflectionOut; + + #ifndef USE_CUSTOM_REFLECTION + reflectionOut = reflectionBlock( + vPositionW + , normalW + , alphaG + , vReflectionMicrosurfaceInfos + , vReflectionInfos + , vReflectionColor + #ifdef ANISOTROPIC + , anisotropicOut + #endif + #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX) + , NdotVUnclamped + #endif + #ifdef LINEARSPECULARREFLECTION + , roughness + #endif + , reflectionSampler + #if defined(NORMAL) && defined(USESPHERICALINVERTEX) + , vEnvironmentIrradiance + #endif + #if (defined(USESPHERICALFROMREFLECTIONMAP) && (!defined(NORMAL) || !defined(USESPHERICALINVERTEX))) || (defined(USEIRRADIANCEMAP) && defined(REFLECTIONMAP_3D)) + , reflectionMatrix + #endif + #ifdef USEIRRADIANCEMAP + , irradianceSampler + #ifdef USE_IRRADIANCE_DOMINANT_DIRECTION + , vReflectionDominantDirection + #endif + #endif + #ifndef LODBASEDMICROSFURACE + , reflectionSamplerLow + , reflectionSamplerHigh + #endif + #ifdef REALTIME_FILTERING + , vReflectionFilteringInfo + #ifdef IBL_CDF_FILTERING + , icdfSampler + #endif + #endif + , viewDirectionW + , diffuseRoughness + , baseColor + ); + #else + #define CUSTOM_REFLECTION + #endif + #endif + + // ___________________ Compute Reflectance aka R0 F0 info _________________________ + #include + + // ________________________________ Sheen ______________________________ + #ifdef SHEEN + sheenOutParams sheenOut; + + #ifdef SHEEN_TEXTURE + vec4 sheenMapData = texture2D(sheenSampler, vSheenUV + uvOffset); + #endif + #if defined(SHEEN_ROUGHNESS) && defined(SHEEN_TEXTURE_ROUGHNESS) && !defined(SHEEN_USE_ROUGHNESS_FROM_MAINTEXTURE) + vec4 sheenMapRoughnessData = texture2D(sheenRoughnessSampler, vSheenRoughnessUV + uvOffset) * vSheenInfos.w; + #endif + + sheenOut = sheenBlock( + vSheenColor + #ifdef SHEEN_ROUGHNESS + , vSheenRoughness + #if defined(SHEEN_TEXTURE_ROUGHNESS) && !defined(SHEEN_USE_ROUGHNESS_FROM_MAINTEXTURE) + , sheenMapRoughnessData + #endif + #endif + , roughness + #ifdef SHEEN_TEXTURE + , sheenMapData + , vSheenInfos.y + #endif + , reflectanceF0 + #ifdef SHEEN_LINKWITHALBEDO + , baseColor + , surfaceAlbedo + #endif + #ifdef ENVIRONMENTBRDF + , NdotV + , environmentBrdf + #endif + #if defined(REFLECTION) && defined(ENVIRONMENTBRDF) + , AARoughnessFactors + , vReflectionMicrosurfaceInfos + , vReflectionInfos + , vReflectionColor + , vLightingIntensity + , reflectionSampler + , reflectionOut.reflectionCoords + , NdotVUnclamped + #ifndef LODBASEDMICROSFURACE + , reflectionSamplerLow + , reflectionSamplerHigh + #endif + #ifdef REALTIME_FILTERING + , vReflectionFilteringInfo + #endif + #if !defined(REFLECTIONMAP_SKYBOX) && defined(RADIANCEOCCLUSION) + , seo + #endif + #if !defined(REFLECTIONMAP_SKYBOX) && defined(HORIZONOCCLUSION) && defined(BUMP) && defined(REFLECTIONMAP_3D) + , eho + #endif + #endif + ); + + #ifdef SHEEN_LINKWITHALBEDO + surfaceAlbedo = sheenOut.surfaceAlbedo; + #endif + #endif + + // _____________ Shared Iridescence and Clear Coat data _________________ + #ifdef CLEARCOAT + #ifdef CLEARCOAT_TEXTURE + vec2 clearCoatMapData = texture2D(clearCoatSampler, vClearCoatUV + uvOffset).rg * vClearCoatInfos.y; + #endif + #endif + + // _____________________________ Iridescence ____________________________ + #ifdef IRIDESCENCE + iridescenceOutParams iridescenceOut; + + #ifdef IRIDESCENCE_TEXTURE + vec2 iridescenceMapData = texture2D(iridescenceSampler, vIridescenceUV + uvOffset).rg * vIridescenceInfos.y; + #endif + #ifdef IRIDESCENCE_THICKNESS_TEXTURE + vec2 iridescenceThicknessMapData = texture2D(iridescenceThicknessSampler, vIridescenceThicknessUV + uvOffset).rg * vIridescenceInfos.w; + #endif + + iridescenceOut = iridescenceBlock( + vIridescenceParams + , NdotV + , specularEnvironmentR0 + #ifdef IRIDESCENCE_TEXTURE + , iridescenceMapData + #endif + #ifdef IRIDESCENCE_THICKNESS_TEXTURE + , iridescenceThicknessMapData + #endif + #ifdef CLEARCOAT + , NdotVUnclamped + , vClearCoatParams + #ifdef CLEARCOAT_TEXTURE + , clearCoatMapData + #endif + #endif + ); + + float iridescenceIntensity = iridescenceOut.iridescenceIntensity; + specularEnvironmentR0 = iridescenceOut.specularEnvironmentR0; + #endif + + // _____________________________ Clear Coat ____________________________ + clearcoatOutParams clearcoatOut; + + #ifdef CLEARCOAT + #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) && !defined(CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE) + vec4 clearCoatMapRoughnessData = texture2D(clearCoatRoughnessSampler, vClearCoatRoughnessUV + uvOffset) * vClearCoatInfos.w; + #endif + + #if defined(CLEARCOAT_TINT) && defined(CLEARCOAT_TINT_TEXTURE) + vec4 clearCoatTintMapData = texture2D(clearCoatTintSampler, vClearCoatTintUV + uvOffset); + #endif + + #ifdef CLEARCOAT_BUMP + vec4 clearCoatBumpMapData = texture2D(clearCoatBumpSampler, vClearCoatBumpUV + uvOffset); + #endif + + clearcoatOut = clearcoatBlock( + vPositionW + , geometricNormalW + , viewDirectionW + , vClearCoatParams + #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) && !defined(CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE) + , clearCoatMapRoughnessData + #endif + , specularEnvironmentR0 + #ifdef CLEARCOAT_TEXTURE + , clearCoatMapData + #endif + #ifdef CLEARCOAT_TINT + , vClearCoatTintParams + , clearCoatColorAtDistance + , vClearCoatRefractionParams + #ifdef CLEARCOAT_TINT_TEXTURE + , clearCoatTintMapData + #endif + #endif + #ifdef CLEARCOAT_BUMP + , vClearCoatBumpInfos + , clearCoatBumpMapData + , vClearCoatBumpUV + #if defined(TANGENT) && defined(NORMAL) + , vTBN + #else + , vClearCoatTangentSpaceParams + #endif + #ifdef OBJECTSPACE_NORMALMAP + , normalMatrix + #endif + #endif + #if defined(FORCENORMALFORWARD) && defined(NORMAL) + , faceNormal + #endif + #ifdef REFLECTION + , vReflectionMicrosurfaceInfos + , vReflectionInfos + , vReflectionColor + , vLightingIntensity + , reflectionSampler + #ifndef LODBASEDMICROSFURACE + , reflectionSamplerLow + , reflectionSamplerHigh + #endif + #ifdef REALTIME_FILTERING + , vReflectionFilteringInfo + #endif + #endif + #if defined(CLEARCOAT_BUMP) || defined(TWOSIDEDLIGHTING) + , (gl_FrontFacing ? 1. : -1.) + #endif + ); + #else + clearcoatOut.specularEnvironmentR0 = specularEnvironmentR0; + #endif + + // _________________________ Specular Environment Reflectance __________________________ + #include + + // ___________________________________ SubSurface ______________________________________ + subSurfaceOutParams subSurfaceOut; + + #ifdef SUBSURFACE + #ifdef SS_THICKNESSANDMASK_TEXTURE + vec4 thicknessMap = texture2D(thicknessSampler, vThicknessUV + uvOffset); + #endif + + #ifdef SS_REFRACTIONINTENSITY_TEXTURE + vec4 refractionIntensityMap = texture2D(refractionIntensitySampler, vRefractionIntensityUV + uvOffset); + #endif + + #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE + vec4 translucencyIntensityMap = texture2D(translucencyIntensitySampler, vTranslucencyIntensityUV + uvOffset); + #endif + + #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE + vec4 translucencyColorMap = texture2D(translucencyColorSampler, vTranslucencyColorUV + uvOffset); + #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE_GAMMA + translucencyColorMap = toLinearSpace(translucencyColorMap); + #endif + #endif + + #ifdef LEGACY_SPECULAR_ENERGY_CONSERVATION + vec3 vSpecularEnvironmentReflectance = vec3(max(colorSpecularEnvironmentReflectance.r, max(colorSpecularEnvironmentReflectance.g, colorSpecularEnvironmentReflectance.b))); + #endif + + subSurfaceOut = subSurfaceBlock( + vSubSurfaceIntensity + , vThicknessParam + , vTintColor + , normalW + #ifdef LEGACY_SPECULAR_ENERGY_CONSERVATION + , vSpecularEnvironmentReflectance + #else + , baseSpecularEnvironmentReflectance + #endif + #ifdef SS_THICKNESSANDMASK_TEXTURE + , thicknessMap + #endif + #ifdef SS_REFRACTIONINTENSITY_TEXTURE + , refractionIntensityMap + #endif + #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE + , translucencyIntensityMap + #endif + #ifdef REFLECTION + #ifdef SS_TRANSLUCENCY + , reflectionMatrix + #ifdef USESPHERICALFROMREFLECTIONMAP + #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX) + , reflectionOut.irradianceVector + #endif + #if defined(REALTIME_FILTERING) + , reflectionSampler + , vReflectionFilteringInfo + #ifdef IBL_CDF_FILTERING + , icdfSampler + #endif + #endif + #endif + #ifdef USEIRRADIANCEMAP + , irradianceSampler + #endif + #endif + #endif + #if defined(SS_REFRACTION) || defined(SS_TRANSLUCENCY) + , surfaceAlbedo + #endif + #ifdef SS_REFRACTION + , vPositionW + , viewDirectionW + , view + , vRefractionInfos + , refractionMatrix + , vRefractionMicrosurfaceInfos + , vLightingIntensity + #ifdef SS_LINKREFRACTIONTOTRANSPARENCY + , alpha + #endif + #ifdef SS_LODINREFRACTIONALPHA + , NdotVUnclamped + #endif + #ifdef SS_LINEARSPECULARREFRACTION + , roughness + #endif + , alphaG + , refractionSampler + #ifndef LODBASEDMICROSFURACE + , refractionSamplerLow + , refractionSamplerHigh + #endif + #ifdef ANISOTROPIC + , anisotropicOut + #endif + #ifdef REALTIME_FILTERING + , vRefractionFilteringInfo + #endif + #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC + , vRefractionPosition + , vRefractionSize + #endif + #ifdef SS_DISPERSION + , dispersion + #endif + #endif + #ifdef SS_TRANSLUCENCY + , vDiffusionDistance + , vTranslucencyColor + #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE + , translucencyColorMap + #endif + #endif + ); + + #ifdef SS_REFRACTION + surfaceAlbedo = subSurfaceOut.surfaceAlbedo; + #ifdef SS_LINKREFRACTIONTOTRANSPARENCY + alpha = subSurfaceOut.alpha; + #endif + #endif + #else + subSurfaceOut.specularEnvironmentReflectance = colorSpecularEnvironmentReflectance; + #endif + + // _____________________________ Direct Lighting Info __________________________________ + #include + + #include[0..maxSimultaneousLights] + + // _____________________________ Compute Final Lit Components ________________________ + #include +#endif // !UNLIT + + #include + + #define CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION + + #include + + #include + #include(color, finalColor) + #include + + #define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR + +#ifdef PREPASS + #include +#endif + +#if !defined(PREPASS) || defined(WEBGL2) + gl_FragColor = finalColor; +#endif + + #include + +#if ORDER_INDEPENDENT_TRANSPARENCY + if (fragDepth == nearestDepth) { + frontColor.rgb += finalColor.rgb * finalColor.a * alphaMultiplier; + // Cancels the 1 - a initial value operation + frontColor.a = 1.0 - alphaMultiplier * (1.0 - finalColor.a); + } else { + backColor += finalColor; + } +#endif + + #include + + #define CUSTOM_FRAGMENT_MAIN_END + +} diff --git a/packages/dev/core/src/Shaders/pbr2.vertex.fx b/packages/dev/core/src/Shaders/pbr2.vertex.fx new file mode 100644 index 00000000000..778fa33de08 --- /dev/null +++ b/packages/dev/core/src/Shaders/pbr2.vertex.fx @@ -0,0 +1,312 @@ +#define PBR_VERTEX_SHADER + +#define CUSTOM_VERTEX_EXTENSION + +precision highp float; + +#include<__decl__pbrVertex> + +#define CUSTOM_VERTEX_BEGIN + +// Attributes +attribute vec3 position; +#ifdef NORMAL +attribute vec3 normal; +#endif +#ifdef TANGENT +attribute vec4 tangent; +#endif +#ifdef UV1 +attribute vec2 uv; +#endif +#include[2..7] +#include[1..7] +#ifdef VERTEXCOLOR +attribute vec4 color; +#endif + +#include +#include +#include +#include + +#include +#include + +#include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,Albedo) +#include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight) +#include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness) +#include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail) +#include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient) +#include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity) +#include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive) +#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap) +#include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity) +#include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler) +#include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance) +#include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance) +#include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump) +#include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal) + +#ifdef CLEARCOAT + #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat) + #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness) + #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump) + #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint) +#endif + +#ifdef IRIDESCENCE + #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence) + #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness) +#endif + +#ifdef SHEEN + #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen) + #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness) +#endif + +#ifdef ANISOTROPIC + #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy) +#endif + +#ifdef SUBSURFACE + #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness) + #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity) + #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity) + #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor) +#endif + +// Output +varying vec3 vPositionW; +#if DEBUGMODE > 0 + varying vec4 vClipSpacePosition; +#endif + +#ifdef NORMAL + varying vec3 vNormalW; + #if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX) + varying vec3 vEnvironmentIrradiance; + + #include + #endif +#endif + +#if defined(VERTEXCOLOR) || defined(INSTANCESCOLOR) && defined(INSTANCES) +varying vec4 vColor; +#endif + +#include +#include +#include +#include<__decl__lightVxFragment>[0..maxSimultaneousLights] + +#include +#include[0..maxSimultaneousMorphTargets] + +#ifdef REFLECTIONMAP_SKYBOX +varying vec3 vPositionUVW; +#endif + +#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED) +varying vec3 vDirectionW; +#endif + +#include +#define CUSTOM_VERTEX_DEFINITIONS + +void main(void) { + + #define CUSTOM_VERTEX_MAIN_BEGIN + + vec3 positionUpdated = position; +#ifdef NORMAL + vec3 normalUpdated = normal; +#endif +#ifdef TANGENT + vec4 tangentUpdated = tangent; +#endif +#ifdef UV1 + vec2 uvUpdated = uv; +#endif +#ifdef UV2 + vec2 uv2Updated = uv2; +#endif +#ifdef VERTEXCOLOR + vec4 colorUpdated = color; +#endif + +#include +#include[0..maxSimultaneousMorphTargets] + +#ifdef REFLECTIONMAP_SKYBOX + vPositionUVW = positionUpdated; +#endif + +#define CUSTOM_VERTEX_UPDATE_POSITION + +#define CUSTOM_VERTEX_UPDATE_NORMAL + +#include + +#if defined(PREPASS) && ((defined(PREPASS_VELOCITY) || defined(PREPASS_VELOCITY_LINEAR)) && !defined(BONES_VELOCITY_ENABLED) + // Compute velocity before bones computation + vCurrentPosition = viewProjection * finalWorld * vec4(positionUpdated, 1.0); + vPreviousPosition = previousViewProjection * finalPreviousWorld * vec4(positionUpdated, 1.0); +#endif + +#include +#include + + vec4 worldPos = finalWorld * vec4(positionUpdated, 1.0); + vPositionW = vec3(worldPos); + +#ifdef PREPASS + #include +#endif + +#ifdef NORMAL + mat3 normalWorld = mat3(finalWorld); + + #if defined(INSTANCES) && defined(THIN_INSTANCES) + vNormalW = normalUpdated / vec3(dot(normalWorld[0], normalWorld[0]), dot(normalWorld[1], normalWorld[1]), dot(normalWorld[2], normalWorld[2])); + vNormalW = normalize(normalWorld * vNormalW); + #else + #ifdef NONUNIFORMSCALING + normalWorld = transposeMat3(inverseMat3(normalWorld)); + #endif + + vNormalW = normalize(normalWorld * normalUpdated); + #endif + + #if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX) + #if BASE_DIFFUSE_MODEL != BRDF_DIFFUSE_MODEL_LAMBERT && BASE_DIFFUSE_MODEL != BRDF_DIFFUSE_MODEL_LEGACY + // Bend the normal towards the viewer based on the diffuse roughness + vec3 viewDirectionW = normalize(vEyePosition.xyz - vPositionW); + + #if !defined(NATIVE) && !defined(WEBGPU) + // Next two lines fixes a flickering that occurs on some specific circumstances on MacOS/iOS + // See https://forum.babylonjs.com/t/needdepthprepass-creates-flickering-in-8-6-2/58421/12 + // Note that the variable passed to isnan doesn't matter... + bool bbb = any(isnan(position)); + if (bbb) { } + #endif + + float NdotV = max(dot(vNormalW, viewDirectionW), 0.0); + vec3 roughNormal = mix(vNormalW, viewDirectionW, (0.5 * (1.0 - NdotV)) * baseDiffuseRoughness); + vec3 reflectionVector = vec3(reflectionMatrix * vec4(roughNormal, 0)).xyz; + #else + vec3 reflectionVector = vec3(reflectionMatrix * vec4(vNormalW, 0)).xyz; + #endif + #ifdef REFLECTIONMAP_OPPOSITEZ + reflectionVector.z *= -1.0; + #endif + vEnvironmentIrradiance = computeEnvironmentIrradiance(reflectionVector); + #endif +#endif + +#define CUSTOM_VERTEX_UPDATE_WORLDPOS + +#ifdef MULTIVIEW + if (gl_ViewID_OVR == 0u) { + gl_Position = viewProjection * worldPos; + } else { + gl_Position = viewProjectionR * worldPos; + } +#else + gl_Position = viewProjection * worldPos; +#endif + +#if DEBUGMODE > 0 + vClipSpacePosition = gl_Position; +#endif + +#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED) + vDirectionW = normalize(vec3(finalWorld * vec4(positionUpdated, 0.0))); +#endif + + // Texture coordinates +#ifndef UV1 + vec2 uvUpdated = vec2(0., 0.); +#endif +#ifndef UV2 + vec2 uv2Updated = vec2(0., 0.); +#endif +#ifdef MAINUV1 + vMainUV1 = uvUpdated; +#endif +#ifdef MAINUV2 + vMainUV2 = uv2Updated; +#endif + + #include[3..7] + + #include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,Albedo,_MATRIXNAME_,albedo,_INFONAME_,AlbedoInfos.x) + #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_MATRIXNAME_,baseWeight,_INFONAME_,BaseWeightInfos.x) + #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_MATRIXNAME_,baseDiffuseRoughness,_INFONAME_,BaseDiffuseRoughnessInfos.x) + #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) + #include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_MATRIXNAME_,ambient,_INFONAME_,AmbientInfos.x) + #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_MATRIXNAME_,opacity,_INFONAME_,OpacityInfos.x) + #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_MATRIXNAME_,emissive,_INFONAME_,EmissiveInfos.x) + #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_MATRIXNAME_,lightmap,_INFONAME_,LightmapInfos.x) + #include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity,_MATRIXNAME_,reflectivity,_INFONAME_,ReflectivityInfos.x) + #include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler,_MATRIXNAME_,microSurfaceSampler,_INFONAME_,MicroSurfaceSamplerInfos.x) + #include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance,_MATRIXNAME_,metallicReflectance,_INFONAME_,MetallicReflectanceInfos.x) + #include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance,_MATRIXNAME_,reflectance,_INFONAME_,ReflectanceInfos.x) + #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump,_MATRIXNAME_,bump,_INFONAME_,BumpInfos.x) + #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_MATRIXNAME_,decal,_INFONAME_,DecalInfos.x) + +#ifdef CLEARCOAT + #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat,_MATRIXNAME_,clearCoat,_INFONAME_,ClearCoatInfos.x) + #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness,_MATRIXNAME_,clearCoatRoughness,_INFONAME_,ClearCoatInfos.z) + #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump,_MATRIXNAME_,clearCoatBump,_INFONAME_,ClearCoatBumpInfos.x) + #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint,_MATRIXNAME_,clearCoatTint,_INFONAME_,ClearCoatTintInfos.x) +#endif + +#ifdef IRIDESCENCE + #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence,_MATRIXNAME_,iridescence,_INFONAME_,IridescenceInfos.x) + #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness,_MATRIXNAME_,iridescenceThickness,_INFONAME_,IridescenceInfos.z) +#endif + +#ifdef SHEEN + #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen,_MATRIXNAME_,sheen,_INFONAME_,SheenInfos.x) + #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness,_MATRIXNAME_,sheenRoughness,_INFONAME_,SheenInfos.z) + +#endif + +#ifdef ANISOTROPIC + #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy,_MATRIXNAME_,anisotropy,_INFONAME_,AnisotropyInfos.x) +#endif + +#ifdef SUBSURFACE + #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness,_MATRIXNAME_,thickness,_INFONAME_,ThicknessInfos.x) + #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity,_MATRIXNAME_,refractionIntensity,_INFONAME_,RefractionIntensityInfos.x) + #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity,_MATRIXNAME_,translucencyIntensity,_INFONAME_,TranslucencyIntensityInfos.x) + #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor,_MATRIXNAME_,translucencyColor,_INFONAME_,TranslucencyColorInfos.x) +#endif + + // TBN +#include + + // Clip plane +#include + + // Fog +#include + + // Shadows +#include[0..maxSimultaneousLights] + + // Vertex color +#include + + // Point size +#if defined(POINTSIZE) && !defined(WEBGPU) + gl_PointSize = pointSize; +#endif + + // Log. depth +#include + +#define CUSTOM_VERTEX_MAIN_END + +} diff --git a/packages/dev/core/src/ShadersWGSL/pbr2.fragment.fx b/packages/dev/core/src/ShadersWGSL/pbr2.fragment.fx new file mode 100644 index 00000000000..91bae999b44 --- /dev/null +++ b/packages/dev/core/src/ShadersWGSL/pbr2.fragment.fx @@ -0,0 +1,688 @@ +#define PBR_FRAGMENT_SHADER + +#define CUSTOM_FRAGMENT_BEGIN + +#include[SCENE_MRT_COUNT] +#include + +// Forces linear space for image processing +#ifndef FROMLINEARSPACE + #define FROMLINEARSPACE +#endif + +// Declaration +#include + +#include +#include[0..maxSimultaneousLights] +#include +#include +#include +#include +#include + +// Helper Functions +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef REFLECTION + #include +#endif + +#define CUSTOM_FRAGMENT_DEFINITIONS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// _____________________________ MAIN FUNCTION ____________________________ +@fragment +fn main(input: FragmentInputs) -> FragmentOutputs { + + #define CUSTOM_FRAGMENT_MAIN_BEGIN + + #include + + // _____________________________ Geometry Information ____________________________ + #include + + #include + + #include + + // _____________________________ Albedo & Opacity ______________________________ + var albedoOpacityOut: albedoOpacityOutParams; + +#ifdef ALBEDO + var albedoTexture: vec4f = textureSample(albedoSampler, albedoSamplerSampler, fragmentInputs.vAlbedoUV + uvOffset); +#endif + +#ifdef BASE_WEIGHT + var baseWeightTexture: vec4f = textureSample(baseWeightSampler, baseWeightSamplerSampler, fragmentInputs.vBaseWeightUV + uvOffset); +#endif + +#ifdef OPACITY + var opacityMap: vec4f = textureSample(opacitySampler, opacitySamplerSampler, fragmentInputs.vOpacityUV + uvOffset); +#endif + +#ifdef DECAL + var decalColor: vec4f = textureSample(decalSampler, decalSamplerSampler, fragmentInputs.vDecalUV + uvOffset); +#endif + + albedoOpacityOut = albedoOpacityBlock( + uniforms.vAlbedoColor + #ifdef ALBEDO + , albedoTexture + , uniforms.vAlbedoInfos + #endif + , uniforms.baseWeight + #ifdef BASE_WEIGHT + , baseWeightTexture + , uniforms.vBaseWeightInfos + #endif + #ifdef OPACITY + , opacityMap + , uniforms.vOpacityInfos + #endif + #ifdef DETAIL + , detailColor + , uniforms.vDetailInfos + #endif + #ifdef DECAL + , decalColor + , uniforms.vDecalInfos + #endif + ); + + var surfaceAlbedo: vec3f = albedoOpacityOut.surfaceAlbedo; + var alpha: f32 = albedoOpacityOut.alpha; + + #define CUSTOM_FRAGMENT_UPDATE_ALPHA + + #include + + #define CUSTOM_FRAGMENT_BEFORE_LIGHTS + + // _____________________________ AO _______________________________ + var aoOut: ambientOcclusionOutParams; + +#ifdef AMBIENT + var ambientOcclusionColorMap: vec3f = textureSample(ambientSampler, ambientSamplerSampler, fragmentInputs.vAmbientUV + uvOffset).rgb; +#endif + + aoOut = ambientOcclusionBlock( + #ifdef AMBIENT + ambientOcclusionColorMap, + uniforms.vAmbientInfos + #endif + ); + + #include + +#ifdef UNLIT + var diffuseBase: vec3f = vec3f(1., 1., 1.); +#else + + // _____________________________ Reflectivity _______________________________ + var baseColor: vec3f = surfaceAlbedo; + + var reflectivityOut: reflectivityOutParams; + +#if defined(REFLECTIVITY) + var surfaceMetallicOrReflectivityColorMap: vec4f = textureSample(reflectivitySampler, reflectivitySamplerSampler, fragmentInputs.vReflectivityUV + uvOffset); + var baseReflectivity: vec4f = surfaceMetallicOrReflectivityColorMap; + #ifndef METALLICWORKFLOW + #ifdef REFLECTIVITY_GAMMA + surfaceMetallicOrReflectivityColorMap = toLinearSpaceVec4(surfaceMetallicOrReflectivityColorMap); + #endif + surfaceMetallicOrReflectivityColorMap = vec4f(surfaceMetallicOrReflectivityColorMap.rgb * uniforms.vReflectivityInfos.y, surfaceMetallicOrReflectivityColorMap.a); + #endif +#endif + +#if defined(MICROSURFACEMAP) + var microSurfaceTexel: vec4f = textureSample(microSurfaceSampler, microSurfaceSamplerSampler, fragmentInputs.vMicroSurfaceSamplerUV + uvOffset) * uniforms.vMicroSurfaceSamplerInfos.y; +#endif + +#ifdef BASE_DIFFUSE_ROUGHNESS + var baseDiffuseRoughnessTexture: f32 = textureSample(baseDiffuseRoughnessSampler, baseDiffuseRoughnessSamplerSampler, fragmentInputs.vBaseDiffuseRoughnessUV + uvOffset).x; +#endif + +#ifdef METALLICWORKFLOW + var metallicReflectanceFactors: vec4f = uniforms.vMetallicReflectanceFactors; + #ifdef REFLECTANCE + var reflectanceFactorsMap: vec4f = textureSample(reflectanceSampler, reflectanceSamplerSampler, fragmentInputs.vReflectanceUV + uvOffset); + #ifdef REFLECTANCE_GAMMA + reflectanceFactorsMap = toLinearSpaceVec4(reflectanceFactorsMap); + #endif + + metallicReflectanceFactors = vec4f(metallicReflectanceFactors.rgb * reflectanceFactorsMap.rgb, metallicReflectanceFactors.a); + #endif + #ifdef METALLIC_REFLECTANCE + var metallicReflectanceFactorsMap: vec4f = textureSample(metallicReflectanceSampler, metallicReflectanceSamplerSampler, fragmentInputs.vMetallicReflectanceUV + uvOffset); + #ifdef METALLIC_REFLECTANCE_GAMMA + metallicReflectanceFactorsMap = toLinearSpaceVec4(metallicReflectanceFactorsMap); + #endif + + #ifndef METALLIC_REFLECTANCE_USE_ALPHA_ONLY + metallicReflectanceFactors = vec4f(metallicReflectanceFactors.rgb * metallicReflectanceFactorsMap.rgb, metallicReflectanceFactors.a); + #endif + metallicReflectanceFactors.a *= metallicReflectanceFactorsMap.a; + #endif +#endif + + reflectivityOut = reflectivityBlock( + uniforms.vReflectivityColor + #ifdef METALLICWORKFLOW + , surfaceAlbedo + , metallicReflectanceFactors + #endif + , uniforms.baseDiffuseRoughness + #ifdef BASE_DIFFUSE_ROUGHNESS + , baseDiffuseRoughnessTexture + , uniforms.vBaseDiffuseRoughnessInfos + #endif + #ifdef REFLECTIVITY + , uniforms.vReflectivityInfos + , surfaceMetallicOrReflectivityColorMap + #endif + #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED) + , aoOut.ambientOcclusionColor + #endif + #ifdef MICROSURFACEMAP + , microSurfaceTexel + #endif + #ifdef DETAIL + , detailColor + , uniforms.vDetailInfos + #endif + ); + + var microSurface: f32 = reflectivityOut.microSurface; + var roughness: f32 = reflectivityOut.roughness; + var diffuseRoughness: f32 = reflectivityOut.diffuseRoughness; + + #ifdef METALLICWORKFLOW + surfaceAlbedo = reflectivityOut.surfaceAlbedo; + #endif + #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED) + aoOut.ambientOcclusionColor = reflectivityOut.ambientOcclusionColor; + #endif + + // _____________________________ Alpha Fresnel ___________________________________ + #ifdef ALPHAFRESNEL + #if defined(ALPHATEST) || defined(ALPHABLEND) + var alphaFresnelOut: alphaFresnelOutParams; + + alphaFresnelOut = alphaFresnelBlock( + normalW, + viewDirectionW, + alpha, + microSurface + ); + + alpha = alphaFresnelOut.alpha; + #endif + #endif + + // _____________________________ Compute Geometry info _________________________________ + #include + + // _____________________________ Anisotropy _______________________________________ + #ifdef ANISOTROPIC + var anisotropicOut: anisotropicOutParams; + + #ifdef ANISOTROPIC_TEXTURE + var anisotropyMapData: vec3f = textureSample(anisotropySampler, anisotropySamplerSampler, fragmentInputs.vAnisotropyUV + uvOffset).rgb * uniforms.vAnisotropyInfos.y; + #endif + + anisotropicOut = anisotropicBlock( + uniforms.vAnisotropy, + roughness, + #ifdef ANISOTROPIC_TEXTURE + anisotropyMapData, + #endif + TBN, + normalW, + viewDirectionW + ); + #endif + + // _____________________________ Reflection Info _______________________________________ + #ifdef REFLECTION + var reflectionOut: reflectionOutParams; + + #ifndef USE_CUSTOM_REFLECTION + reflectionOut = reflectionBlock( + fragmentInputs.vPositionW + , normalW + , alphaG + , uniforms.vReflectionMicrosurfaceInfos + , uniforms.vReflectionInfos + , uniforms.vReflectionColor + #ifdef ANISOTROPIC + , anisotropicOut + #endif + #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX) + , NdotVUnclamped + #endif + #ifdef LINEARSPECULARREFLECTION + , roughness + #endif + , reflectionSampler + , reflectionSamplerSampler + #if defined(NORMAL) && defined(USESPHERICALINVERTEX) + , fragmentInputs.vEnvironmentIrradiance + #endif + #if (defined(USESPHERICALFROMREFLECTIONMAP) && (!defined(NORMAL) || !defined(USESPHERICALINVERTEX))) || (defined(USEIRRADIANCEMAP) && defined(REFLECTIONMAP_3D)) + , uniforms.reflectionMatrix + #endif + #ifdef USEIRRADIANCEMAP + , irradianceSampler + , irradianceSamplerSampler + #ifdef USE_IRRADIANCE_DOMINANT_DIRECTION + , uniforms.vReflectionDominantDirection + #endif + #endif + #ifndef LODBASEDMICROSFURACE + , reflectionLowSampler + , reflectionLowSamplerSampler + , reflectionHighSampler + , reflectionHighSamplerSampler + #endif + #ifdef REALTIME_FILTERING + , uniforms.vReflectionFilteringInfo + #ifdef IBL_CDF_FILTERING + , icdfSampler + , icdfSamplerSampler + #endif + #endif + , viewDirectionW + , diffuseRoughness + , surfaceAlbedo + ); + #else + #define CUSTOM_REFLECTION + #endif + #endif + + // ___________________ Compute Reflectance aka R0 F0 info _________________________ + #include + + // ________________________________ Sheen ______________________________ + #ifdef SHEEN + var sheenOut: sheenOutParams; + + #ifdef SHEEN_TEXTURE + var sheenMapData: vec4f = textureSample(sheenSampler, sheenSamplerSampler, fragmentInputs.vSheenUV + uvOffset); + #endif + #if defined(SHEEN_ROUGHNESS) && defined(SHEEN_TEXTURE_ROUGHNESS) && !defined(SHEEN_USE_ROUGHNESS_FROM_MAINTEXTURE) + var sheenMapRoughnessData: vec4f = textureSample(sheenRoughnessSampler, sheenRoughnessSamplerSampler, fragmentInputs.vSheenRoughnessUV + uvOffset) * uniforms.vSheenInfos.w; + #endif + + sheenOut = sheenBlock( + uniforms.vSheenColor + #ifdef SHEEN_ROUGHNESS + , uniforms.vSheenRoughness + #if defined(SHEEN_TEXTURE_ROUGHNESS) && !defined(SHEEN_USE_ROUGHNESS_FROM_MAINTEXTURE) + , sheenMapRoughnessData + #endif + #endif + , roughness + #ifdef SHEEN_TEXTURE + , sheenMapData + , uniforms.vSheenInfos.y + #endif + , reflectanceF0 + #ifdef SHEEN_LINKWITHALBEDO + , baseColor + , surfaceAlbedo + #endif + #ifdef ENVIRONMENTBRDF + , NdotV + , environmentBrdf + #endif + #if defined(REFLECTION) && defined(ENVIRONMENTBRDF) + , AARoughnessFactors + , uniforms.vReflectionMicrosurfaceInfos + , uniforms.vReflectionInfos + , uniforms.vReflectionColor + , uniforms.vLightingIntensity + , reflectionSampler + , reflectionSamplerSampler + , reflectionOut.reflectionCoords + , NdotVUnclamped + #ifndef LODBASEDMICROSFURACE + , reflectionLowSampler + , reflectionLowSamplerSampler + , reflectionHighSampler + , reflectionHighSamplerSampler + #endif + #ifdef REALTIME_FILTERING + , uniforms.vReflectionFilteringInfo + #endif + #if !defined(REFLECTIONMAP_SKYBOX) && defined(RADIANCEOCCLUSION) + , seo + #endif + #if !defined(REFLECTIONMAP_SKYBOX) && defined(HORIZONOCCLUSION) && defined(BUMP) && defined(REFLECTIONMAP_3D) + , eho + #endif + #endif + ); + + #ifdef SHEEN_LINKWITHALBEDO + surfaceAlbedo = sheenOut.surfaceAlbedo; + #endif + #endif + + // _____________ Shared Iridescence and Clear Coat data _________________ + #ifdef CLEARCOAT + #ifdef CLEARCOAT_TEXTURE + var clearCoatMapData: vec2f = textureSample(clearCoatSampler, clearCoatSamplerSampler, fragmentInputs.vClearCoatUV + uvOffset).rg * uniforms.vClearCoatInfos.y; + #endif + #endif + + // _____________________________ Iridescence ____________________________ + #ifdef IRIDESCENCE + var iridescenceOut: iridescenceOutParams; + + #ifdef IRIDESCENCE_TEXTURE + var iridescenceMapData: vec2f = textureSample(iridescenceSampler, iridescenceSamplerSampler, fragmentInputs.vIridescenceUV + uvOffset).rg * uniforms.vIridescenceInfos.y; + #endif + #ifdef IRIDESCENCE_THICKNESS_TEXTURE + var iridescenceThicknessMapData: vec2f = textureSample(iridescenceThicknessSampler, iridescenceThicknessSamplerSampler, fragmentInputs.vIridescenceThicknessUV + uvOffset).rg * uniforms.vIridescenceInfos.w; + #endif + + iridescenceOut = iridescenceBlock( + uniforms.vIridescenceParams + , NdotV + , specularEnvironmentR0 + #ifdef IRIDESCENCE_TEXTURE + , iridescenceMapData + #endif + #ifdef IRIDESCENCE_THICKNESS_TEXTURE + , iridescenceThicknessMapData + #endif + #ifdef CLEARCOAT + , NdotVUnclamped + , uniforms.vClearCoatParams + #ifdef CLEARCOAT_TEXTURE + , clearCoatMapData + #endif + #endif + ); + + var iridescenceIntensity: f32 = iridescenceOut.iridescenceIntensity; + specularEnvironmentR0 = iridescenceOut.specularEnvironmentR0; + #endif + + // _____________________________ Clear Coat ____________________________ + var clearcoatOut: clearcoatOutParams; + + #ifdef CLEARCOAT + #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) && !defined(CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE) + var clearCoatMapRoughnessData: vec4f = textureSample(clearCoatRoughnessSampler, clearCoatRoughnessSamplerSampler, fragmentInputs.vClearCoatRoughnessUV + uvOffset) * uniforms.vClearCoatInfos.w; + #endif + + #if defined(CLEARCOAT_TINT) && defined(CLEARCOAT_TINT_TEXTURE) + var clearCoatTintMapData: vec4f = textureSample(clearCoatTintSampler, clearCoatTintSamplerSampler, fragmentInputs.vClearCoatTintUV + uvOffset); + #endif + + #ifdef CLEARCOAT_BUMP + var clearCoatBumpMapData: vec4f = textureSample(clearCoatBumpSampler, clearCoatBumpSamplerSampler, fragmentInputs.vClearCoatBumpUV + uvOffset); + #endif + + clearcoatOut = clearcoatBlock( + fragmentInputs.vPositionW + , geometricNormalW + , viewDirectionW + , uniforms.vClearCoatParams + #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) && !defined(CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE) + , clearCoatMapRoughnessData + #endif + , specularEnvironmentR0 + #ifdef CLEARCOAT_TEXTURE + , clearCoatMapData + #endif + #ifdef CLEARCOAT_TINT + , uniforms.vClearCoatTintParams + , uniforms.clearCoatColorAtDistance + , uniforms.vClearCoatRefractionParams + #ifdef CLEARCOAT_TINT_TEXTURE + , clearCoatTintMapData + #endif + #endif + #ifdef CLEARCOAT_BUMP + , uniforms.vClearCoatBumpInfos + , clearCoatBumpMapData + , fragmentInputs.vClearCoatBumpUV + #if defined(TANGENT) && defined(NORMAL) + , mat3x3(input.vTBN0, input.vTBN1, input.vTBN2) + #else + , uniforms.vClearCoatTangentSpaceParams + #endif + #ifdef OBJECTSPACE_NORMALMAP + , uniforms.normalMatrix + #endif + #endif + #if defined(FORCENORMALFORWARD) && defined(NORMAL) + , faceNormal + #endif + #ifdef REFLECTION + , uniforms.vReflectionMicrosurfaceInfos + , uniforms.vReflectionInfos + , uniforms.vReflectionColor + , uniforms.vLightingIntensity + , reflectionSampler + , reflectionSamplerSampler + #ifndef LODBASEDMICROSFURACE + , reflectionLowSampler + , reflectionLowSamplerSampler + , reflectionHighSampler + , reflectionHighSamplerSampler + #endif + #ifdef REALTIME_FILTERING + , uniforms.vReflectionFilteringInfo + #endif + #endif + #if defined(CLEARCOAT_BUMP) || defined(TWOSIDEDLIGHTING) + , select(-1., 1., fragmentInputs.frontFacing) + #endif + ); + #else + clearcoatOut.specularEnvironmentR0 = specularEnvironmentR0; + #endif + + // _________________________ Specular Environment Reflectance __________________________ + #include + + // ___________________________________ SubSurface ______________________________________ + var subSurfaceOut: subSurfaceOutParams; + + #ifdef SUBSURFACE + #ifdef SS_THICKNESSANDMASK_TEXTURE + var thicknessMap: vec4f = textureSample(thicknessSampler, thicknessSamplerSampler, fragmentInputs.vThicknessUV + uvOffset); + #endif + + #ifdef SS_REFRACTIONINTENSITY_TEXTURE + var refractionIntensityMap: vec4f = textureSample(refractionIntensitySampler, refractionIntensitySamplerSampler, fragmentInputs.vRefractionIntensityUV + uvOffset); + #endif + + #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE + var translucencyIntensityMap: vec4f = textureSample(translucencyIntensitySampler, translucencyIntensitySamplerSampler, fragmentInputs.vTranslucencyIntensityUV + uvOffset); + #endif + + #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE + var translucencyColorMap: vec4f = textureSample(translucencyColorSampler, translucencyColorSamplerSampler, fragmentInputs.vTranslucencyColorUV + uvOffset); + #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE_GAMMA + translucencyColorMap = toLinearSpaceVec4(translucencyColorMap); + #endif + #endif + + subSurfaceOut = subSurfaceBlock( + uniforms.vSubSurfaceIntensity + , uniforms.vThicknessParam + , uniforms.vTintColor + , normalW + #ifdef LEGACY_SPECULAR_ENERGY_CONSERVATION + , vec3f(max(colorSpecularEnvironmentReflectance.r, max(colorSpecularEnvironmentReflectance.g, colorSpecularEnvironmentReflectance.b))) + #else + , baseSpecularEnvironmentReflectance + #endif + #ifdef SS_THICKNESSANDMASK_TEXTURE + , thicknessMap + #endif + #ifdef SS_REFRACTIONINTENSITY_TEXTURE + , refractionIntensityMap + #endif + #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE + , translucencyIntensityMap + #endif + #ifdef REFLECTION + #ifdef SS_TRANSLUCENCY + , uniforms.reflectionMatrix + #ifdef USESPHERICALFROMREFLECTIONMAP + #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX) + , reflectionOut.irradianceVector + #endif + #if defined(REALTIME_FILTERING) + , reflectionSampler + , reflectionSamplerSampler + , uniforms.vReflectionFilteringInfo + #ifdef IBL_CDF_FILTERING + , icdfSampler + , icdfSamplerSampler + #endif + #endif + #endif + #ifdef USEIRRADIANCEMAP + , irradianceSampler + , irradianceSamplerSampler + #endif + #endif + #endif + #if defined(SS_REFRACTION) || defined(SS_TRANSLUCENCY) + , surfaceAlbedo + #endif + #ifdef SS_REFRACTION + , fragmentInputs.vPositionW + , viewDirectionW + , scene.view + , uniforms.vRefractionInfos + , uniforms.refractionMatrix + , uniforms.vRefractionMicrosurfaceInfos + , uniforms.vLightingIntensity + #ifdef SS_LINKREFRACTIONTOTRANSPARENCY + , alpha + #endif + #ifdef SS_LODINREFRACTIONALPHA + , NdotVUnclamped + #endif + #ifdef SS_LINEARSPECULARREFRACTION + , roughness + #endif + , alphaG + , refractionSampler + , refractionSamplerSampler + #ifndef LODBASEDMICROSFURACE + , refractionLowSampler + , refractionLowSamplerSampler + , refractionHighSampler + , refractionHighSamplerSampler + #endif + #ifdef ANISOTROPIC + , anisotropicOut + #endif + #ifdef REALTIME_FILTERING + , uniforms.vRefractionFilteringInfo + #endif + #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC + , uniforms.vRefractionPosition + , uniforms.vRefractionSize + #endif + #ifdef SS_DISPERSION + , dispersion + #endif + #endif + #ifdef SS_TRANSLUCENCY + , uniforms.vDiffusionDistance + , uniforms.vTranslucencyColor + #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE + , translucencyColorMap + #endif + #endif + ); + + #ifdef SS_REFRACTION + surfaceAlbedo = subSurfaceOut.surfaceAlbedo; + #ifdef SS_LINKREFRACTIONTOTRANSPARENCY + alpha = subSurfaceOut.alpha; + #endif + #endif + #else + subSurfaceOut.specularEnvironmentReflectance = colorSpecularEnvironmentReflectance; + #endif + + // _____________________________ Direct Lighting Info __________________________________ + #include + + #include[0..maxSimultaneousLights] + + // _____________________________ Compute Final Lit Components ________________________ + #include +#endif // UNLIT + + #include + + #define CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION + + #include + + #include + #include(color, finalColor) + #include + + #define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR + +#ifdef PREPASS + #include +#endif + +#if !defined(PREPASS) && !defined(ORDER_INDEPENDENT_TRANSPARENCY) + fragmentOutputs.color = finalColor; +#endif + + #include + +#if ORDER_INDEPENDENT_TRANSPARENCY + if (fragDepth == nearestDepth) { + fragmentOutputs.frontColor = vec4f(fragmentOutputs.frontColor.rgb + finalColor.rgb * finalColor.a * alphaMultiplier, 1.0 - alphaMultiplier * (1.0 - finalColor.a)); + } else { + fragmentOutputs.backColor += finalColor; + } +#endif + + #include + + #define CUSTOM_FRAGMENT_MAIN_END + +} diff --git a/packages/dev/core/src/ShadersWGSL/pbr2.vertex.fx b/packages/dev/core/src/ShadersWGSL/pbr2.vertex.fx new file mode 100644 index 00000000000..dd7d851f241 --- /dev/null +++ b/packages/dev/core/src/ShadersWGSL/pbr2.vertex.fx @@ -0,0 +1,295 @@ +#define PBR_VERTEX_SHADER + +#include + +#define CUSTOM_VERTEX_BEGIN + +// Attributes +attribute position: vec3f; +#ifdef NORMAL +attribute normal: vec3f; +#endif +#ifdef TANGENT +attribute tangent: vec4f; +#endif +#ifdef UV1 +attribute uv: vec2f; +#endif +#include[2..7] +#include[1..7] +#ifdef VERTEXCOLOR +attribute color: vec4f; +#endif + +#include +#include +#include +#include + +#include +#include + +#include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,Albedo) +#include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight) +#include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness) +#include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail) +#include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient) +#include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity) +#include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive) +#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap) +#include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity) +#include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler) +#include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance) +#include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance) +#include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump) +#include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal) + +#ifdef CLEARCOAT + #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat) + #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness) + #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump) + #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint) +#endif + +#ifdef IRIDESCENCE + #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence) + #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness) +#endif + +#ifdef SHEEN + #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen) + #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness) +#endif + +#ifdef ANISOTROPIC + #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy) +#endif + +#ifdef SUBSURFACE + #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness) + #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity) + #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity) + #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor) +#endif + +// Output +varying vPositionW: vec3f; +#if DEBUGMODE > 0 + varying vClipSpacePosition: vec4f; +#endif +#ifdef NORMAL + varying vNormalW: vec3f; + #if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX) + varying vEnvironmentIrradiance: vec3f; + + #include + #endif +#endif + +#if defined(VERTEXCOLOR) || defined(INSTANCESCOLOR) && defined(INSTANCES) +varying vColor: vec4f; +#endif + +#include +#include +#include +#include[0..maxSimultaneousLights] + +#include +#include[0..maxSimultaneousMorphTargets] + +#ifdef REFLECTIONMAP_SKYBOX +varying vPositionUVW: vec3f; +#endif + +#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED) +varying vDirectionW: vec3f; +#endif + +#include +#define CUSTOM_VERTEX_DEFINITIONS + +@vertex +fn main(input : VertexInputs) -> FragmentInputs { + + #define CUSTOM_VERTEX_MAIN_BEGIN + + var positionUpdated: vec3f = vertexInputs.position; +#ifdef NORMAL + var normalUpdated: vec3f = vertexInputs.normal; +#endif +#ifdef TANGENT + var tangentUpdated: vec4f = vertexInputs.tangent; +#endif +#ifdef UV1 + var uvUpdated: vec2f = vertexInputs.uv; +#endif +#ifdef UV2 + var uv2Updated: vec2f = vertexInputs.uv2; +#endif +#ifdef VERTEXCOLOR + var colorUpdated: vec4f = vertexInputs.color; +#endif + +#include +#include[0..maxSimultaneousMorphTargets] + +#ifdef REFLECTIONMAP_SKYBOX + vertexOutputs.vPositionUVW = positionUpdated; +#endif + +#define CUSTOM_VERTEX_UPDATE_POSITION + +#define CUSTOM_VERTEX_UPDATE_NORMAL + +#include + +#if defined(PREPASS) && ((defined(PREPASS_VELOCITY) || defined(PREPASS_VELOCITY_LINEAR)) && !defined(BONES_VELOCITY_ENABLED) + // Compute velocity before bones computation + vertexOutputs.vCurrentPosition = scene.viewProjection * finalWorld * vec4f(positionUpdated, 1.0); + vertexOutputs.vPreviousPosition = uniforms.previousViewProjection * finalPreviousWorld * vec4f(positionUpdated, 1.0); +#endif + +#include +#include + + var worldPos: vec4f = finalWorld * vec4f(positionUpdated, 1.0); + vertexOutputs.vPositionW = worldPos.xyz; + +#ifdef PREPASS + #include +#endif + +#ifdef NORMAL + var normalWorld: mat3x3f = mat3x3f(finalWorld[0].xyz, finalWorld[1].xyz, finalWorld[2].xyz); + + #if defined(INSTANCES) && defined(THIN_INSTANCES) + vertexOutputs.vNormalW = normalUpdated / vec3f(dot(normalWorld[0], normalWorld[0]), dot(normalWorld[1], normalWorld[1]), dot(normalWorld[2], normalWorld[2])); + vertexOutputs.vNormalW = normalize(normalWorld * vertexOutputs.vNormalW); + #else + #ifdef NONUNIFORMSCALING + normalWorld = transposeMat3(inverseMat3(normalWorld)); + #endif + + vertexOutputs.vNormalW = normalize(normalWorld * normalUpdated); + #endif + + #if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX) + #if BASE_DIFFUSE_MODEL != BRDF_DIFFUSE_MODEL_LAMBERT && BASE_DIFFUSE_MODEL != BRDF_DIFFUSE_MODEL_LEGACY + // Bend the normal towards the viewer based on the diffuse roughness + var viewDirectionW: vec3f = normalize(scene.vEyePosition.xyz - vertexOutputs.vPositionW); + var NdotV: f32 = max(dot(vertexOutputs.vNormalW, viewDirectionW), 0.0); + var roughNormal: vec3f = mix(vertexOutputs.vNormalW, viewDirectionW, (0.5 * (1.0 - NdotV)) * uniforms.baseDiffuseRoughness); + var reflectionVector: vec3f = (uniforms.reflectionMatrix * vec4f(roughNormal, 0)).xyz; + #else + var reflectionVector: vec3f = (uniforms.reflectionMatrix * vec4f(vertexOutputs.vNormalW, 0)).xyz; + #endif + #ifdef REFLECTIONMAP_OPPOSITEZ + reflectionVector.z *= -1.0; + #endif + + vertexOutputs.vEnvironmentIrradiance = computeEnvironmentIrradiance(reflectionVector); + #endif +#endif + +#define CUSTOM_VERTEX_UPDATE_WORLDPOS + +#ifdef MULTIVIEW + if (gl_ViewID_OVR == 0u) { + vertexOutputs.position = scene.viewProjection * worldPos; + } else { + vertexOutputs.position = scene.viewProjectionR * worldPos; + } +#else + vertexOutputs.position = scene.viewProjection * worldPos; +#endif + +#if DEBUGMODE > 0 + vertexOutputs.vClipSpacePosition = vertexOutputs.position; +#endif + +#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED) + vertexOutputs.vDirectionW = normalize((finalWorld * vec4f(positionUpdated, 0.0)).xyz); +#endif + + // Texture coordinates +#ifndef UV1 + var uvUpdated: vec2f = vec2f(0., 0.); +#endif +#ifdef MAINUV1 + vertexOutputs.vMainUV1 = uvUpdated; +#endif +#ifndef UV2 + var uv2Updated: vec2f = vec2f(0., 0.); +#endif +#ifdef MAINUV2 + vertexOutputs.vMainUV2 = uv2Updated; +#endif + + #include[3..7] + + #include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,Albedo,_MATRIXNAME_,albedo,_INFONAME_,AlbedoInfos.x) + #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_MATRIXNAME_,baseWeight,_INFONAME_,BaseWeightInfos.x) + #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_MATRIXNAME_,baseDiffuseRoughness,_INFONAME_,BaseDiffuseRoughnessInfos.x) + #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) + #include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_MATRIXNAME_,ambient,_INFONAME_,AmbientInfos.x) + #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_MATRIXNAME_,opacity,_INFONAME_,OpacityInfos.x) + #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_MATRIXNAME_,emissive,_INFONAME_,EmissiveInfos.x) + #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_MATRIXNAME_,lightmap,_INFONAME_,LightmapInfos.x) + #include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity,_MATRIXNAME_,reflectivity,_INFONAME_,ReflectivityInfos.x) + #include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler,_MATRIXNAME_,microSurfaceSampler,_INFONAME_,MicroSurfaceSamplerInfos.x) + #include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance,_MATRIXNAME_,metallicReflectance,_INFONAME_,MetallicReflectanceInfos.x) + #include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance,_MATRIXNAME_,reflectance,_INFONAME_,ReflectanceInfos.x) + #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump,_MATRIXNAME_,bump,_INFONAME_,BumpInfos.x) + #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_MATRIXNAME_,decal,_INFONAME_,DecalInfos.x) + +#ifdef CLEARCOAT + #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat,_MATRIXNAME_,clearCoat,_INFONAME_,ClearCoatInfos.x) + #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness,_MATRIXNAME_,clearCoatRoughness,_INFONAME_,ClearCoatInfos.z) + #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump,_MATRIXNAME_,clearCoatBump,_INFONAME_,ClearCoatBumpInfos.x) + #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint,_MATRIXNAME_,clearCoatTint,_INFONAME_,ClearCoatTintInfos.x) +#endif + +#ifdef IRIDESCENCE + #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence,_MATRIXNAME_,iridescence,_INFONAME_,IridescenceInfos.x) + #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness,_MATRIXNAME_,iridescenceThickness,_INFONAME_,IridescenceInfos.z) +#endif + +#ifdef SHEEN + #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen,_MATRIXNAME_,sheen,_INFONAME_,SheenInfos.x) + #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness,_MATRIXNAME_,sheenRoughness,_INFONAME_,SheenInfos.z) + +#endif + +#ifdef ANISOTROPIC + #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy,_MATRIXNAME_,anisotropy,_INFONAME_,AnisotropyInfos.x) +#endif + +#ifdef SUBSURFACE + #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness,_MATRIXNAME_,thickness,_INFONAME_,ThicknessInfos.x) + #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity,_MATRIXNAME_,refractionIntensity,_INFONAME_,RefractionIntensityInfos.x) + #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity,_MATRIXNAME_,translucencyIntensity,_INFONAME_,TranslucencyIntensityInfos.x) + #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor,_MATRIXNAME_,translucencyColor,_INFONAME_,TranslucencyColorInfos.x) +#endif + + // TBN +#include + + // Clip plane +#include + + // Fog +#include + + // Shadows +#include[0..maxSimultaneousLights] + + // Vertex color +#include + + // Log. depth +#include + +#define CUSTOM_VERTEX_MAIN_END + +} \ No newline at end of file diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts index 2ded7721f72..ee338f27624 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -74,7 +75,7 @@ export class EXT_materials_diffuse_roughness implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadDiffuseRoughnessPropertiesAsync(context: string, properties: IEXTMaterialsDiffuseRoughness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts index c425c295da5..e2ef0b82009 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -70,7 +71,7 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { } private async _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsAnisotropy, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts index bc394cd1040..7d51a89c977 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -72,7 +73,7 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts index 5507ebfb1ab..4b98b0a6193 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts @@ -1,6 +1,7 @@ /* eslint-disable github/no-then */ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -77,7 +78,7 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async private _loadTranslucentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDiffuseTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } 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 1a99485b358..4061875421d 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 @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -73,7 +74,7 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadDispersionPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDispersion): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts index b2c0e1a0e41..c80e9794d50 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -70,7 +71,7 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { } private _loadEmissiveProperties(context: string, properties: IKHRMaterialsEmissiveStrength, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts index ad70f99ba58..480e8eb8df8 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -77,7 +78,7 @@ export class KHR_materials_ior implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts index 11168af02da..bfb5304c3dd 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -72,7 +73,7 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts index 4f228ad3d07..2120598c1d0 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts @@ -1,6 +1,7 @@ import type { Nullable } from "core/types"; import { Color3 } from "core/Maths/math.color"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -74,7 +75,7 @@ export class KHR_materials_pbrSpecularGlossiness implements IGLTFLoaderExtension // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSpecularGlossinessPropertiesAsync(context: string, properties: IKHRMaterialsPbrSpecularGlossiness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts index 4816792a5e3..a99c04337a5 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -74,7 +75,7 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts index 38cbf494cd9..e5c5d196148 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -83,7 +84,7 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts index 5f91a41d555..17674b2b99a 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -378,7 +379,7 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } const pbrMaterial = babylonMaterial; diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts index 1a9609ac33c..c3dd1019330 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts @@ -1,6 +1,7 @@ import type { Nullable } from "core/types"; import { Color3 } from "core/Maths/math.color"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -68,7 +69,7 @@ export class KHR_materials_unlit implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadUnlitPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts index 349cbd67c10..3929bb97f13 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -81,7 +82,7 @@ export class KHR_materials_volume implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts index 84055b9c49b..b3463735af8 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts @@ -1,6 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -47,7 +48,7 @@ export class MSFT_minecraftMesh implements IGLTFLoaderExtension { public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { if (extra) { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${extraContext}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index ab98d23ed09..f515f1954bf 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -1,6 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -47,7 +48,7 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { if (extra) { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${extraContext}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index b199e919678..dd3d399c8ec 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -17,6 +17,7 @@ import { Bone } from "core/Bones/bone"; import { Skeleton } from "core/Bones/skeleton"; import { Material } from "core/Materials/material"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { ITextureCreationOptions } from "core/Materials/Textures/texture"; import { Texture } from "core/Materials/Textures/texture"; @@ -2127,7 +2128,7 @@ export class GLTFLoader implements IGLTFLoader { } private _loadMaterialMetallicRoughnessPropertiesAsync(context: string, properties: IMaterialPbrMetallicRoughness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } @@ -2227,7 +2228,12 @@ export class GLTFLoader implements IGLTFLoader { private _createDefaultMaterial(name: string, babylonDrawMode: number): Material { this._babylonScene._blockEntityCollection = !!this._assetContainer; - const babylonMaterial = new PBRMaterial(name, this._babylonScene); + let babylonMaterial; + if (this.parent.usePBR2) { + babylonMaterial = new PBRMaterial2(name, this._babylonScene); + } else { + babylonMaterial = new PBRMaterial(name, this._babylonScene); + } babylonMaterial._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; // Moved to mesh so user can change materials on gltf meshes: babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation; @@ -2295,7 +2301,7 @@ export class GLTFLoader implements IGLTFLoader { * @returns A promise that resolves when the load is complete */ public loadMaterialBasePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } @@ -2360,7 +2366,7 @@ export class GLTFLoader implements IGLTFLoader { * @param babylonMaterial The Babylon material */ public loadMaterialAlphaProperties(context: string, material: IMaterial, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/glTFFileLoader.ts b/packages/dev/loaders/src/glTF/glTFFileLoader.ts index 4da0f4a44c3..38f287c9d7b 100644 --- a/packages/dev/loaders/src/glTF/glTFFileLoader.ts +++ b/packages/dev/loaders/src/glTF/glTFFileLoader.ts @@ -206,6 +206,7 @@ abstract class GLTFLoaderOptions { this.compileShadowGenerators = options.compileShadowGenerators ?? this.compileShadowGenerators; this.transparencyAsCoverage = options.transparencyAsCoverage ?? this.transparencyAsCoverage; this.useRangeRequests = options.useRangeRequests ?? this.useRangeRequests; + this.usePBR2 = options.usePBR2 ?? this.usePBR2; this.createInstances = options.createInstances ?? this.createInstances; this.alwaysComputeBoundingBox = options.alwaysComputeBoundingBox ?? this.alwaysComputeBoundingBox; this.loadAllMaterials = options.loadAllMaterials ?? this.loadAllMaterials; @@ -294,6 +295,11 @@ abstract class GLTFLoaderOptions { */ public useRangeRequests = false; + /** + * Load the glTF files using the PBR2 material. + */ + public usePBR2 = false; + /** * Defines if the loader should create instances when multiple glTF nodes point to the same glTF mesh. Defaults to true. */ From b3e25ff8adf2f447fc6e7144f59074cc2f38a5a4 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Thu, 19 Jun 2025 15:32:19 -0700 Subject: [PATCH 02/23] Try mixins for reusing defines in materials --- .../Background/backgroundMaterial.ts | 23 ++---------- .../core/src/Materials/Node/nodeMaterial.ts | 37 ++----------------- .../core/src/Materials/PBR/pbrBaseMaterial.ts | 25 ++----------- .../core/src/Materials/PBR/pbrMaterial2.ts | 25 ++----------- .../imageProcessingConfiguration.defines.ts | 30 +++++++++++++++ .../core/src/Materials/standardMaterial.ts | 24 ++---------- .../dev/materials/src/water/waterMaterial.ts | 22 ++--------- 7 files changed, 54 insertions(+), 132 deletions(-) diff --git a/packages/dev/core/src/Materials/Background/backgroundMaterial.ts b/packages/dev/core/src/Materials/Background/backgroundMaterial.ts index 8caad63d4e0..cf82580c1c0 100644 --- a/packages/dev/core/src/Materials/Background/backgroundMaterial.ts +++ b/packages/dev/core/src/Materials/Background/backgroundMaterial.ts @@ -15,7 +15,7 @@ import type { IEffectCreationOptions } from "../../Materials/effect"; import { MaterialDefines } from "../../Materials/materialDefines"; import { PushMaterial } from "../../Materials/pushMaterial"; import type { ColorCurves } from "../../Materials/colorCurves"; -import type { IImageProcessingConfigurationDefines } from "../../Materials/imageProcessingConfiguration.defines"; +import { ImageProcessingDefinesMixin } from "../../Materials/imageProcessingConfiguration.defines"; import { ImageProcessingConfiguration } from "../../Materials/imageProcessingConfiguration"; import type { BaseTexture } from "../../Materials/Textures/baseTexture"; import { Texture } from "../../Materials/Textures/texture"; @@ -48,11 +48,13 @@ import { import { SerializationHelper } from "../../Misc/decorators.serialization"; import { ShaderLanguage } from "../shaderLanguage"; +class BackgroundMaterialDefinesBase extends MaterialDefines {} + /** * Background material defines definition. * @internal Mainly internal Use */ -class BackgroundMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines { +class BackgroundMaterialDefines extends ImageProcessingDefinesMixin(BackgroundMaterialDefinesBase) { /** * True if the diffuse texture is in use. */ @@ -135,23 +137,6 @@ class BackgroundMaterialDefines extends MaterialDefines implements IImageProcess */ public PROJECTED_GROUND = false; - public IMAGEPROCESSING = false; - public VIGNETTE = false; - public VIGNETTEBLENDMODEMULTIPLY = false; - public VIGNETTEBLENDMODEOPAQUE = false; - public TONEMAPPING = 0; - public CONTRAST = false; - public COLORCURVES = false; - public COLORGRADING = false; - public COLORGRADING3D = false; - public SAMPLER3DGREENDEPTH = false; - public SAMPLER3DBGRMAP = false; - public DITHER = false; - public IMAGEPROCESSINGPOSTPROCESS = false; - public SKIPFINALCOLORCLAMP = false; - public EXPOSURE = false; - public MULTIVIEW = false; - // Reflection. public REFLECTION = false; public REFLECTIONMAP_3D = false; diff --git a/packages/dev/core/src/Materials/Node/nodeMaterial.ts b/packages/dev/core/src/Materials/Node/nodeMaterial.ts index 3508fceab1e..0d397ddc33a 100644 --- a/packages/dev/core/src/Materials/Node/nodeMaterial.ts +++ b/packages/dev/core/src/Materials/Node/nodeMaterial.ts @@ -67,7 +67,7 @@ import type { NodeMaterialTeleportOutBlock } from "./Blocks/Teleport/teleportOut import type { NodeMaterialTeleportInBlock } from "./Blocks/Teleport/teleportInBlock"; import { Logger } from "core/Misc/logger"; import { PrepareDefinesForCamera, PrepareDefinesForPrePass } from "../materialHelper.functions"; -import type { IImageProcessingConfigurationDefines } from "../imageProcessingConfiguration.defines"; +import { ImageProcessingDefinesMixin } from "../imageProcessingConfiguration.defines"; import { ShaderLanguage } from "../shaderLanguage"; import { AbstractEngine } from "../../Engines/abstractEngine"; import type { LoopBlock } from "./Blocks/loopBlock"; @@ -91,8 +91,10 @@ export interface INodeMaterialEditorOptions { }; } +class NodeMaterialDefinesBase extends MaterialDefines {} + /** @internal */ -export class NodeMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines { +export class NodeMaterialDefines extends ImageProcessingDefinesMixin(NodeMaterialDefinesBase) { /** Normal */ public NORMAL = false; /** Tangent */ @@ -177,37 +179,6 @@ export class NodeMaterialDefines extends MaterialDefines implements IImageProces /** Using a texture to store morph target data */ public MORPHTARGETS_TEXTURE = false; - /** IMAGE PROCESSING */ - public IMAGEPROCESSING = false; - /** Vignette */ - public VIGNETTE = false; - /** Multiply blend mode for vignette */ - public VIGNETTEBLENDMODEMULTIPLY = false; - /** Opaque blend mode for vignette */ - public VIGNETTEBLENDMODEOPAQUE = false; - /** Tone mapping */ - public TONEMAPPING = 0; - /** Contrast */ - public CONTRAST = false; - /** Exposure */ - public EXPOSURE = false; - /** Color curves */ - public COLORCURVES = false; - /** Color grading */ - public COLORGRADING = false; - /** 3D color grading */ - public COLORGRADING3D = false; - /** Sampler green depth */ - public SAMPLER3DGREENDEPTH = false; - /** Sampler for BGR map */ - public SAMPLER3DBGRMAP = false; - /** Dithering */ - public DITHER = false; - /** Using post process for image processing */ - public IMAGEPROCESSINGPOSTPROCESS = false; - /** Skip color clamp */ - public SKIPFINALCOLORCLAMP = false; - /** MISC. */ public BUMPDIRECTUV = 0; /** Camera is orthographic */ diff --git a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts index 841eab9fb71..6055c228fbe 100644 --- a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts @@ -16,7 +16,7 @@ import { PBRBRDFConfiguration } from "./pbrBRDFConfiguration"; import { PrePassConfiguration } from "../prePassConfiguration"; import { Color3, TmpColors } from "../../Maths/math.color"; -import type { IImageProcessingConfigurationDefines } from "../../Materials/imageProcessingConfiguration.defines"; +import { ImageProcessingDefinesMixin } from "../../Materials/imageProcessingConfiguration.defines"; import { ImageProcessingConfiguration } from "../../Materials/imageProcessingConfiguration"; import type { Effect, IEffectCreationOptions } from "../../Materials/effect"; import type { IMaterialCompilationOptions, ICustomShaderNameResolveOptions } from "../../Materials/material"; @@ -71,11 +71,13 @@ import { MaterialHelperGeometryRendering } from "../materialHelper.geometryrende const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; +class PBRMaterialDefinesBase extends MaterialDefines {} + /** * Manages the defines for the PBR Material. * @internal */ -export class PBRMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines { +export class PBRMaterialDefines extends ImageProcessingDefinesMixin(PBRMaterialDefinesBase) { public PBR = true; public NUM_SAMPLES = "0"; @@ -256,25 +258,6 @@ export class PBRMaterialDefines extends MaterialDefines implements IImageProcess public NUM_MORPH_INFLUENCERS = 0; public MORPHTARGETS_TEXTURE = false; - public IMAGEPROCESSING = false; - public VIGNETTE = false; - public VIGNETTEBLENDMODEMULTIPLY = false; - public VIGNETTEBLENDMODEOPAQUE = false; - public TONEMAPPING = 0; - public CONTRAST = false; - public COLORCURVES = false; - public COLORGRADING = false; - public COLORGRADING3D = false; - public SAMPLER3DGREENDEPTH = false; - public SAMPLER3DBGRMAP = false; - public DITHER = false; - public IMAGEPROCESSINGPOSTPROCESS = false; - public SKIPFINALCOLORCLAMP = false; - public EXPOSURE = false; - public MULTIVIEW = false; - public ORDER_INDEPENDENT_TRANSPARENCY = false; - public ORDER_INDEPENDENT_TRANSPARENCY_16BITS = false; - public USEPHYSICALLIGHTFALLOFF = false; public USEGLTFLIGHTFALLOFF = false; public TWOSIDEDLIGHTING = false; diff --git a/packages/dev/core/src/Materials/PBR/pbrMaterial2.ts b/packages/dev/core/src/Materials/PBR/pbrMaterial2.ts index 39ef0957c06..4d29c78ff02 100644 --- a/packages/dev/core/src/Materials/PBR/pbrMaterial2.ts +++ b/packages/dev/core/src/Materials/PBR/pbrMaterial2.ts @@ -15,7 +15,7 @@ import { SerializationHelper } from "../../Misc/decorators.serialization"; import type { AbstractMesh } from "../../Meshes/abstractMesh"; import type { Effect, IEffectCreationOptions } from "../../Materials/effect"; import { MaterialDefines } from "../../Materials/materialDefines"; -import type { IImageProcessingConfigurationDefines } from "../../Materials/imageProcessingConfiguration.defines"; +import { ImageProcessingDefinesMixin } from "../../Materials/imageProcessingConfiguration.defines"; import { EffectFallbacks } from "../effectFallbacks"; import { AddClipPlaneUniforms } from "../clipPlaneMaterialHelper"; import { @@ -53,11 +53,13 @@ import type { SubMesh } from "../../Meshes/subMesh"; import { Logger } from "core/Misc/logger"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; + +class PBRMaterial2DefinesBase extends MaterialDefines {} /** * Manages the defines for the PBR Material. * @internal */ -export class PBRMaterial2Defines extends MaterialDefines implements IImageProcessingConfigurationDefines { +export class PBRMaterial2Defines extends ImageProcessingDefinesMixin(PBRMaterial2DefinesBase) { public PBR = true; public NUM_SAMPLES = "0"; @@ -238,25 +240,6 @@ export class PBRMaterial2Defines extends MaterialDefines implements IImageProces public NUM_MORPH_INFLUENCERS = 0; public MORPHTARGETS_TEXTURE = false; - public IMAGEPROCESSING = false; - public VIGNETTE = false; - public VIGNETTEBLENDMODEMULTIPLY = false; - public VIGNETTEBLENDMODEOPAQUE = false; - public TONEMAPPING = 0; - public CONTRAST = false; - public COLORCURVES = false; - public COLORGRADING = false; - public COLORGRADING3D = false; - public SAMPLER3DGREENDEPTH = false; - public SAMPLER3DBGRMAP = false; - public DITHER = false; - public IMAGEPROCESSINGPOSTPROCESS = false; - public SKIPFINALCOLORCLAMP = false; - public EXPOSURE = false; - public MULTIVIEW = false; - public ORDER_INDEPENDENT_TRANSPARENCY = false; - public ORDER_INDEPENDENT_TRANSPARENCY_16BITS = false; - public USEPHYSICALLIGHTFALLOFF = false; public USEGLTFLIGHTFALLOFF = false; public TWOSIDEDLIGHTING = false; diff --git a/packages/dev/core/src/Materials/imageProcessingConfiguration.defines.ts b/packages/dev/core/src/Materials/imageProcessingConfiguration.defines.ts index 53f897fbdc2..de659b50f28 100644 --- a/packages/dev/core/src/Materials/imageProcessingConfiguration.defines.ts +++ b/packages/dev/core/src/Materials/imageProcessingConfiguration.defines.ts @@ -22,6 +22,36 @@ export interface IImageProcessingConfigurationDefines { SKIPFINALCOLORCLAMP: boolean; } +type Constructor = new (...args: any[]) => T; + +/** + * Mixin to add Image processing defines to your material defines + * @internal + */ +export function ImageProcessingDefinesMixin(base: Tbase) { + return class extends base implements IImageProcessingConfigurationDefines { + // Implement all members of IImageProcessingConfigurationDefines here + public IMAGEPROCESSING = false; + public VIGNETTE = false; + public VIGNETTEBLENDMODEMULTIPLY = false; + public VIGNETTEBLENDMODEOPAQUE = false; + public TONEMAPPING = 0; + public CONTRAST = false; + public COLORCURVES = false; + public COLORGRADING = false; + public COLORGRADING3D = false; + public SAMPLER3DGREENDEPTH = false; + public SAMPLER3DBGRMAP = false; + public DITHER = false; + public IMAGEPROCESSINGPOSTPROCESS = false; + public SKIPFINALCOLORCLAMP = false; + public EXPOSURE = false; + public MULTIVIEW = false; + public ORDER_INDEPENDENT_TRANSPARENCY = false; + public ORDER_INDEPENDENT_TRANSPARENCY_16BITS = false; + }; +} + /** * @internal */ diff --git a/packages/dev/core/src/Materials/standardMaterial.ts b/packages/dev/core/src/Materials/standardMaterial.ts index ccc8f1d952d..44c5f8c1e73 100644 --- a/packages/dev/core/src/Materials/standardMaterial.ts +++ b/packages/dev/core/src/Materials/standardMaterial.ts @@ -14,7 +14,7 @@ import type { AbstractMesh } from "../Meshes/abstractMesh"; import type { Mesh } from "../Meshes/mesh"; import { PrePassConfiguration } from "./prePassConfiguration"; -import type { IImageProcessingConfigurationDefines } from "./imageProcessingConfiguration.defines"; +import { ImageProcessingDefinesMixin } from "./imageProcessingConfiguration.defines"; import { ImageProcessingConfiguration } from "./imageProcessingConfiguration"; import type { ColorCurves } from "./colorCurves"; import type { FresnelParameters } from "./fresnelParameters"; @@ -64,8 +64,10 @@ import { MaterialHelperGeometryRendering } from "./materialHelper.geometryrender const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; +class StandardMaterialDefinesBase extends MaterialDefines {} + /** @internal */ -export class StandardMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines { +export class StandardMaterialDefines extends ImageProcessingDefinesMixin(StandardMaterialDefinesBase) { public MAINUV1 = false; public MAINUV2 = false; public MAINUV3 = false; @@ -211,23 +213,6 @@ export class StandardMaterialDefines extends MaterialDefines implements IImagePr public RGBDREFLECTION = false; public RGBDREFRACTION = false; - public IMAGEPROCESSING = false; - public VIGNETTE = false; - public VIGNETTEBLENDMODEMULTIPLY = false; - public VIGNETTEBLENDMODEOPAQUE = false; - public TONEMAPPING = 0; - public CONTRAST = false; - public COLORCURVES = false; - public COLORGRADING = false; - public COLORGRADING3D = false; - public SAMPLER3DGREENDEPTH = false; - public SAMPLER3DBGRMAP = false; - public DITHER = false; - public IMAGEPROCESSINGPOSTPROCESS = false; - public SKIPFINALCOLORCLAMP = false; - public MULTIVIEW = false; - public ORDER_INDEPENDENT_TRANSPARENCY = false; - public ORDER_INDEPENDENT_TRANSPARENCY_16BITS = false; public CAMERA_ORTHOGRAPHIC = false; public CAMERA_PERSPECTIVE = false; public AREALIGHTSUPPORTED = true; @@ -242,7 +227,6 @@ export class StandardMaterialDefines extends MaterialDefines implements IImagePr * @internal */ public IS_REFRACTION_LINEAR = false; - public EXPOSURE = false; public DECAL_AFTER_DETAIL = false; diff --git a/packages/dev/materials/src/water/waterMaterial.ts b/packages/dev/materials/src/water/waterMaterial.ts index cfc989f34e9..5e3cb408a6a 100644 --- a/packages/dev/materials/src/water/waterMaterial.ts +++ b/packages/dev/materials/src/water/waterMaterial.ts @@ -13,7 +13,7 @@ import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import { RenderTargetTexture } from "core/Materials/Textures/renderTargetTexture"; import type { IEffectCreationOptions } from "core/Materials/effect"; import { MaterialDefines } from "core/Materials/materialDefines"; -import type { IImageProcessingConfigurationDefines } from "core/Materials/imageProcessingConfiguration.defines"; +import { ImageProcessingDefinesMixin } from "core/Materials/imageProcessingConfiguration.defines"; import { ImageProcessingConfiguration } from "core/Materials/imageProcessingConfiguration"; import { PushMaterial } from "core/Materials/pushMaterial"; import { MaterialFlags } from "core/Materials/materialFlags"; @@ -47,7 +47,9 @@ import { import "core/Rendering/boundingBoxRenderer"; -class WaterMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines { +class WaterMaterialDefinesBase extends MaterialDefines {} + +class WaterMaterialDefines extends ImageProcessingDefinesMixin(WaterMaterialDefinesBase) { public BUMP = false; public REFLECTION = false; public CLIPPLANE = false; @@ -77,22 +79,6 @@ class WaterMaterialDefines extends MaterialDefines implements IImageProcessingCo public BUMPAFFECTSREFLECTION = false; public USE_WORLD_COORDINATES = false; - public IMAGEPROCESSING = false; - public VIGNETTE = false; - public VIGNETTEBLENDMODEMULTIPLY = false; - public VIGNETTEBLENDMODEOPAQUE = false; - public TONEMAPPING = 0; - public CONTRAST = false; - public EXPOSURE = false; - public COLORCURVES = false; - public COLORGRADING = false; - public COLORGRADING3D = false; - public SAMPLER3DGREENDEPTH = false; - public SAMPLER3DBGRMAP = false; - public DITHER = false; - public IMAGEPROCESSINGPOSTPROCESS = false; - public SKIPFINALCOLORCLAMP = false; - constructor() { super(); this.rebuild(); From d7f3ddae7da678df4467dc015097dee01fd7f883 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Fri, 20 Jun 2025 09:11:40 -0700 Subject: [PATCH 03/23] Move UV defines into a mixin --- .../core/src/Materials/Node/nodeMaterial.ts | 15 ++----------- .../core/src/Materials/PBR/pbrBaseMaterial.ts | 15 ++----------- .../core/src/Materials/standardMaterial.ts | 15 ++----------- packages/dev/core/src/Materials/uv.defines.ts | 22 +++++++++++++++++++ .../dev/materials/src/water/waterMaterial.ts | 22 +++++++++++++++---- 5 files changed, 46 insertions(+), 43 deletions(-) create mode 100644 packages/dev/core/src/Materials/uv.defines.ts diff --git a/packages/dev/core/src/Materials/Node/nodeMaterial.ts b/packages/dev/core/src/Materials/Node/nodeMaterial.ts index 0d397ddc33a..72660c183d7 100644 --- a/packages/dev/core/src/Materials/Node/nodeMaterial.ts +++ b/packages/dev/core/src/Materials/Node/nodeMaterial.ts @@ -72,6 +72,7 @@ import { ShaderLanguage } from "../shaderLanguage"; import { AbstractEngine } from "../../Engines/abstractEngine"; import type { LoopBlock } from "./Blocks/loopBlock"; import { MaterialHelperGeometryRendering } from "../materialHelper.geometryrendering"; +import { UVDefinesMixin } from "../uv.defines"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; @@ -91,7 +92,7 @@ export interface INodeMaterialEditorOptions { }; } -class NodeMaterialDefinesBase extends MaterialDefines {} +class NodeMaterialDefinesBase extends UVDefinesMixin(MaterialDefines) {} /** @internal */ export class NodeMaterialDefines extends ImageProcessingDefinesMixin(NodeMaterialDefinesBase) { @@ -101,18 +102,6 @@ export class NodeMaterialDefines extends ImageProcessingDefinesMixin(NodeMateria public TANGENT = false; /** Vertex color */ public VERTEXCOLOR_NME = false; - /** Uv1 **/ - public UV1 = false; - /** Uv2 **/ - public UV2 = false; - /** Uv3 **/ - public UV3 = false; - /** Uv4 **/ - public UV4 = false; - /** Uv5 **/ - public UV5 = false; - /** Uv6 **/ - public UV6 = false; /** Prepass **/ public PREPASS = false; diff --git a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts index 6055c228fbe..b2cf5bc8615 100644 --- a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts @@ -68,10 +68,11 @@ import { } from "../materialHelper.functions"; import { ShaderLanguage } from "../shaderLanguage"; import { MaterialHelperGeometryRendering } from "../materialHelper.geometryrendering"; +import { UVDefinesMixin } from "../uv.defines"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; -class PBRMaterialDefinesBase extends MaterialDefines {} +class PBRMaterialDefinesBase extends UVDefinesMixin(MaterialDefines) {} /** * Manages the defines for the PBR Material. @@ -83,18 +84,6 @@ export class PBRMaterialDefines extends ImageProcessingDefinesMixin(PBRMaterialD public NUM_SAMPLES = "0"; public REALTIME_FILTERING = false; public IBL_CDF_FILTERING = false; - public MAINUV1 = false; - public MAINUV2 = false; - public MAINUV3 = false; - public MAINUV4 = false; - public MAINUV5 = false; - public MAINUV6 = false; - public UV1 = false; - public UV2 = false; - public UV3 = false; - public UV4 = false; - public UV5 = false; - public UV6 = false; public ALBEDO = false; public GAMMAALBEDO = false; diff --git a/packages/dev/core/src/Materials/standardMaterial.ts b/packages/dev/core/src/Materials/standardMaterial.ts index 44c5f8c1e73..4148f04f9c4 100644 --- a/packages/dev/core/src/Materials/standardMaterial.ts +++ b/packages/dev/core/src/Materials/standardMaterial.ts @@ -61,19 +61,14 @@ import { import { SerializationHelper } from "../Misc/decorators.serialization"; import { ShaderLanguage } from "./shaderLanguage"; import { MaterialHelperGeometryRendering } from "./materialHelper.geometryrendering"; +import { UVDefinesMixin } from "./uv.defines"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; -class StandardMaterialDefinesBase extends MaterialDefines {} +class StandardMaterialDefinesBase extends UVDefinesMixin(MaterialDefines) {} /** @internal */ export class StandardMaterialDefines extends ImageProcessingDefinesMixin(StandardMaterialDefinesBase) { - public MAINUV1 = false; - public MAINUV2 = false; - public MAINUV3 = false; - public MAINUV4 = false; - public MAINUV5 = false; - public MAINUV6 = false; public DIFFUSE = false; public DIFFUSEDIRECTUV = 0; public BAKED_VERTEX_ANIMATION_TEXTURE = false; @@ -113,12 +108,6 @@ export class StandardMaterialDefines extends ImageProcessingDefinesMixin(Standar public FRESNEL = false; public NORMAL = false; public TANGENT = false; - public UV1 = false; - public UV2 = false; - public UV3 = false; - public UV4 = false; - public UV5 = false; - public UV6 = false; public VERTEXCOLOR = false; public VERTEXALPHA = false; public NUM_BONE_INFLUENCERS = 0; diff --git a/packages/dev/core/src/Materials/uv.defines.ts b/packages/dev/core/src/Materials/uv.defines.ts new file mode 100644 index 00000000000..12eec96845c --- /dev/null +++ b/packages/dev/core/src/Materials/uv.defines.ts @@ -0,0 +1,22 @@ +type Constructor = new (...args: any[]) => T; + +/** + * Mixin to add UV defines to your material defines + * @internal + */ +export function UVDefinesMixin(base: Tbase) { + return class extends base { + public MAINUV1 = false; + public MAINUV2 = false; + public MAINUV3 = false; + public MAINUV4 = false; + public MAINUV5 = false; + public MAINUV6 = false; + public UV1 = false; + public UV2 = false; + public UV3 = false; + public UV4 = false; + public UV5 = false; + public UV6 = false; + }; +} diff --git a/packages/dev/materials/src/water/waterMaterial.ts b/packages/dev/materials/src/water/waterMaterial.ts index 5e3cb408a6a..cfc989f34e9 100644 --- a/packages/dev/materials/src/water/waterMaterial.ts +++ b/packages/dev/materials/src/water/waterMaterial.ts @@ -13,7 +13,7 @@ import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import { RenderTargetTexture } from "core/Materials/Textures/renderTargetTexture"; import type { IEffectCreationOptions } from "core/Materials/effect"; import { MaterialDefines } from "core/Materials/materialDefines"; -import { ImageProcessingDefinesMixin } from "core/Materials/imageProcessingConfiguration.defines"; +import type { IImageProcessingConfigurationDefines } from "core/Materials/imageProcessingConfiguration.defines"; import { ImageProcessingConfiguration } from "core/Materials/imageProcessingConfiguration"; import { PushMaterial } from "core/Materials/pushMaterial"; import { MaterialFlags } from "core/Materials/materialFlags"; @@ -47,9 +47,7 @@ import { import "core/Rendering/boundingBoxRenderer"; -class WaterMaterialDefinesBase extends MaterialDefines {} - -class WaterMaterialDefines extends ImageProcessingDefinesMixin(WaterMaterialDefinesBase) { +class WaterMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines { public BUMP = false; public REFLECTION = false; public CLIPPLANE = false; @@ -79,6 +77,22 @@ class WaterMaterialDefines extends ImageProcessingDefinesMixin(WaterMaterialDefi public BUMPAFFECTSREFLECTION = false; public USE_WORLD_COORDINATES = false; + public IMAGEPROCESSING = false; + public VIGNETTE = false; + public VIGNETTEBLENDMODEMULTIPLY = false; + public VIGNETTEBLENDMODEOPAQUE = false; + public TONEMAPPING = 0; + public CONTRAST = false; + public EXPOSURE = false; + public COLORCURVES = false; + public COLORGRADING = false; + public COLORGRADING3D = false; + public SAMPLER3DGREENDEPTH = false; + public SAMPLER3DBGRMAP = false; + public DITHER = false; + public IMAGEPROCESSINGPOSTPROCESS = false; + public SKIPFINALCOLORCLAMP = false; + constructor() { super(); this.rebuild(); From 05e5bf22a72d6bbe01e2b0ced1f66e56f6452b4b Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Fri, 20 Jun 2025 14:06:51 -0700 Subject: [PATCH 04/23] Add mixin for imageProcessing support in materials --- .../Background/backgroundMaterial.ts | 170 +---------- packages/dev/core/src/Materials/PBR/index.ts | 2 +- .../PBR/{pbrMaterial2.ts => pbr2Material.ts} | 264 +++++++----------- .../core/src/Materials/PBR/pbrBaseMaterial.ts | 47 +--- .../dev/core/src/Materials/PBR/pbrMaterial.ts | 123 -------- .../dev/core/src/Materials/imageProcessing.ts | 193 +++++++++++++ .../core/src/Materials/standardMaterial.ts | 164 +---------- .../EXT_materials_diffuse_roughness.ts | 4 +- .../Extensions/KHR_materials_anisotropy.ts | 4 +- .../2.0/Extensions/KHR_materials_clearcoat.ts | 4 +- .../KHR_materials_diffuse_transmission.ts | 4 +- .../Extensions/KHR_materials_dispersion.ts | 4 +- .../KHR_materials_emissive_strength.ts | 4 +- .../glTF/2.0/Extensions/KHR_materials_ior.ts | 4 +- .../Extensions/KHR_materials_iridescence.ts | 4 +- .../KHR_materials_pbrSpecularGlossiness.ts | 4 +- .../2.0/Extensions/KHR_materials_sheen.ts | 4 +- .../2.0/Extensions/KHR_materials_specular.ts | 4 +- .../Extensions/KHR_materials_transmission.ts | 4 +- .../2.0/Extensions/KHR_materials_unlit.ts | 4 +- .../2.0/Extensions/KHR_materials_volume.ts | 4 +- .../glTF/2.0/Extensions/MSFT_minecraftMesh.ts | 4 +- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 4 +- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 10 +- 24 files changed, 339 insertions(+), 698 deletions(-) rename packages/dev/core/src/Materials/PBR/{pbrMaterial2.ts => pbr2Material.ts} (89%) create mode 100644 packages/dev/core/src/Materials/imageProcessing.ts diff --git a/packages/dev/core/src/Materials/Background/backgroundMaterial.ts b/packages/dev/core/src/Materials/Background/backgroundMaterial.ts index cf82580c1c0..77ff895e8d0 100644 --- a/packages/dev/core/src/Materials/Background/backgroundMaterial.ts +++ b/packages/dev/core/src/Materials/Background/backgroundMaterial.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { serialize, serializeAsColor3, expandToProperty, serializeAsTexture, serializeAsVector3, serializeAsImageProcessingConfiguration } from "../../Misc/decorators"; +import { serialize, serializeAsColor3, expandToProperty, serializeAsTexture, serializeAsVector3 } from "../../Misc/decorators"; import { SmartArray } from "../../Misc/smartArray"; -import type { Observer } from "../../Misc/observable"; import { Logger } from "../../Misc/logger"; import type { Nullable, int, float } from "../../types"; import type { Scene } from "../../scene"; @@ -14,7 +13,6 @@ import type { Mesh } from "../../Meshes/mesh"; import type { IEffectCreationOptions } from "../../Materials/effect"; import { MaterialDefines } from "../../Materials/materialDefines"; import { PushMaterial } from "../../Materials/pushMaterial"; -import type { ColorCurves } from "../../Materials/colorCurves"; import { ImageProcessingDefinesMixin } from "../../Materials/imageProcessingConfiguration.defines"; import { ImageProcessingConfiguration } from "../../Materials/imageProcessingConfiguration"; import type { BaseTexture } from "../../Materials/Textures/baseTexture"; @@ -47,6 +45,7 @@ import { } from "../materialHelper.functions"; import { SerializationHelper } from "../../Misc/decorators.serialization"; import { ShaderLanguage } from "../shaderLanguage"; +import { ImageProcessingMixin } from "../imageProcessing"; class BackgroundMaterialDefinesBase extends MaterialDefines {} @@ -187,11 +186,12 @@ class BackgroundMaterialDefines extends ImageProcessingDefinesMixin(BackgroundMa } } +class BackgroundMaterialBase extends ImageProcessingMixin(PushMaterial) {} /** * Background material used to create an efficient environment around your scene. * #157MGZ: simple test */ -export class BackgroundMaterial extends PushMaterial { +export class BackgroundMaterial extends BackgroundMaterialBase { /** * Standard reflectance value at parallel view angle. */ @@ -439,168 +439,6 @@ export class BackgroundMaterial extends PushMaterial { @expandToProperty("_markAllSubMeshesAsLightsDirty") public shadowOnly: boolean = false; - /** - * Default configuration related to image processing available in the Background Material. - */ - @serializeAsImageProcessingConfiguration() - protected _imageProcessingConfiguration: ImageProcessingConfiguration; - - /** - * Keep track of the image processing observer to allow dispose and replace. - */ - private _imageProcessingObserver: Nullable> = null; - - /** - * Attaches a new image processing configuration to the PBR Material. - * @param configuration (if null the scene configuration will be use) - */ - protected _attachImageProcessingConfiguration(configuration: Nullable): void { - if (configuration === this._imageProcessingConfiguration) { - return; - } - - // Detaches observer. - if (this._imageProcessingConfiguration && this._imageProcessingObserver) { - this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver); - } - - // Pick the scene configuration if needed. - if (!configuration) { - this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration; - } else { - this._imageProcessingConfiguration = configuration; - } - - // Attaches observer. - if (this._imageProcessingConfiguration) { - this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(() => { - this._computePrimaryColorFromPerceptualColor(); - this._markAllSubMeshesAsImageProcessingDirty(); - }); - } - } - - /** - * Gets the image processing configuration used either in this material. - */ - public get imageProcessingConfiguration(): Nullable { - return this._imageProcessingConfiguration; - } - - /** - * Sets the Default image processing configuration used either in the this material. - * - * If sets to null, the scene one is in use. - */ - public set imageProcessingConfiguration(value: Nullable) { - this._attachImageProcessingConfiguration(value); - - // Ensure the effect will be rebuilt. - this._markAllSubMeshesAsTexturesDirty(); - } - - /** - * Gets whether the color curves effect is enabled. - */ - public get cameraColorCurvesEnabled(): boolean { - return (this.imageProcessingConfiguration).colorCurvesEnabled; - } - /** - * Sets whether the color curves effect is enabled. - */ - public set cameraColorCurvesEnabled(value: boolean) { - (this.imageProcessingConfiguration).colorCurvesEnabled = value; - } - - /** - * Gets whether the color grading effect is enabled. - */ - public get cameraColorGradingEnabled(): boolean { - return (this.imageProcessingConfiguration).colorGradingEnabled; - } - /** - * Gets whether the color grading effect is enabled. - */ - public set cameraColorGradingEnabled(value: boolean) { - (this.imageProcessingConfiguration).colorGradingEnabled = value; - } - - /** - * Gets whether tonemapping is enabled or not. - */ - public get cameraToneMappingEnabled(): boolean { - return this._imageProcessingConfiguration.toneMappingEnabled; - } - /** - * Sets whether tonemapping is enabled or not - */ - public set cameraToneMappingEnabled(value: boolean) { - this._imageProcessingConfiguration.toneMappingEnabled = value; - } - - /** - * The camera exposure used on this material. - * This property is here and not in the camera to allow controlling exposure without full screen post process. - * This corresponds to a photographic exposure. - */ - public get cameraExposure(): float { - return this._imageProcessingConfiguration.exposure; - } - /** - * The camera exposure used on this material. - * This property is here and not in the camera to allow controlling exposure without full screen post process. - * This corresponds to a photographic exposure. - */ - public set cameraExposure(value: float) { - this._imageProcessingConfiguration.exposure = value; - } - - /** - * Gets The camera contrast used on this material. - */ - public get cameraContrast(): float { - return this._imageProcessingConfiguration.contrast; - } - - /** - * Sets The camera contrast used on this material. - */ - public set cameraContrast(value: float) { - this._imageProcessingConfiguration.contrast = value; - } - - /** - * Gets the Color Grading 2D Lookup Texture. - */ - public get cameraColorGradingTexture(): Nullable { - return this._imageProcessingConfiguration.colorGradingTexture; - } - /** - * Sets the Color Grading 2D Lookup Texture. - */ - public set cameraColorGradingTexture(value: Nullable) { - (this.imageProcessingConfiguration).colorGradingTexture = value; - } - - /** - * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). - * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. - * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; - * corresponding to low luminance, medium luminance, and high luminance areas respectively. - */ - public get cameraColorCurves(): Nullable { - return (this.imageProcessingConfiguration).colorCurves; - } - /** - * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). - * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. - * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; - * corresponding to low luminance, medium luminance, and high luminance areas respectively. - */ - public set cameraColorCurves(value: Nullable) { - (this.imageProcessingConfiguration).colorCurves = value; - } - /** * Due to a bug in iOS10, video tags (which are using the background material) are in BGR and not RGB. * Setting this flag to true (not done automatically!) will convert it back to RGB. diff --git a/packages/dev/core/src/Materials/PBR/index.ts b/packages/dev/core/src/Materials/PBR/index.ts index a04f9cd3f91..c97b2aa4adc 100644 --- a/packages/dev/core/src/Materials/PBR/index.ts +++ b/packages/dev/core/src/Materials/PBR/index.ts @@ -5,7 +5,7 @@ export * from "./pbrBRDFConfiguration"; export * from "./pbrClearCoatConfiguration"; export * from "./pbrIridescenceConfiguration"; export * from "./pbrMaterial"; -export * from "./pbrMaterial2"; +export * from "./pbr2Material"; export * from "./pbrMetallicRoughnessMaterial"; export * from "./pbrSpecularGlossinessMaterial"; export * from "./pbrSheenConfiguration"; diff --git a/packages/dev/core/src/Materials/PBR/pbrMaterial2.ts b/packages/dev/core/src/Materials/PBR/pbr2Material.ts similarity index 89% rename from packages/dev/core/src/Materials/PBR/pbrMaterial2.ts rename to packages/dev/core/src/Materials/PBR/pbr2Material.ts index 4d29c78ff02..bffc22fa70a 100644 --- a/packages/dev/core/src/Materials/PBR/pbrMaterial2.ts +++ b/packages/dev/core/src/Materials/PBR/pbr2Material.ts @@ -3,9 +3,8 @@ import { serialize, serializeAsColor3, expandToProperty, serializeAsTexture } fr import { GetEnvironmentBRDFTexture } from "../../Misc/brdfTextureTools"; import type { Nullable } from "../../types"; import type { Scene } from "../../scene"; -import { Color3 } from "../../Maths/math.color"; -import { ImageProcessingConfiguration } from "../../Materials/imageProcessingConfiguration"; -import type { ColorCurves } from "../../Materials/colorCurves"; +import { Color3, Color4 } from "../../Maths/math.color"; +import { ImageProcessingConfiguration } from "../imageProcessingConfiguration"; import type { BaseTexture } from "../../Materials/Textures/baseTexture"; import { PBRBaseMaterial } from "./pbrBaseMaterial"; import { RegisterClass } from "../../Misc/typeStore"; @@ -14,8 +13,8 @@ import { SerializationHelper } from "../../Misc/decorators.serialization"; import type { AbstractMesh } from "../../Meshes/abstractMesh"; import type { Effect, IEffectCreationOptions } from "../../Materials/effect"; -import { MaterialDefines } from "../../Materials/materialDefines"; -import { ImageProcessingDefinesMixin } from "../../Materials/imageProcessingConfiguration.defines"; +import { MaterialDefines } from "../materialDefines"; +import { ImageProcessingDefinesMixin } from "../imageProcessingConfiguration.defines"; import { EffectFallbacks } from "../effectFallbacks"; import { AddClipPlaneUniforms } from "../clipPlaneMaterialHelper"; import { @@ -48,35 +47,69 @@ import { PrePassConfiguration } from "../prePassConfiguration"; import type { IMaterialCompilationOptions, ICustomShaderNameResolveOptions } from "../../Materials/material"; import { ShaderLanguage } from "../shaderLanguage"; import { MaterialFlags } from "../materialFlags"; -import { Texture } from "../../Materials/Textures/texture"; +import { Texture } from "../Textures/texture"; import type { SubMesh } from "../../Meshes/subMesh"; import { Logger } from "core/Misc/logger"; +import { UVDefinesMixin } from "../uv.defines"; +import { Vector2, Vector3, Vector4 } from "core/Maths/math.vector"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; -class PBRMaterial2DefinesBase extends MaterialDefines {} +/** + * Defines a property for the PBR2Material. + */ +class Property { + /** + * Creates a new Property instance. + * @param name The name of the property in the shader + * @param defaultValue The default value of the property + * @param value The current value of the property, defaults to defaultValue + */ + constructor( + public name: string, + public defaultValue: T, + public value: T = defaultValue + ) {} + + /** + * Returns the number of components of the property based on its type. + */ + public get numComponents(): number { + if (typeof this.defaultValue === "number") { + return 1; // Single float + } else if (this.defaultValue instanceof Color3) { + return 3; + } else if (this.defaultValue instanceof Color4) { + return 4; + } else if (this.defaultValue instanceof Vector2) { + return 2; + } else if (this.defaultValue instanceof Vector3) { + return 3; + } else if (this.defaultValue instanceof Vector4) { + return 4; + } + return 0; // Default size for unsupported types + } +} + +class Sampler { + constructor( + public name: string, // Name in the shader + public value: Nullable = null // Texture value, default to null + ) {} +} + +class PBR2MaterialDefinesBase extends UVDefinesMixin(MaterialDefines) {} /** * Manages the defines for the PBR Material. * @internal */ -export class PBRMaterial2Defines extends ImageProcessingDefinesMixin(PBRMaterial2DefinesBase) { +export class PBR2MaterialDefines extends ImageProcessingDefinesMixin(PBR2MaterialDefinesBase) { public PBR = true; public NUM_SAMPLES = "0"; public REALTIME_FILTERING = false; public IBL_CDF_FILTERING = false; - public MAINUV1 = false; - public MAINUV2 = false; - public MAINUV3 = false; - public MAINUV4 = false; - public MAINUV5 = false; - public MAINUV6 = false; - public UV1 = false; - public UV2 = false; - public UV3 = false; - public UV4 = false; - public UV5 = false; - public UV6 = false; public ALBEDO = false; public GAMMAALBEDO = false; @@ -84,9 +117,7 @@ export class PBRMaterial2Defines extends ImageProcessingDefinesMixin(PBRMaterial public VERTEXCOLOR = false; public BASE_WEIGHT = false; - public BASE_WEIGHTDIRECTUV = 0; public BASE_DIFFUSE_ROUGHNESS = false; - public BASE_DIFFUSE_ROUGHNESSDIRECTUV = 0; public BAKED_VERTEX_ANIMATION_TEXTURE = false; @@ -288,6 +319,7 @@ export class PBRMaterial2Defines extends ImageProcessingDefinesMixin(PBRMaterial } } +// class PBR2MaterialBase extends ImageProcessingMixin(PBRBaseMaterial) {} /** * The Physically based material of BJS. * @@ -295,24 +327,24 @@ export class PBRMaterial2Defines extends ImageProcessingDefinesMixin(PBRMaterial * For more information, please refer to the documentation : * https://doc.babylonjs.com/features/featuresDeepDive/materials/using/introToPBR */ -export class PBRMaterial2 extends PBRBaseMaterial { +export class PBR2Material extends PBRBaseMaterial { /** - * PBRMaterial2TransparencyMode: No transparency mode, Alpha channel is not use. + * PBR2MaterialTransparencyMode: No transparency mode, Alpha channel is not use. */ public static override readonly PBRMATERIAL_OPAQUE = PBRBaseMaterial.PBRMATERIAL_OPAQUE; /** - * PBRMaterial2TransparencyMode: Alpha Test mode, pixel are discarded below a certain threshold defined by the alpha cutoff value. + * PBR2MaterialTransparencyMode: Alpha Test mode, pixel are discarded below a certain threshold defined by the alpha cutoff value. */ public static override readonly PBRMATERIAL_ALPHATEST = PBRBaseMaterial.PBRMATERIAL_ALPHATEST; /** - * PBRMaterial2TransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. + * PBR2MaterialTransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. */ public static override readonly PBRMATERIAL_ALPHABLEND = PBRBaseMaterial.PBRMATERIAL_ALPHABLEND; /** - * PBRMaterial2TransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. + * PBR2MaterialTransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. * They are also discarded below the alpha cutoff threshold to improve performances. */ public static override readonly PBRMATERIAL_ALPHATESTANDBLEND = PBRBaseMaterial.PBRMATERIAL_ALPHATESTANDBLEND; @@ -323,6 +355,28 @@ export class PBRMaterial2 extends PBRBaseMaterial { */ public static override DEFAULT_AO_ON_ANALYTICAL_LIGHTS = PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; + /** + * Base Color uniform property. + */ + get baseColor(): Color3 { + return this._baseColor.value; + } + set baseColor(color: Color3) { + this._baseColor.value = color; + } + private _baseColor: Property = new Property("baseColor", Color3.White()); + + /** + * Base Color Texture property. + */ + get baseColorTexture(): Nullable { + return this._baseColorTexture.value; + } + set baseColorTexture(texture: Nullable) { + this._baseColorTexture.value = texture; + } + private _baseColorTexture: Sampler = new Sampler("baseColor"); + /** * Intensity of the direct lights e.g. the four lights available in your scene. * This impacts both the direct diffuse and specular highlights. @@ -404,7 +458,7 @@ export class PBRMaterial2 extends PBRBaseMaterial { */ @serialize() @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public ambientTextureImpactOnAnalyticalLights: number = PBRMaterial2.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; + public ambientTextureImpactOnAnalyticalLights: number = PBR2Material.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; /** * Stores the alpha values in a texture. Use luminance if texture.getAlphaFromRGB is true. @@ -935,128 +989,7 @@ export class PBRMaterial2 extends PBRBaseMaterial { public applyDecalMapAfterDetailMap = false; /** - * Gets the image processing configuration used either in this material. - */ - public get imageProcessingConfiguration(): ImageProcessingConfiguration { - return this._imageProcessingConfiguration; - } - - /** - * Sets the Default image processing configuration used either in the this material. - * - * If sets to null, the scene one is in use. - */ - public set imageProcessingConfiguration(value: ImageProcessingConfiguration) { - this._attachImageProcessingConfiguration(value); - - // Ensure the effect will be rebuilt. - this._markAllSubMeshesAsImageProcessingDirty(); - } - - /** - * Gets whether the color curves effect is enabled. - */ - public get cameraColorCurvesEnabled(): boolean { - return this.imageProcessingConfiguration.colorCurvesEnabled; - } - /** - * Sets whether the color curves effect is enabled. - */ - public set cameraColorCurvesEnabled(value: boolean) { - this.imageProcessingConfiguration.colorCurvesEnabled = value; - } - - /** - * Gets whether the color grading effect is enabled. - */ - public get cameraColorGradingEnabled(): boolean { - return this.imageProcessingConfiguration.colorGradingEnabled; - } - /** - * Gets whether the color grading effect is enabled. - */ - public set cameraColorGradingEnabled(value: boolean) { - this.imageProcessingConfiguration.colorGradingEnabled = value; - } - - /** - * Gets whether tonemapping is enabled or not. - */ - public get cameraToneMappingEnabled(): boolean { - return this._imageProcessingConfiguration.toneMappingEnabled; - } - /** - * Sets whether tonemapping is enabled or not - */ - public set cameraToneMappingEnabled(value: boolean) { - this._imageProcessingConfiguration.toneMappingEnabled = value; - } - - /** - * The camera exposure used on this material. - * This property is here and not in the camera to allow controlling exposure without full screen post process. - * This corresponds to a photographic exposure. - */ - public get cameraExposure(): number { - return this._imageProcessingConfiguration.exposure; - } - /** - * The camera exposure used on this material. - * This property is here and not in the camera to allow controlling exposure without full screen post process. - * This corresponds to a photographic exposure. - */ - public set cameraExposure(value: number) { - this._imageProcessingConfiguration.exposure = value; - } - - /** - * Gets The camera contrast used on this material. - */ - public get cameraContrast(): number { - return this._imageProcessingConfiguration.contrast; - } - - /** - * Sets The camera contrast used on this material. - */ - public set cameraContrast(value: number) { - this._imageProcessingConfiguration.contrast = value; - } - - /** - * Gets the Color Grading 2D Lookup Texture. - */ - public get cameraColorGradingTexture(): Nullable { - return this._imageProcessingConfiguration.colorGradingTexture; - } - /** - * Sets the Color Grading 2D Lookup Texture. - */ - public set cameraColorGradingTexture(value: Nullable) { - this._imageProcessingConfiguration.colorGradingTexture = value; - } - - /** - * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). - * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. - * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; - * corresponding to low luminance, medium luminance, and high luminance areas respectively. - */ - public get cameraColorCurves(): Nullable { - return this._imageProcessingConfiguration.colorCurves; - } - /** - * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). - * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. - * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; - * corresponding to low luminance, medium luminance, and high luminance areas respectively. - */ - public set cameraColorCurves(value: Nullable) { - this._imageProcessingConfiguration.colorCurves = value; - } - - /** - * Instantiates a new PBRMaterial2 instance. + * Instantiates a new PBR2Material instance. * * @param name The material name * @param scene The scene the material will be use in. @@ -1064,7 +997,6 @@ export class PBRMaterial2 extends PBRBaseMaterial { */ constructor(name: string, scene?: Scene, forceGLSL = false) { super(name, scene, forceGLSL); - this._environmentBRDFTexture = GetEnvironmentBRDFTexture(this.getScene()); } @@ -1072,7 +1004,7 @@ export class PBRMaterial2 extends PBRBaseMaterial { * @returns the name of this material class. */ public override getClassName(): string { - return "PBRMaterial2"; + return "gi"; } /** @@ -1082,8 +1014,8 @@ export class PBRMaterial2 extends PBRBaseMaterial { * @param rootUrl defines the root URL to use to load textures * @returns cloned material instance */ - public override clone(name: string, cloneTexturesOnlyOnce: boolean = true, rootUrl = ""): PBRMaterial2 { - const clone = SerializationHelper.Clone(() => new PBRMaterial2(name, this.getScene()), this, { cloneTexturesOnlyOnce }); + public override clone(name: string, cloneTexturesOnlyOnce: boolean = true, rootUrl = ""): PBR2Material { + const clone = SerializationHelper.Clone(() => new PBR2Material(name, this.getScene()), this, { cloneTexturesOnlyOnce }); clone.id = name; clone.name = name; @@ -1101,7 +1033,7 @@ export class PBRMaterial2 extends PBRBaseMaterial { */ public override serialize(): any { const serializationObject = super.serialize(); - serializationObject.customType = "BABYLON.PBRMaterial2"; + serializationObject.customType = "BABYLON.PBR2Material"; return serializationObject; } @@ -1112,10 +1044,10 @@ export class PBRMaterial2 extends PBRBaseMaterial { * @param source - Serialized object. * @param scene - BJS scene instance. * @param rootUrl - url for the scene object - * @returns - PBRMaterial2 + * @returns - PBR2Material */ - public static override Parse(source: any, scene: Scene, rootUrl: string): PBRMaterial2 { - const material = SerializationHelper.Parse(() => new PBRMaterial2(source.name, scene), source, scene, rootUrl); + public static override Parse(source: any, scene: Scene, rootUrl: string): PBR2Material { + const material = SerializationHelper.Parse(() => new PBR2Material(source.name, scene), source, scene, rootUrl); if (source.stencil) { material.stencil.parse(source.stencil, scene, rootUrl); @@ -1168,7 +1100,7 @@ export class PBRMaterial2 extends PBRBaseMaterial { if (this._breakShaderLoadedCheck2) { return; } - const defines = new PBRMaterial2Defines(this._eventInfo.defineNames); + const defines = new PBR2MaterialDefines(this._eventInfo.defineNames); const effect = this._prepareEffect2(mesh, defines, undefined, undefined, localOptions.useInstances, localOptions.clipPlane, mesh.hasThinInstances)!; if (this._onEffectCreatedObservable) { onCreatedEffectParameters.effect = effect; @@ -1212,10 +1144,10 @@ export class PBRMaterial2 extends PBRBaseMaterial { if (!subMesh.materialDefines) { this._callbackPluginEventGeneric(MaterialPluginEvent.GetDefineNames, this._eventInfo); - subMesh.materialDefines = new PBRMaterial2Defines(this._eventInfo.defineNames); + subMesh.materialDefines = new PBR2MaterialDefines(this._eventInfo.defineNames); } - const defines = subMesh.materialDefines; + const defines = subMesh.materialDefines; if (this._isReadyForSubMesh(subMesh)) { return true; } @@ -1359,7 +1291,7 @@ export class PBRMaterial2 extends PBRBaseMaterial { if (!engine.getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) { mesh.createNormals(true); - Logger.Warn("PBRMaterial2: Normals have been created for the mesh: " + mesh.name); + Logger.Warn("PBR2Material: Normals have been created for the mesh: " + mesh.name); } const previousEffect = subMesh.effect; @@ -1408,7 +1340,7 @@ export class PBRMaterial2 extends PBRBaseMaterial { private _prepareEffect2( mesh: AbstractMesh, - defines: PBRMaterial2Defines, + defines: PBR2MaterialDefines, onCompiled: Nullable<(effect: Effect) => void> = null, onError: Nullable<(effect: Effect, errors: string) => void> = null, useInstances: Nullable = null, @@ -1723,7 +1655,7 @@ export class PBRMaterial2 extends PBRBaseMaterial { private _prepareDefines2( mesh: AbstractMesh, - defines: PBRMaterial2Defines, + defines: PBR2MaterialDefines, useInstances: Nullable = null, useClipPlane: Nullable = null, useThinInstances: boolean = false @@ -1756,8 +1688,6 @@ export class PBRMaterial2 extends PBRBaseMaterial { } if (scene.texturesEnabled) { defines.ALBEDODIRECTUV = 0; - defines.BASE_WEIGHTDIRECTUV = 0; - defines.BASE_DIFFUSE_ROUGHNESSDIRECTUV = 0; defines.AMBIENTDIRECTUV = 0; defines.OPACITYDIRECTUV = 0; defines.EMISSIVEDIRECTUV = 0; @@ -2118,4 +2048,4 @@ export class PBRMaterial2 extends PBRBaseMaterial { private _breakShaderLoadedCheck2 = false; } -RegisterClass("BABYLON.PBRMaterial2", PBRMaterial2); +RegisterClass("BABYLON.PBR2Material", PBR2Material); diff --git a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts index b2cf5bc8615..83b2bcdded8 100644 --- a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { serializeAsImageProcessingConfiguration, expandToProperty } from "../../Misc/decorators"; -import type { Observer } from "../../Misc/observable"; +import { expandToProperty } from "../../Misc/decorators"; import { Logger } from "../../Misc/logger"; import { SmartArray } from "../../Misc/smartArray"; import { GetEnvironmentBRDFTexture } from "../../Misc/brdfTextureTools"; @@ -69,6 +68,7 @@ import { import { ShaderLanguage } from "../shaderLanguage"; import { MaterialHelperGeometryRendering } from "../materialHelper.geometryrendering"; import { UVDefinesMixin } from "../uv.defines"; +import { ImageProcessingMixin } from "../imageProcessing"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; @@ -295,6 +295,7 @@ export class PBRMaterialDefines extends ImageProcessingDefinesMixin(PBRMaterialD } } +class PBRBaseMaterialBase extends ImageProcessingMixin(PushMaterial) {} /** * The Physically based material base class of BJS. * @@ -304,7 +305,7 @@ export class PBRMaterialDefines extends ImageProcessingDefinesMixin(PBRMaterialD * @see [WebGL](https://playground.babylonjs.com/#CGHTSM#1) * @see [WebGPU](https://playground.babylonjs.com/#CGHTSM#2) */ -export abstract class PBRBaseMaterial extends PushMaterial { +export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { /** * PBRMaterialTransparencyMode: No transparency mode, Alpha channel is not use. */ @@ -814,46 +815,6 @@ export abstract class PBRBaseMaterial extends PushMaterial { */ public _enableSpecularAntiAliasing = false; - /** - * Default configuration related to image processing available in the PBR Material. - */ - @serializeAsImageProcessingConfiguration() - protected _imageProcessingConfiguration: ImageProcessingConfiguration; - - /** - * Keep track of the image processing observer to allow dispose and replace. - */ - private _imageProcessingObserver: Nullable> = null; - - /** - * Attaches a new image processing configuration to the PBR Material. - * @param configuration - */ - protected _attachImageProcessingConfiguration(configuration: Nullable): void { - if (configuration === this._imageProcessingConfiguration) { - return; - } - - // Detaches observer. - if (this._imageProcessingConfiguration && this._imageProcessingObserver) { - this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver); - } - - // Pick the scene configuration if needed. - if (!configuration) { - this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration; - } else { - this._imageProcessingConfiguration = configuration; - } - - // Attaches observer. - if (this._imageProcessingConfiguration) { - this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(() => { - this._markAllSubMeshesAsImageProcessingDirty(); - }); - } - } - /** * Stores the available render targets. */ diff --git a/packages/dev/core/src/Materials/PBR/pbrMaterial.ts b/packages/dev/core/src/Materials/PBR/pbrMaterial.ts index 212a3a0c30b..366acf92344 100644 --- a/packages/dev/core/src/Materials/PBR/pbrMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/pbrMaterial.ts @@ -3,8 +3,6 @@ import { GetEnvironmentBRDFTexture } from "../../Misc/brdfTextureTools"; import type { Nullable } from "../../types"; import type { Scene } from "../../scene"; import { Color3 } from "../../Maths/math.color"; -import type { ImageProcessingConfiguration } from "../../Materials/imageProcessingConfiguration"; -import type { ColorCurves } from "../../Materials/colorCurves"; import type { BaseTexture } from "../../Materials/Textures/baseTexture"; import { PBRBaseMaterial } from "./pbrBaseMaterial"; import { RegisterClass } from "../../Misc/typeStore"; @@ -657,127 +655,6 @@ export class PBRMaterial extends PBRBaseMaterial { @expandToProperty("_markAllSubMeshesAsMiscDirty") public applyDecalMapAfterDetailMap = false; - /** - * Gets the image processing configuration used either in this material. - */ - public get imageProcessingConfiguration(): ImageProcessingConfiguration { - return this._imageProcessingConfiguration; - } - - /** - * Sets the Default image processing configuration used either in the this material. - * - * If sets to null, the scene one is in use. - */ - public set imageProcessingConfiguration(value: ImageProcessingConfiguration) { - this._attachImageProcessingConfiguration(value); - - // Ensure the effect will be rebuilt. - this._markAllSubMeshesAsImageProcessingDirty(); - } - - /** - * Gets whether the color curves effect is enabled. - */ - public get cameraColorCurvesEnabled(): boolean { - return this.imageProcessingConfiguration.colorCurvesEnabled; - } - /** - * Sets whether the color curves effect is enabled. - */ - public set cameraColorCurvesEnabled(value: boolean) { - this.imageProcessingConfiguration.colorCurvesEnabled = value; - } - - /** - * Gets whether the color grading effect is enabled. - */ - public get cameraColorGradingEnabled(): boolean { - return this.imageProcessingConfiguration.colorGradingEnabled; - } - /** - * Gets whether the color grading effect is enabled. - */ - public set cameraColorGradingEnabled(value: boolean) { - this.imageProcessingConfiguration.colorGradingEnabled = value; - } - - /** - * Gets whether tonemapping is enabled or not. - */ - public get cameraToneMappingEnabled(): boolean { - return this._imageProcessingConfiguration.toneMappingEnabled; - } - /** - * Sets whether tonemapping is enabled or not - */ - public set cameraToneMappingEnabled(value: boolean) { - this._imageProcessingConfiguration.toneMappingEnabled = value; - } - - /** - * The camera exposure used on this material. - * This property is here and not in the camera to allow controlling exposure without full screen post process. - * This corresponds to a photographic exposure. - */ - public get cameraExposure(): number { - return this._imageProcessingConfiguration.exposure; - } - /** - * The camera exposure used on this material. - * This property is here and not in the camera to allow controlling exposure without full screen post process. - * This corresponds to a photographic exposure. - */ - public set cameraExposure(value: number) { - this._imageProcessingConfiguration.exposure = value; - } - - /** - * Gets The camera contrast used on this material. - */ - public get cameraContrast(): number { - return this._imageProcessingConfiguration.contrast; - } - - /** - * Sets The camera contrast used on this material. - */ - public set cameraContrast(value: number) { - this._imageProcessingConfiguration.contrast = value; - } - - /** - * Gets the Color Grading 2D Lookup Texture. - */ - public get cameraColorGradingTexture(): Nullable { - return this._imageProcessingConfiguration.colorGradingTexture; - } - /** - * Sets the Color Grading 2D Lookup Texture. - */ - public set cameraColorGradingTexture(value: Nullable) { - this._imageProcessingConfiguration.colorGradingTexture = value; - } - - /** - * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). - * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. - * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; - * corresponding to low luminance, medium luminance, and high luminance areas respectively. - */ - public get cameraColorCurves(): Nullable { - return this._imageProcessingConfiguration.colorCurves; - } - /** - * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). - * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. - * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; - * corresponding to low luminance, medium luminance, and high luminance areas respectively. - */ - public set cameraColorCurves(value: Nullable) { - this._imageProcessingConfiguration.colorCurves = value; - } - /** * Instantiates a new PBRMaterial instance. * diff --git a/packages/dev/core/src/Materials/imageProcessing.ts b/packages/dev/core/src/Materials/imageProcessing.ts new file mode 100644 index 00000000000..639d1061c9a --- /dev/null +++ b/packages/dev/core/src/Materials/imageProcessing.ts @@ -0,0 +1,193 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { serializeAsImageProcessingConfiguration } from "../Misc/decorators"; +import type { Nullable } from "../types"; +import type { ImageProcessingConfiguration } from "./imageProcessingConfiguration"; +import type { Observer } from "../Misc/observable"; +import type { BaseTexture } from "../Materials/Textures/baseTexture"; +import type { ColorCurves } from "../Materials/colorCurves"; + +type Constructor = new (...args: any[]) => T; + +/** + * Mixin to add Image processing defines to your material defines + * @internal + */ +export function ImageProcessingMixin(base: Tbase) { + return class extends base { + /** + * Constructor for the ImageProcessingMixin. + * @param args - arguments to pass to the base class constructor + */ + constructor(...args: any[]) { + super(...args); + // Decorators don't work on this annonymous class + // so I'm setting this up manually. + const fn = serializeAsImageProcessingConfiguration(); + fn.call(this, this, "_imageProcessingConfiguration"); + } + /** + * Default configuration related to image processing available in the standard Material. + */ + public _imageProcessingConfiguration: ImageProcessingConfiguration; + + /** + * Gets the image processing configuration used either in this material. + */ + public get imageProcessingConfiguration(): ImageProcessingConfiguration { + return this._imageProcessingConfiguration; + } + + /** + * Sets the Default image processing configuration used either in the this material. + * + * If sets to null, the scene one is in use. + */ + public set imageProcessingConfiguration(value: ImageProcessingConfiguration) { + this._attachImageProcessingConfiguration(value); + + // Ensure the effect will be rebuilt. + if ((this as any)._markAllSubMeshesAsImageProcessingDirty) { + (this as any)._markAllSubMeshesAsImageProcessingDirty(); + } + } + + /** + * Keep track of the image processing observer to allow dispose and replace. + */ + public _imageProcessingObserver: Nullable>; + + /** + * Attaches a new image processing configuration to the Standard Material. + * @param configuration + */ + public _attachImageProcessingConfiguration(configuration: Nullable): void { + if (configuration === this._imageProcessingConfiguration) { + return; + } + + // Detaches observer + if (this._imageProcessingConfiguration && this._imageProcessingObserver) { + this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver); + } + + // Pick the scene configuration if needed + if (!configuration && (this as any).getScene) { + this._imageProcessingConfiguration = (this as any).getScene().imageProcessingConfiguration; + } else if (configuration) { + this._imageProcessingConfiguration = configuration; + } + + // Attaches observer + if (this._imageProcessingConfiguration) { + this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(() => { + // Ensure the effect will be rebuilt. + if ((this as any)._markAllSubMeshesAsImageProcessingDirty) { + (this as any)._markAllSubMeshesAsImageProcessingDirty(); + } + }); + } + } + + /** + * Gets whether the color curves effect is enabled. + */ + public get cameraColorCurvesEnabled(): boolean { + return this.imageProcessingConfiguration.colorCurvesEnabled; + } + /** + * Sets whether the color curves effect is enabled. + */ + public set cameraColorCurvesEnabled(value: boolean) { + this.imageProcessingConfiguration.colorCurvesEnabled = value; + } + + /** + * Gets whether the color grading effect is enabled. + */ + public get cameraColorGradingEnabled(): boolean { + return this.imageProcessingConfiguration.colorGradingEnabled; + } + /** + * Gets whether the color grading effect is enabled. + */ + public set cameraColorGradingEnabled(value: boolean) { + this.imageProcessingConfiguration.colorGradingEnabled = value; + } + + /** + * Gets whether tonemapping is enabled or not. + */ + public get cameraToneMappingEnabled(): boolean { + return this._imageProcessingConfiguration.toneMappingEnabled; + } + /** + * Sets whether tonemapping is enabled or not + */ + public set cameraToneMappingEnabled(value: boolean) { + this._imageProcessingConfiguration.toneMappingEnabled = value; + } + + /** + * The camera exposure used on this material. + * This property is here and not in the camera to allow controlling exposure without full screen post process. + * This corresponds to a photographic exposure. + */ + public get cameraExposure(): number { + return this._imageProcessingConfiguration.exposure; + } + /** + * The camera exposure used on this material. + * This property is here and not in the camera to allow controlling exposure without full screen post process. + * This corresponds to a photographic exposure. + */ + public set cameraExposure(value: number) { + this._imageProcessingConfiguration.exposure = value; + } + + /** + * Gets The camera contrast used on this material. + */ + public get cameraContrast(): number { + return this._imageProcessingConfiguration.contrast; + } + + /** + * Sets The camera contrast used on this material. + */ + public set cameraContrast(value: number) { + this._imageProcessingConfiguration.contrast = value; + } + + /** + * Gets the Color Grading 2D Lookup Texture. + */ + public get cameraColorGradingTexture(): Nullable { + return this._imageProcessingConfiguration.colorGradingTexture; + } + /** + * Sets the Color Grading 2D Lookup Texture. + */ + public set cameraColorGradingTexture(value: Nullable) { + this._imageProcessingConfiguration.colorGradingTexture = value; + } + + /** + * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT). + * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. + * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; + * corresponding to low luminance, medium luminance, and high luminance areas respectively. + */ + public get cameraColorCurves(): Nullable { + return this._imageProcessingConfiguration.colorCurves; + } + /** + * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). + * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. + * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; + * corresponding to low luminance, medium luminance, and high luminance areas respectively. + */ + public set cameraColorCurves(value: Nullable) { + this._imageProcessingConfiguration.colorCurves = value; + } + }; +} diff --git a/packages/dev/core/src/Materials/standardMaterial.ts b/packages/dev/core/src/Materials/standardMaterial.ts index 4148f04f9c4..f4712d9365d 100644 --- a/packages/dev/core/src/Materials/standardMaterial.ts +++ b/packages/dev/core/src/Materials/standardMaterial.ts @@ -62,6 +62,7 @@ import { SerializationHelper } from "../Misc/decorators.serialization"; import { ShaderLanguage } from "./shaderLanguage"; import { MaterialHelperGeometryRendering } from "./materialHelper.geometryrendering"; import { UVDefinesMixin } from "./uv.defines"; +import { ImageProcessingMixin } from "./imageProcessing"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; @@ -248,12 +249,13 @@ export class StandardMaterialDefines extends ImageProcessingDefinesMixin(Standar } } +class StandardMaterialBase extends ImageProcessingMixin(PushMaterial) {} /** * This is the default material used in Babylon. It is the best trade off between quality * and performances. * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/using/materials_introduction */ -export class StandardMaterial extends PushMaterial { +export class StandardMaterial extends StandardMaterialBase { /** * Force all the standard materials to compile to glsl even on WebGPU engines. * False by default. This is mostly meant for backward compatibility. @@ -600,64 +602,6 @@ export class StandardMaterial extends PushMaterial { @expandToProperty("_markAllSubMeshesAsMiscDirty") public applyDecalMapAfterDetailMap: boolean; - /** - * Default configuration related to image processing available in the standard Material. - */ - protected _imageProcessingConfiguration: ImageProcessingConfiguration; - - /** - * Gets the image processing configuration used either in this material. - */ - public get imageProcessingConfiguration(): ImageProcessingConfiguration { - return this._imageProcessingConfiguration; - } - - /** - * Sets the Default image processing configuration used either in the this material. - * - * If sets to null, the scene one is in use. - */ - public set imageProcessingConfiguration(value: ImageProcessingConfiguration) { - this._attachImageProcessingConfiguration(value); - - // Ensure the effect will be rebuilt. - this._markAllSubMeshesAsImageProcessingDirty(); - } - - /** - * Keep track of the image processing observer to allow dispose and replace. - */ - private _imageProcessingObserver: Nullable>; - - /** - * Attaches a new image processing configuration to the Standard Material. - * @param configuration - */ - protected _attachImageProcessingConfiguration(configuration: Nullable): void { - if (configuration === this._imageProcessingConfiguration) { - return; - } - - // Detaches observer - if (this._imageProcessingConfiguration && this._imageProcessingObserver) { - this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver); - } - - // Pick the scene configuration if needed - if (!configuration) { - this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration; - } else { - this._imageProcessingConfiguration = configuration; - } - - // Attaches observer - if (this._imageProcessingConfiguration) { - this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(() => { - this._markAllSubMeshesAsImageProcessingDirty(); - }); - } - } - private _shadersLoaded = false; /** @@ -672,108 +616,6 @@ export class StandardMaterial extends PushMaterial { return !this.disableDepthWrite; } - /** - * Gets whether the color curves effect is enabled. - */ - public get cameraColorCurvesEnabled(): boolean { - return this.imageProcessingConfiguration.colorCurvesEnabled; - } - /** - * Sets whether the color curves effect is enabled. - */ - public set cameraColorCurvesEnabled(value: boolean) { - this.imageProcessingConfiguration.colorCurvesEnabled = value; - } - - /** - * Gets whether the color grading effect is enabled. - */ - public get cameraColorGradingEnabled(): boolean { - return this.imageProcessingConfiguration.colorGradingEnabled; - } - /** - * Gets whether the color grading effect is enabled. - */ - public set cameraColorGradingEnabled(value: boolean) { - this.imageProcessingConfiguration.colorGradingEnabled = value; - } - - /** - * Gets whether tonemapping is enabled or not. - */ - public get cameraToneMappingEnabled(): boolean { - return this._imageProcessingConfiguration.toneMappingEnabled; - } - /** - * Sets whether tonemapping is enabled or not - */ - public set cameraToneMappingEnabled(value: boolean) { - this._imageProcessingConfiguration.toneMappingEnabled = value; - } - - /** - * The camera exposure used on this material. - * This property is here and not in the camera to allow controlling exposure without full screen post process. - * This corresponds to a photographic exposure. - */ - public get cameraExposure(): number { - return this._imageProcessingConfiguration.exposure; - } - /** - * The camera exposure used on this material. - * This property is here and not in the camera to allow controlling exposure without full screen post process. - * This corresponds to a photographic exposure. - */ - public set cameraExposure(value: number) { - this._imageProcessingConfiguration.exposure = value; - } - - /** - * Gets The camera contrast used on this material. - */ - public get cameraContrast(): number { - return this._imageProcessingConfiguration.contrast; - } - - /** - * Sets The camera contrast used on this material. - */ - public set cameraContrast(value: number) { - this._imageProcessingConfiguration.contrast = value; - } - - /** - * Gets the Color Grading 2D Lookup Texture. - */ - public get cameraColorGradingTexture(): Nullable { - return this._imageProcessingConfiguration.colorGradingTexture; - } - /** - * Sets the Color Grading 2D Lookup Texture. - */ - public set cameraColorGradingTexture(value: Nullable) { - this._imageProcessingConfiguration.colorGradingTexture = value; - } - - /** - * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT). - * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. - * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; - * corresponding to low luminance, medium luminance, and high luminance areas respectively. - */ - public get cameraColorCurves(): Nullable { - return this._imageProcessingConfiguration.colorCurves; - } - /** - * The color grading curves provide additional color adjustment that is applied after any color grading transform (3D LUT). - * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects. - * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; - * corresponding to low luminance, medium luminance, and high luminance areas respectively. - */ - public set cameraColorCurves(value: Nullable) { - this._imageProcessingConfiguration.colorCurves = value; - } - /** * Can this material render to several textures at once */ diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts index ee338f27624..2029a3aaf1f 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -75,7 +75,7 @@ export class EXT_materials_diffuse_roughness implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadDiffuseRoughnessPropertiesAsync(context: string, properties: IEXTMaterialsDiffuseRoughness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts index e2ef0b82009..2a89f37a970 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -71,7 +71,7 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { } private async _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsAnisotropy, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts index 7d51a89c977..438c5e49dda 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -73,7 +73,7 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts index 4b98b0a6193..88185371315 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts @@ -1,7 +1,7 @@ /* eslint-disable github/no-then */ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -78,7 +78,7 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async private _loadTranslucentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDiffuseTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } 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 4061875421d..c4d12526646 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 @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -74,7 +74,7 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadDispersionPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDispersion): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts index c80e9794d50..15b30b78e65 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -71,7 +71,7 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { } private _loadEmissiveProperties(context: string, properties: IKHRMaterialsEmissiveStrength, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts index 480e8eb8df8..b7aefce1d72 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -78,7 +78,7 @@ export class KHR_materials_ior implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts index bfb5304c3dd..1c9a62c37eb 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -73,7 +73,7 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts index 2120598c1d0..54081698e17 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import { Color3 } from "core/Maths/math.color"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -75,7 +75,7 @@ export class KHR_materials_pbrSpecularGlossiness implements IGLTFLoaderExtension // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSpecularGlossinessPropertiesAsync(context: string, properties: IKHRMaterialsPbrSpecularGlossiness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts index a99c04337a5..c4d3aba8b9e 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -75,7 +75,7 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts index e5c5d196148..25d7d3ccf8b 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -84,7 +84,7 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts index 17674b2b99a..a11e95c6f56 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -379,7 +379,7 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } const pbrMaterial = babylonMaterial; diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts index c3dd1019330..15a0390af36 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import { Color3 } from "core/Maths/math.color"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -69,7 +69,7 @@ export class KHR_materials_unlit implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadUnlitPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts index 3929bb97f13..513052f2896 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -82,7 +82,7 @@ export class KHR_materials_volume implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts index b3463735af8..82a6559ba80 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -48,7 +48,7 @@ export class MSFT_minecraftMesh implements IGLTFLoaderExtension { public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { if (extra) { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${extraContext}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index f515f1954bf..f45fc79ed69 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -48,7 +48,7 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { if (extra) { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${extraContext}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index dd3d399c8ec..f3a2fd646bd 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -17,7 +17,7 @@ import { Bone } from "core/Bones/bone"; import { Skeleton } from "core/Bones/skeleton"; import { Material } from "core/Materials/material"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBRMaterial2 } from "core/Materials/PBR/pbrMaterial2"; +import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { ITextureCreationOptions } from "core/Materials/Textures/texture"; import { Texture } from "core/Materials/Textures/texture"; @@ -2128,7 +2128,7 @@ export class GLTFLoader implements IGLTFLoader { } private _loadMaterialMetallicRoughnessPropertiesAsync(context: string, properties: IMaterialPbrMetallicRoughness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } @@ -2230,7 +2230,7 @@ export class GLTFLoader implements IGLTFLoader { this._babylonScene._blockEntityCollection = !!this._assetContainer; let babylonMaterial; if (this.parent.usePBR2) { - babylonMaterial = new PBRMaterial2(name, this._babylonScene); + babylonMaterial = new PBR2Material(name, this._babylonScene); } else { babylonMaterial = new PBRMaterial(name, this._babylonScene); } @@ -2301,7 +2301,7 @@ export class GLTFLoader implements IGLTFLoader { * @returns A promise that resolves when the load is complete */ public loadMaterialBasePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } @@ -2366,7 +2366,7 @@ export class GLTFLoader implements IGLTFLoader { * @param babylonMaterial The Babylon material */ public loadMaterialAlphaProperties(context: string, material: IMaterial, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBRMaterial2)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { throw new Error(`${context}: Material type not supported`); } From d9e91e1bc2595740064f50be642678b5d6e94a7d Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Fri, 20 Jun 2025 14:23:35 -0700 Subject: [PATCH 05/23] Fix compile warnings --- packages/dev/core/src/Materials/standardMaterial.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/dev/core/src/Materials/standardMaterial.ts b/packages/dev/core/src/Materials/standardMaterial.ts index f4712d9365d..93a6dd24d6e 100644 --- a/packages/dev/core/src/Materials/standardMaterial.ts +++ b/packages/dev/core/src/Materials/standardMaterial.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { serialize, serializeAsColor3, expandToProperty, serializeAsFresnelParameters, serializeAsTexture } from "../Misc/decorators"; -import type { Observer } from "../Misc/observable"; import { SmartArray } from "../Misc/smartArray"; import type { IAnimatable } from "../Animations/animatable.interface"; @@ -16,7 +15,6 @@ import { PrePassConfiguration } from "./prePassConfiguration"; import { ImageProcessingDefinesMixin } from "./imageProcessingConfiguration.defines"; import { ImageProcessingConfiguration } from "./imageProcessingConfiguration"; -import type { ColorCurves } from "./colorCurves"; import type { FresnelParameters } from "./fresnelParameters"; import type { ICustomShaderNameResolveOptions } from "../Materials/material"; import { Material } from "../Materials/material"; From 06a6506de3f133ee4ae4fb623c82c3c462e592b5 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Mon, 23 Jun 2025 10:50:18 -0700 Subject: [PATCH 06/23] Fix error with es6 build and imageProcessing mixin --- .../core/src/Materials/Node/nodeMaterial.ts | 64 +------------------ .../core/src/Materials/PBR/pbr2Material.ts | 2 +- .../core/src/Materials/PBR/pbrBaseMaterial.ts | 24 +++---- .../dev/core/src/Materials/imageProcessing.ts | 8 ++- packages/dev/core/src/Materials/index.ts | 2 + .../core/src/Particles/baseParticleSystem.ts | 44 ++----------- 6 files changed, 28 insertions(+), 116 deletions(-) diff --git a/packages/dev/core/src/Materials/Node/nodeMaterial.ts b/packages/dev/core/src/Materials/Node/nodeMaterial.ts index 72660c183d7..d39371bb844 100644 --- a/packages/dev/core/src/Materials/Node/nodeMaterial.ts +++ b/packages/dev/core/src/Materials/Node/nodeMaterial.ts @@ -10,14 +10,12 @@ import { NodeMaterialBuildState } from "./nodeMaterialBuildState"; import type { IEffectCreationOptions } from "../effect"; import { Effect } from "../effect"; import type { BaseTexture } from "../../Materials/Textures/baseTexture"; -import type { Observer } from "../../Misc/observable"; import { Observable } from "../../Misc/observable"; import { NodeMaterialBlockTargets } from "./Enums/nodeMaterialBlockTargets"; import { NodeMaterialBuildStateSharedData } from "./nodeMaterialBuildStateSharedData"; import type { SubMesh } from "../../Meshes/subMesh"; import { MaterialDefines } from "../../Materials/materialDefines"; import type { NodeMaterialOptimizer } from "./Optimizers/nodeMaterialOptimizer"; -import type { ImageProcessingConfiguration } from "../imageProcessingConfiguration"; import type { Nullable } from "../../types"; import { VertexBuffer } from "../../Buffers/buffer"; import { Tools } from "../../Misc/tools"; @@ -73,6 +71,7 @@ import { AbstractEngine } from "../../Engines/abstractEngine"; import type { LoopBlock } from "./Blocks/loopBlock"; import { MaterialHelperGeometryRendering } from "../materialHelper.geometryrendering"; import { UVDefinesMixin } from "../uv.defines"; +import { ImageProcessingMixin } from "../imageProcessing"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; @@ -232,10 +231,11 @@ export type NodeMaterialTextureBlocks = | BiPlanarBlock | PrePassTextureBlock; +class NodeMaterialBase extends ImageProcessingMixin(PushMaterial) {} /** * Class used to create a node based material built by assembling shader blocks */ -export class NodeMaterial extends PushMaterial { +export class NodeMaterial extends NodeMaterialBase { private static _BuildIdGenerator: number = 0; private _options: INodeMaterialOptions; private _vertexCompilationState: NodeMaterialBuildState; @@ -373,30 +373,6 @@ export class NodeMaterial extends PushMaterial { this._options = options; } - /** - * Default configuration related to image processing available in the standard Material. - */ - protected _imageProcessingConfiguration: ImageProcessingConfiguration; - - /** - * Gets the image processing configuration used either in this material. - */ - public get imageProcessingConfiguration(): ImageProcessingConfiguration { - return this._imageProcessingConfiguration; - } - - /** - * Sets the Default image processing configuration used either in the this material. - * - * If sets to null, the scene one is in use. - */ - public set imageProcessingConfiguration(value: ImageProcessingConfiguration) { - this._attachImageProcessingConfiguration(value); - - // Ensure the effect will be rebuilt. - this._markAllSubMeshesAsTexturesDirty(); - } - /** * Gets an array of blocks that needs to be serialized even if they are not yet connected */ @@ -470,40 +446,6 @@ export class NodeMaterial extends PushMaterial { return "NodeMaterial"; } - /** - * Keep track of the image processing observer to allow dispose and replace. - */ - private _imageProcessingObserver: Nullable>; - - /** - * Attaches a new image processing configuration to the Standard Material. - * @param configuration - */ - protected _attachImageProcessingConfiguration(configuration: Nullable): void { - if (configuration === this._imageProcessingConfiguration) { - return; - } - - // Detaches observer. - if (this._imageProcessingConfiguration && this._imageProcessingObserver) { - this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver); - } - - // Pick the scene configuration if needed. - if (!configuration) { - this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration; - } else { - this._imageProcessingConfiguration = configuration; - } - - // Attaches observer. - if (this._imageProcessingConfiguration) { - this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(() => { - this._markAllSubMeshesAsImageProcessingDirty(); - }); - } - } - /** * Get a block by its name * @param name defines the name of the block to retrieve diff --git a/packages/dev/core/src/Materials/PBR/pbr2Material.ts b/packages/dev/core/src/Materials/PBR/pbr2Material.ts index bffc22fa70a..6b37f716207 100644 --- a/packages/dev/core/src/Materials/PBR/pbr2Material.ts +++ b/packages/dev/core/src/Materials/PBR/pbr2Material.ts @@ -5,7 +5,7 @@ import type { Nullable } from "../../types"; import type { Scene } from "../../scene"; import { Color3, Color4 } from "../../Maths/math.color"; import { ImageProcessingConfiguration } from "../imageProcessingConfiguration"; -import type { BaseTexture } from "../../Materials/Textures/baseTexture"; +import type { BaseTexture } from "../Textures/baseTexture"; import { PBRBaseMaterial } from "./pbrBaseMaterial"; import { RegisterClass } from "../../Misc/typeStore"; import { Material } from "../material"; diff --git a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts index 83b2bcdded8..8367075077c 100644 --- a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts @@ -15,25 +15,25 @@ import { PBRBRDFConfiguration } from "./pbrBRDFConfiguration"; import { PrePassConfiguration } from "../prePassConfiguration"; import { Color3, TmpColors } from "../../Maths/math.color"; -import { ImageProcessingDefinesMixin } from "../../Materials/imageProcessingConfiguration.defines"; -import { ImageProcessingConfiguration } from "../../Materials/imageProcessingConfiguration"; -import type { Effect, IEffectCreationOptions } from "../../Materials/effect"; -import type { IMaterialCompilationOptions, ICustomShaderNameResolveOptions } from "../../Materials/material"; -import { Material } from "../../Materials/material"; +import { ImageProcessingDefinesMixin } from "../imageProcessingConfiguration.defines"; +import { ImageProcessingConfiguration } from "../imageProcessingConfiguration"; +import type { Effect, IEffectCreationOptions } from "../effect"; +import type { IMaterialCompilationOptions, ICustomShaderNameResolveOptions } from "../material"; +import { Material } from "../material"; import { MaterialPluginEvent } from "../materialPluginEvent"; -import { MaterialDefines } from "../../Materials/materialDefines"; -import { PushMaterial } from "../../Materials/pushMaterial"; +import { MaterialDefines } from "../materialDefines"; +import { PushMaterial } from "../pushMaterial"; -import type { BaseTexture } from "../../Materials/Textures/baseTexture"; -import { Texture } from "../../Materials/Textures/texture"; -import type { RenderTargetTexture } from "../../Materials/Textures/renderTargetTexture"; -import type { CubeTexture } from "../../Materials/Textures/cubeTexture"; +import type { BaseTexture } from "../Textures/baseTexture"; +import { Texture } from "../Textures/texture"; +import type { RenderTargetTexture } from "../Textures/renderTargetTexture"; +import type { CubeTexture } from "../Textures/cubeTexture"; import { MaterialFlags } from "../materialFlags"; import { Constants } from "../../Engines/constants"; import type { IAnimatable } from "../../Animations/animatable.interface"; -import "../../Materials/Textures/baseTexture.polynomial"; +import "../Textures/baseTexture.polynomial"; import { EffectFallbacks } from "../effectFallbacks"; import { PBRClearCoatConfiguration } from "./pbrClearCoatConfiguration"; diff --git a/packages/dev/core/src/Materials/imageProcessing.ts b/packages/dev/core/src/Materials/imageProcessing.ts index 639d1061c9a..7b9f29727f1 100644 --- a/packages/dev/core/src/Materials/imageProcessing.ts +++ b/packages/dev/core/src/Materials/imageProcessing.ts @@ -3,8 +3,12 @@ import { serializeAsImageProcessingConfiguration } from "../Misc/decorators"; import type { Nullable } from "../types"; import type { ImageProcessingConfiguration } from "./imageProcessingConfiguration"; import type { Observer } from "../Misc/observable"; -import type { BaseTexture } from "../Materials/Textures/baseTexture"; -import type { ColorCurves } from "../Materials/colorCurves"; +import type { BaseTexture } from "./Textures/baseTexture"; +import type { ColorCurves } from "./colorCurves"; + +// Explicit re-export of types to help TypeScript resolve them in declaration files +export type { Observer } from "../Misc/observable"; +export type { ColorCurves } from "./colorCurves"; type Constructor = new (...args: any[]) => T; diff --git a/packages/dev/core/src/Materials/index.ts b/packages/dev/core/src/Materials/index.ts index 5aa74929c47..9c870151530 100644 --- a/packages/dev/core/src/Materials/index.ts +++ b/packages/dev/core/src/Materials/index.ts @@ -5,6 +5,7 @@ export * from "./iEffectFallbacks"; export * from "./effectFallbacks"; export * from "./effect"; export * from "./fresnelParameters"; +export * from "./imageProcessing"; export * from "./imageProcessingConfiguration"; export * from "./material"; export * from "./materialDefines"; @@ -39,6 +40,7 @@ export * from "./meshDebugPluginMaterial"; export * from "./GaussianSplatting/gaussianSplattingMaterial"; export * from "./materialHelper.functions"; export * from "./materialHelper.geometryrendering"; +export * from "./uv.defines"; import "./material.decalMap"; // async-loaded shaders diff --git a/packages/dev/core/src/Particles/baseParticleSystem.ts b/packages/dev/core/src/Particles/baseParticleSystem.ts index 4d082cd9520..dc628b486b7 100644 --- a/packages/dev/core/src/Particles/baseParticleSystem.ts +++ b/packages/dev/core/src/Particles/baseParticleSystem.ts @@ -1,7 +1,6 @@ import type { Nullable } from "../types"; import { Vector2, Vector3 } from "../Maths/math.vector"; import type { AbstractMesh } from "../Meshes/abstractMesh"; -import type { ImageProcessingConfiguration } from "../Materials/imageProcessingConfiguration"; import { ImageProcessingConfigurationDefines } from "../Materials/imageProcessingConfiguration.defines"; import type { ColorGradient, FactorGradient, Color3Gradient, IValueGradient } from "../Misc/gradients"; import type { BoxParticleEmitter } from "../Particles/EmitterTypes/boxParticleEmitter"; @@ -24,14 +23,16 @@ import type { SphereDirectedParticleEmitter, SphereParticleEmitter } from "./Emi import type { CylinderDirectedParticleEmitter, CylinderParticleEmitter } from "./EmitterTypes/cylinderParticleEmitter"; import type { ConeDirectedParticleEmitter, ConeParticleEmitter } from "./EmitterTypes/coneParticleEmitter"; import { RegisterClass } from "../Misc/typeStore"; +import { ImageProcessingMixin } from "core/Materials/imageProcessing"; +class BaseParticleSystemBase extends ImageProcessingMixin(Object) {} /** * This represents the base class for particle system in Babylon. * Particles are often small sprites used to simulate hard-to-reproduce phenomena like fire, smoke, water, or abstract visual effects like magic glitter and faery dust. * Particles can take different shapes while emitted like box, sphere, cone or you can write your custom function. * @example https://doc.babylonjs.com/features/featuresDeepDive/particles/particle_system/particle_system_intro */ -export class BaseParticleSystem implements IClipPlanesHolder { +export class BaseParticleSystem extends BaseParticleSystemBase implements IClipPlanesHolder { /** * Source color is added to the destination color without alpha affecting the result. Great for additive glow effects (fire, magic, lasers) */ @@ -739,44 +740,6 @@ export class BaseParticleSystem implements IClipPlanesHolder { */ protected _imageProcessingConfigurationDefines = new ImageProcessingConfigurationDefines(); - /** - * Default configuration related to image processing available in the standard Material. - */ - protected _imageProcessingConfiguration: Nullable; - - /** - * Gets the image processing configuration used either in this material. - */ - public get imageProcessingConfiguration(): Nullable { - return this._imageProcessingConfiguration; - } - - /** - * Sets the Default image processing configuration used either in the this material. - * - * If sets to null, the scene one is in use. - */ - public set imageProcessingConfiguration(value: Nullable) { - this._attachImageProcessingConfiguration(value); - } - - /** - * Attaches a new image processing configuration to the Standard Material. - * @param configuration - */ - protected _attachImageProcessingConfiguration(configuration: Nullable): void { - if (configuration === this._imageProcessingConfiguration) { - return; - } - - // Pick the scene configuration if needed. - if (!configuration && this._scene) { - this._imageProcessingConfiguration = this._scene.imageProcessingConfiguration; - } else { - this._imageProcessingConfiguration = configuration; - } - } - /** @internal */ protected _reset() {} @@ -810,6 +773,7 @@ export class BaseParticleSystem implements IClipPlanesHolder { * @param name The name of the particle system */ public constructor(name: string) { + super(name); this.id = name; this.name = name; } From e9b9e7e3a2f89315e70ab042a40f5bf2e39d6a18 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Tue, 24 Jun 2025 10:50:09 -0700 Subject: [PATCH 07/23] Separating reflection (IBL) defines and uniforms --- .../Background/backgroundMaterial.ts | 102 +----- .../core/src/Materials/PBR/pbr2Material.ts | 163 +-------- .../core/src/Materials/PBR/pbrBaseMaterial.ts | 289 +-------------- .../src/Materials/materialHelper.functions.ts | 341 +++++++++++++++++- .../core/src/Materials/standardMaterial.ts | 106 +----- .../backgroundUboDeclaration.fx | 7 +- .../ShadersInclude/defaultUboDeclaration.fx | 9 +- .../ShadersInclude/pbrUboDeclaration.fx | 17 +- .../backgroundUboDeclaration.fx | 11 +- .../ShadersInclude/defaultUboDeclaration.fx | 8 +- .../ShadersInclude/pbrUboDeclaration.fx | 17 +- 11 files changed, 431 insertions(+), 639 deletions(-) diff --git a/packages/dev/core/src/Materials/Background/backgroundMaterial.ts b/packages/dev/core/src/Materials/Background/backgroundMaterial.ts index 77ff895e8d0..e8c272d634d 100644 --- a/packages/dev/core/src/Materials/Background/backgroundMaterial.ts +++ b/packages/dev/core/src/Materials/Background/backgroundMaterial.ts @@ -16,7 +16,6 @@ import { PushMaterial } from "../../Materials/pushMaterial"; import { ImageProcessingDefinesMixin } from "../../Materials/imageProcessingConfiguration.defines"; import { ImageProcessingConfiguration } from "../../Materials/imageProcessingConfiguration"; import type { BaseTexture } from "../../Materials/Textures/baseTexture"; -import { Texture } from "../../Materials/Textures/texture"; import type { RenderTargetTexture } from "../../Materials/Textures/renderTargetTexture"; import type { IShadowLight } from "../../Lights/shadowLight"; import { Constants } from "../../Engines/constants"; @@ -32,16 +31,21 @@ import { BindLights, BindLogDepth, BindTextureMatrix, + BindIBLParameters, + BindIBLSamplers, HandleFallbacksForShadows, PrepareAttributesForBones, PrepareAttributesForInstances, PrepareDefinesForAttributes, PrepareDefinesForFrameBoundValues, PrepareDefinesForLights, + PrepareDefinesForIBL, PrepareDefinesForMergedUV, PrepareDefinesForMisc, PrepareDefinesForMultiview, PrepareUniformsAndSamplersList, + PrepareUniformsAndSamplersForIBL, + PrepareUniformLayoutForIBL, } from "../materialHelper.functions"; import { SerializationHelper } from "../../Misc/decorators.serialization"; import { ShaderLanguage } from "../shaderLanguage"; @@ -597,57 +601,14 @@ export class BackgroundMaterial extends BackgroundMaterialBase { } const reflectionTexture = this._reflectionTexture; + PrepareDefinesForIBL(scene, reflectionTexture, defines); if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { if (!reflectionTexture.isReadyOrNotBlocking()) { return false; } - - defines.REFLECTION = true; - defines.GAMMAREFLECTION = reflectionTexture.gammaSpace; - defines.RGBDREFLECTION = reflectionTexture.isRGBD; - defines.REFLECTIONBLUR = this._reflectionBlur > 0; - defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha; defines.EQUIRECTANGULAR_RELFECTION_FOV = this.useEquirectangularFOV; defines.REFLECTIONBGR = this.switchToBGR; - - if (reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE) { - defines.INVERTCUBICMAP = true; - } - - defines.REFLECTIONMAP_3D = reflectionTexture.isCube; - defines.REFLECTIONMAP_OPPOSITEZ = defines.REFLECTIONMAP_3D && this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ; - - switch (reflectionTexture.coordinatesMode) { - case Texture.EXPLICIT_MODE: - defines.REFLECTIONMAP_EXPLICIT = true; - break; - case Texture.PLANAR_MODE: - defines.REFLECTIONMAP_PLANAR = true; - break; - case Texture.PROJECTION_MODE: - defines.REFLECTIONMAP_PROJECTION = true; - break; - case Texture.SKYBOX_MODE: - defines.REFLECTIONMAP_SKYBOX = true; - break; - case Texture.SPHERICAL_MODE: - defines.REFLECTIONMAP_SPHERICAL = true; - break; - case Texture.EQUIRECTANGULAR_MODE: - defines.REFLECTIONMAP_EQUIRECTANGULAR = true; - break; - case Texture.FIXED_EQUIRECTANGULAR_MODE: - defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true; - break; - case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE: - defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true; - break; - case Texture.CUBIC_MODE: - case Texture.INVCUBIC_MODE: - default: - defines.REFLECTIONMAP_CUBIC = true; - break; - } + defines.REFLECTIONBLUR = this._reflectionBlur > 0; if (this.reflectionFresnel) { defines.REFLECTIONFRESNEL = true; @@ -662,25 +623,9 @@ export class BackgroundMaterial extends BackgroundMaterialBase { defines.REFLECTIONFALLOFF = false; } } else { - defines.REFLECTION = false; defines.REFLECTIONFRESNEL = false; defines.REFLECTIONFALLOFF = false; defines.REFLECTIONBLUR = false; - defines.REFLECTIONMAP_3D = false; - defines.REFLECTIONMAP_SPHERICAL = false; - defines.REFLECTIONMAP_PLANAR = false; - defines.REFLECTIONMAP_CUBIC = false; - defines.REFLECTIONMAP_PROJECTION = false; - defines.REFLECTIONMAP_SKYBOX = false; - defines.REFLECTIONMAP_EXPLICIT = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; - defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; - defines.INVERTCUBICMAP = false; - defines.REFLECTIONMAP_OPPOSITEZ = false; - defines.LODINREFLECTIONALPHA = false; - defines.GAMMAREFLECTION = false; - defines.RGBDREFLECTION = false; } } @@ -779,9 +724,6 @@ export class BackgroundMaterial extends BackgroundMaterialBase { "vPrimaryColor", "vPrimaryColorShadow", - "vReflectionInfos", - "reflectionMatrix", - "vReflectionMicrosurfaceInfos", "fFovMultiplier", "shadowLevel", @@ -798,7 +740,8 @@ export class BackgroundMaterial extends BackgroundMaterialBase { ]; AddClipPlaneUniforms(uniforms); - const samplers = ["diffuseSampler", "reflectionSampler", "reflectionSamplerLow", "reflectionSamplerHigh"]; + const samplers = ["diffuseSampler"]; + PrepareUniformsAndSamplersForIBL(uniforms, samplers, false); const uniformBuffers = ["Material", "Scene"]; if (ImageProcessingConfiguration) { @@ -908,10 +851,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase { this._uniformBuffer.addUniform("vPrimaryColor", 4); this._uniformBuffer.addUniform("vPrimaryColorShadow", 4); this._uniformBuffer.addUniform("vDiffuseInfos", 2); - this._uniformBuffer.addUniform("vReflectionInfos", 2); this._uniformBuffer.addUniform("diffuseMatrix", 16); - this._uniformBuffer.addUniform("reflectionMatrix", 16); - this._uniformBuffer.addUniform("vReflectionMicrosurfaceInfos", 3); this._uniformBuffer.addUniform("fFovMultiplier", 1); this._uniformBuffer.addUniform("pointSize", 1); this._uniformBuffer.addUniform("shadowLevel", 1); @@ -920,6 +860,8 @@ export class BackgroundMaterial extends BackgroundMaterialBase { this._uniformBuffer.addUniform("vReflectionControl", 4); this._uniformBuffer.addUniform("projectedGroundInfos", 2); + PrepareUniformLayoutForIBL(this._uniformBuffer, true, false, false); + this._uniformBuffer.create(); } @@ -987,17 +929,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase { BindTextureMatrix(this._diffuseTexture, this._uniformBuffer, "diffuse"); } - if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { - this._uniformBuffer.updateMatrix("reflectionMatrix", reflectionTexture.getReflectionTextureMatrix()); - this._uniformBuffer.updateFloat2("vReflectionInfos", reflectionTexture.level, this._reflectionBlur); - - this._uniformBuffer.updateFloat3( - "vReflectionMicrosurfaceInfos", - reflectionTexture.getSize().width, - reflectionTexture.lodGenerationScale, - reflectionTexture.lodGenerationOffset - ); - } + BindIBLParameters(scene, defines, this._uniformBuffer, reflectionTexture); } if (this.shadowLevel > 0) { @@ -1027,15 +959,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase { } if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { - if (defines.REFLECTIONBLUR && defines.TEXTURELODSUPPORT) { - this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture); - } else if (!defines.REFLECTIONBLUR) { - this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture); - } else { - this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture._lodTextureMid || reflectionTexture); - this._uniformBuffer.setTexture("reflectionSamplerLow", reflectionTexture._lodTextureLow || reflectionTexture); - this._uniformBuffer.setTexture("reflectionSamplerHigh", reflectionTexture._lodTextureHigh || reflectionTexture); - } + BindIBLSamplers(scene, defines, this._uniformBuffer, reflectionTexture); if (defines.REFLECTIONFRESNEL) { this._uniformBuffer.updateFloat3("vBackgroundCenter", this.sceneCenter.x, this.sceneCenter.y, this.sceneCenter.z); diff --git a/packages/dev/core/src/Materials/PBR/pbr2Material.ts b/packages/dev/core/src/Materials/PBR/pbr2Material.ts index 6b37f716207..e16fe3d2dcf 100644 --- a/packages/dev/core/src/Materials/PBR/pbr2Material.ts +++ b/packages/dev/core/src/Materials/PBR/pbr2Material.ts @@ -32,12 +32,14 @@ import { PrepareDefinesForAttributes, PrepareDefinesForFrameBoundValues, PrepareDefinesForLights, + PrepareDefinesForIBL, PrepareDefinesForMergedUV, PrepareDefinesForMisc, PrepareDefinesForMultiview, PrepareDefinesForOIT, PrepareDefinesForPrePass, PrepareUniformsAndSamplersList, + PrepareUniformsAndSamplersForIBL, } from "../materialHelper.functions"; import { Constants } from "../../Engines/constants"; import { VertexBuffer } from "../../Buffers/buffer"; @@ -47,7 +49,6 @@ import { PrePassConfiguration } from "../prePassConfiguration"; import type { IMaterialCompilationOptions, ICustomShaderNameResolveOptions } from "../../Materials/material"; import { ShaderLanguage } from "../shaderLanguage"; import { MaterialFlags } from "../materialFlags"; -import { Texture } from "../Textures/texture"; import type { SubMesh } from "../../Meshes/subMesh"; import { Logger } from "core/Misc/logger"; import { UVDefinesMixin } from "../uv.defines"; @@ -1483,7 +1484,6 @@ export class PBR2Material extends PBRBaseMaterial { "vMetallicReflectanceFactors", "vEmissiveColor", "visibility", - "vReflectionColor", "vFogInfos", "vFogColor", "pointSize", @@ -1492,12 +1492,8 @@ export class PBR2Material extends PBRBaseMaterial { "vBaseDiffuseRoughnessInfos", "vAmbientInfos", "vOpacityInfos", - "vReflectionInfos", - "vReflectionPosition", - "vReflectionSize", "vEmissiveInfos", "vReflectivityInfos", - "vReflectionFilteringInfo", "vMetallicReflectanceInfos", "vReflectanceInfos", "vMicroSurfaceSamplerInfos", @@ -1509,7 +1505,6 @@ export class PBR2Material extends PBRBaseMaterial { "baseDiffuseRoughnessMatrix", "ambientMatrix", "opacityMatrix", - "reflectionMatrix", "emissiveMatrix", "reflectivityMatrix", "normalMatrix", @@ -1520,26 +1515,6 @@ export class PBR2Material extends PBRBaseMaterial { "reflectanceMatrix", "vLightingIntensity", "logarithmicDepthConstant", - "vSphericalX", - "vSphericalY", - "vSphericalZ", - "vSphericalXX_ZZ", - "vSphericalYY_ZZ", - "vSphericalZZ", - "vSphericalXY", - "vSphericalYZ", - "vSphericalZX", - "vSphericalL00", - "vSphericalL1_1", - "vSphericalL10", - "vSphericalL11", - "vSphericalL2_2", - "vSphericalL2_1", - "vSphericalL20", - "vSphericalL21", - "vSphericalL22", - "vReflectionMicrosurfaceInfos", - "vReflectionDominantDirection", "vTangentSpaceParams", "boneTextureWidth", "vDebugMode", @@ -1558,10 +1533,6 @@ export class PBR2Material extends PBRBaseMaterial { "bumpSampler", "lightmapSampler", "opacitySampler", - "reflectionSampler", - "reflectionSamplerLow", - "reflectionSamplerHigh", - "irradianceSampler", "microSurfaceSampler", "environmentBrdfSampler", "boneSampler", @@ -1570,11 +1541,12 @@ export class PBR2Material extends PBRBaseMaterial { "morphTargets", "oitDepthSampler", "oitFrontColorSampler", - "icdfSampler", "areaLightsLTC1Sampler", "areaLightsLTC2Sampler", ]; + PrepareUniformsAndSamplersForIBL(uniforms, samplers, true); + const uniformBuffers = ["Material", "Scene", "Mesh"]; const indexParameters = { maxSimultaneousLights: this._maxSimultaneousLights, maxSimultaneousMorphTargets: defines.NUM_MORPH_INFLUENCERS }; @@ -1736,126 +1708,13 @@ export class PBR2Material extends PBRBaseMaterial { } const reflectionTexture = this._getReflectionTexture2(); - if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { - defines.REFLECTION = true; - defines.GAMMAREFLECTION = reflectionTexture.gammaSpace; - defines.RGBDREFLECTION = reflectionTexture.isRGBD; - defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha; - defines.LINEARSPECULARREFLECTION = reflectionTexture.linearSpecularLOD; - defines.USEIRRADIANCEMAP = false; - - if (this.realTimeFiltering && this.realTimeFilteringQuality > 0) { - defines.NUM_SAMPLES = "" + this.realTimeFilteringQuality; - if (engine._features.needTypeSuffixInShaderConstants) { - defines.NUM_SAMPLES = defines.NUM_SAMPLES + "u"; - } - - defines.REALTIME_FILTERING = true; - if (this.getScene().iblCdfGenerator) { - defines.IBL_CDF_FILTERING = true; - } - } else { - defines.REALTIME_FILTERING = false; - } - - defines.INVERTCUBICMAP = reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE; - defines.REFLECTIONMAP_3D = reflectionTexture.isCube; - defines.REFLECTIONMAP_OPPOSITEZ = defines.REFLECTIONMAP_3D && this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ; - - defines.REFLECTIONMAP_CUBIC = false; - defines.REFLECTIONMAP_EXPLICIT = false; - defines.REFLECTIONMAP_PLANAR = false; - defines.REFLECTIONMAP_PROJECTION = false; - defines.REFLECTIONMAP_SKYBOX = false; - defines.REFLECTIONMAP_SPHERICAL = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; - defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; - - switch (reflectionTexture.coordinatesMode) { - case Texture.EXPLICIT_MODE: - defines.REFLECTIONMAP_EXPLICIT = true; - break; - case Texture.PLANAR_MODE: - defines.REFLECTIONMAP_PLANAR = true; - break; - case Texture.PROJECTION_MODE: - defines.REFLECTIONMAP_PROJECTION = true; - break; - case Texture.SKYBOX_MODE: - defines.REFLECTIONMAP_SKYBOX = true; - break; - case Texture.SPHERICAL_MODE: - defines.REFLECTIONMAP_SPHERICAL = true; - break; - case Texture.EQUIRECTANGULAR_MODE: - defines.REFLECTIONMAP_EQUIRECTANGULAR = true; - break; - case Texture.FIXED_EQUIRECTANGULAR_MODE: - defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true; - break; - case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE: - defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true; - break; - case Texture.CUBIC_MODE: - case Texture.INVCUBIC_MODE: - default: - defines.REFLECTIONMAP_CUBIC = true; - defines.USE_LOCAL_REFLECTIONMAP_CUBIC = (reflectionTexture).boundingBoxSize ? true : false; - break; - } - - if (reflectionTexture.coordinatesMode !== Texture.SKYBOX_MODE) { - if (reflectionTexture.irradianceTexture) { - defines.USEIRRADIANCEMAP = true; - defines.USESPHERICALFROMREFLECTIONMAP = false; - defines.USESPHERICALINVERTEX = false; - if (reflectionTexture.irradianceTexture._dominantDirection) { - defines.USE_IRRADIANCE_DOMINANT_DIRECTION = true; - } - } - // Assume using spherical polynomial if the reflection texture is a cube map - else if (reflectionTexture.isCube) { - defines.USESPHERICALFROMREFLECTIONMAP = true; - defines.USEIRRADIANCEMAP = false; - defines.USE_IRRADIANCE_DOMINANT_DIRECTION = false; - if ( - this._forceIrradianceInFragment || - this.realTimeFiltering || - this._twoSidedLighting || - engine.getCaps().maxVaryingVectors <= 8 || - this._baseDiffuseRoughnessTexture - ) { - defines.USESPHERICALINVERTEX = false; - } else { - defines.USESPHERICALINVERTEX = true; - } - } - } - } else { - defines.REFLECTION = false; - defines.REFLECTIONMAP_3D = false; - defines.REFLECTIONMAP_SPHERICAL = false; - defines.REFLECTIONMAP_PLANAR = false; - defines.REFLECTIONMAP_CUBIC = false; - defines.USE_LOCAL_REFLECTIONMAP_CUBIC = false; - defines.REFLECTIONMAP_PROJECTION = false; - defines.REFLECTIONMAP_SKYBOX = false; - defines.REFLECTIONMAP_EXPLICIT = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; - defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; - defines.INVERTCUBICMAP = false; - defines.USESPHERICALFROMREFLECTIONMAP = false; - defines.USEIRRADIANCEMAP = false; - defines.USE_IRRADIANCE_DOMINANT_DIRECTION = false; - defines.USESPHERICALINVERTEX = false; - defines.REFLECTIONMAP_OPPOSITEZ = false; - defines.LODINREFLECTIONALPHA = false; - defines.GAMMAREFLECTION = false; - defines.RGBDREFLECTION = false; - defines.LINEARSPECULARREFLECTION = false; - } + const useSHInFragment: boolean = + this._forceIrradianceInFragment || + this.realTimeFiltering || + this._twoSidedLighting || + engine.getCaps().maxVaryingVectors <= 8 || + this._baseDiffuseRoughnessTexture != null; + PrepareDefinesForIBL(scene, reflectionTexture, defines, this.realTimeFiltering, this.realTimeFilteringQuality, !useSHInFragment); if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { PrepareDefinesForMergedUV(this._lightmapTexture, defines, "LIGHTMAP"); diff --git a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts index 8367075077c..f9539a22508 100644 --- a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts @@ -25,9 +25,7 @@ import { MaterialDefines } from "../materialDefines"; import { PushMaterial } from "../pushMaterial"; import type { BaseTexture } from "../Textures/baseTexture"; -import { Texture } from "../Textures/texture"; import type { RenderTargetTexture } from "../Textures/renderTargetTexture"; -import type { CubeTexture } from "../Textures/cubeTexture"; import { MaterialFlags } from "../materialFlags"; import { Constants } from "../../Engines/constants"; @@ -50,6 +48,8 @@ import { BindLogDepth, BindMorphTargetParameters, BindTextureMatrix, + BindIBLParameters, + BindIBLSamplers, HandleFallbacksForShadows, PrepareAttributesForBakedVertexAnimation, PrepareAttributesForBones, @@ -58,12 +58,15 @@ import { PrepareDefinesForAttributes, PrepareDefinesForFrameBoundValues, PrepareDefinesForLights, + PrepareDefinesForIBL, PrepareDefinesForMergedUV, PrepareDefinesForMisc, PrepareDefinesForMultiview, PrepareDefinesForOIT, PrepareDefinesForPrePass, PrepareUniformsAndSamplersList, + PrepareUniformsAndSamplersForIBL, + PrepareUniformLayoutForIBL, } from "../materialHelper.functions"; import { ShaderLanguage } from "../shaderLanguage"; import { MaterialHelperGeometryRendering } from "../materialHelper.geometryrendering"; @@ -1407,7 +1410,6 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { "vMetallicReflectanceFactors", "vEmissiveColor", "visibility", - "vReflectionColor", "vFogInfos", "vFogColor", "pointSize", @@ -1416,12 +1418,8 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { "vBaseDiffuseRoughnessInfos", "vAmbientInfos", "vOpacityInfos", - "vReflectionInfos", - "vReflectionPosition", - "vReflectionSize", "vEmissiveInfos", "vReflectivityInfos", - "vReflectionFilteringInfo", "vMetallicReflectanceInfos", "vReflectanceInfos", "vMicroSurfaceSamplerInfos", @@ -1433,7 +1431,6 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { "baseDiffuseRoughnessMatrix", "ambientMatrix", "opacityMatrix", - "reflectionMatrix", "emissiveMatrix", "reflectivityMatrix", "normalMatrix", @@ -1444,26 +1441,6 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { "reflectanceMatrix", "vLightingIntensity", "logarithmicDepthConstant", - "vSphericalX", - "vSphericalY", - "vSphericalZ", - "vSphericalXX_ZZ", - "vSphericalYY_ZZ", - "vSphericalZZ", - "vSphericalXY", - "vSphericalYZ", - "vSphericalZX", - "vSphericalL00", - "vSphericalL1_1", - "vSphericalL10", - "vSphericalL11", - "vSphericalL2_2", - "vSphericalL2_1", - "vSphericalL20", - "vSphericalL21", - "vSphericalL22", - "vReflectionMicrosurfaceInfos", - "vReflectionDominantDirection", "vTangentSpaceParams", "boneTextureWidth", "vDebugMode", @@ -1482,10 +1459,6 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { "bumpSampler", "lightmapSampler", "opacitySampler", - "reflectionSampler", - "reflectionSamplerLow", - "reflectionSamplerHigh", - "irradianceSampler", "microSurfaceSampler", "environmentBrdfSampler", "boneSampler", @@ -1494,11 +1467,12 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { "morphTargets", "oitDepthSampler", "oitFrontColorSampler", - "icdfSampler", "areaLightsLTC1Sampler", "areaLightsLTC2Sampler", ]; + PrepareUniformsAndSamplersForIBL(uniforms, samplers, true); + const uniformBuffers = ["Material", "Scene", "Mesh"]; const indexParameters = { maxSimultaneousLights: this._maxSimultaneousLights, maxSimultaneousMorphTargets: defines.NUM_MORPH_INFLUENCERS }; @@ -1662,126 +1636,13 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { } const reflectionTexture = this._getReflectionTexture(); - if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { - defines.REFLECTION = true; - defines.GAMMAREFLECTION = reflectionTexture.gammaSpace; - defines.RGBDREFLECTION = reflectionTexture.isRGBD; - defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha; - defines.LINEARSPECULARREFLECTION = reflectionTexture.linearSpecularLOD; - defines.USEIRRADIANCEMAP = false; - - if (this.realTimeFiltering && this.realTimeFilteringQuality > 0) { - defines.NUM_SAMPLES = "" + this.realTimeFilteringQuality; - if (engine._features.needTypeSuffixInShaderConstants) { - defines.NUM_SAMPLES = defines.NUM_SAMPLES + "u"; - } - - defines.REALTIME_FILTERING = true; - if (this.getScene().iblCdfGenerator) { - defines.IBL_CDF_FILTERING = true; - } - } else { - defines.REALTIME_FILTERING = false; - } - - defines.INVERTCUBICMAP = reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE; - defines.REFLECTIONMAP_3D = reflectionTexture.isCube; - defines.REFLECTIONMAP_OPPOSITEZ = defines.REFLECTIONMAP_3D && this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ; - - defines.REFLECTIONMAP_CUBIC = false; - defines.REFLECTIONMAP_EXPLICIT = false; - defines.REFLECTIONMAP_PLANAR = false; - defines.REFLECTIONMAP_PROJECTION = false; - defines.REFLECTIONMAP_SKYBOX = false; - defines.REFLECTIONMAP_SPHERICAL = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; - defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; - - switch (reflectionTexture.coordinatesMode) { - case Texture.EXPLICIT_MODE: - defines.REFLECTIONMAP_EXPLICIT = true; - break; - case Texture.PLANAR_MODE: - defines.REFLECTIONMAP_PLANAR = true; - break; - case Texture.PROJECTION_MODE: - defines.REFLECTIONMAP_PROJECTION = true; - break; - case Texture.SKYBOX_MODE: - defines.REFLECTIONMAP_SKYBOX = true; - break; - case Texture.SPHERICAL_MODE: - defines.REFLECTIONMAP_SPHERICAL = true; - break; - case Texture.EQUIRECTANGULAR_MODE: - defines.REFLECTIONMAP_EQUIRECTANGULAR = true; - break; - case Texture.FIXED_EQUIRECTANGULAR_MODE: - defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true; - break; - case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE: - defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true; - break; - case Texture.CUBIC_MODE: - case Texture.INVCUBIC_MODE: - default: - defines.REFLECTIONMAP_CUBIC = true; - defines.USE_LOCAL_REFLECTIONMAP_CUBIC = (reflectionTexture).boundingBoxSize ? true : false; - break; - } - - if (reflectionTexture.coordinatesMode !== Texture.SKYBOX_MODE) { - if (reflectionTexture.irradianceTexture) { - defines.USEIRRADIANCEMAP = true; - defines.USESPHERICALFROMREFLECTIONMAP = false; - defines.USESPHERICALINVERTEX = false; - if (reflectionTexture.irradianceTexture._dominantDirection) { - defines.USE_IRRADIANCE_DOMINANT_DIRECTION = true; - } - } - // Assume using spherical polynomial if the reflection texture is a cube map - else if (reflectionTexture.isCube) { - defines.USESPHERICALFROMREFLECTIONMAP = true; - defines.USEIRRADIANCEMAP = false; - defines.USE_IRRADIANCE_DOMINANT_DIRECTION = false; - if ( - this._forceIrradianceInFragment || - this.realTimeFiltering || - this._twoSidedLighting || - engine.getCaps().maxVaryingVectors <= 8 || - this._baseDiffuseRoughnessTexture - ) { - defines.USESPHERICALINVERTEX = false; - } else { - defines.USESPHERICALINVERTEX = true; - } - } - } - } else { - defines.REFLECTION = false; - defines.REFLECTIONMAP_3D = false; - defines.REFLECTIONMAP_SPHERICAL = false; - defines.REFLECTIONMAP_PLANAR = false; - defines.REFLECTIONMAP_CUBIC = false; - defines.USE_LOCAL_REFLECTIONMAP_CUBIC = false; - defines.REFLECTIONMAP_PROJECTION = false; - defines.REFLECTIONMAP_SKYBOX = false; - defines.REFLECTIONMAP_EXPLICIT = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR = false; - defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; - defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; - defines.INVERTCUBICMAP = false; - defines.USESPHERICALFROMREFLECTIONMAP = false; - defines.USEIRRADIANCEMAP = false; - defines.USE_IRRADIANCE_DOMINANT_DIRECTION = false; - defines.USESPHERICALINVERTEX = false; - defines.REFLECTIONMAP_OPPOSITEZ = false; - defines.LODINREFLECTIONALPHA = false; - defines.GAMMAREFLECTION = false; - defines.RGBDREFLECTION = false; - defines.LINEARSPECULARREFLECTION = false; - } + const useSHInFragment: boolean = + this._forceIrradianceInFragment || + this.realTimeFiltering || + this._twoSidedLighting || + engine.getCaps().maxVaryingVectors <= 8 || + this._baseDiffuseRoughnessTexture != null; + PrepareDefinesForIBL(scene, reflectionTexture, defines, this.realTimeFiltering, this.realTimeFilteringQuality, !useSHInFragment); if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { PrepareDefinesForMergedUV(this._lightmapTexture, defines, "LIGHTMAP"); @@ -2018,10 +1879,6 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { ubo.addUniform("vLightmapInfos", 2); ubo.addUniform("vReflectivityInfos", 3); ubo.addUniform("vMicroSurfaceSamplerInfos", 2); - ubo.addUniform("vReflectionInfos", 2); - ubo.addUniform("vReflectionFilteringInfo", 2); - ubo.addUniform("vReflectionPosition", 3); - ubo.addUniform("vReflectionSize", 3); ubo.addUniform("vBumpInfos", 3); ubo.addUniform("albedoMatrix", 16); ubo.addUniform("baseWeightMatrix", 16); @@ -2034,16 +1891,11 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { ubo.addUniform("microSurfaceSamplerMatrix", 16); ubo.addUniform("bumpMatrix", 16); ubo.addUniform("vTangentSpaceParams", 2); - ubo.addUniform("reflectionMatrix", 16); - - ubo.addUniform("vReflectionColor", 3); ubo.addUniform("vAlbedoColor", 4); ubo.addUniform("baseWeight", 1); ubo.addUniform("baseDiffuseRoughness", 1); ubo.addUniform("vLightingIntensity", 4); - ubo.addUniform("vReflectionMicrosurfaceInfos", 3); - ubo.addUniform("vReflectionDominantDirection", 3); ubo.addUniform("pointSize", 1); ubo.addUniform("vReflectivityColor", 4); ubo.addUniform("vEmissiveColor", 3); @@ -2057,28 +1909,8 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { ubo.addUniform("vReflectanceInfos", 2); ubo.addUniform("reflectanceMatrix", 16); - ubo.addUniform("vSphericalL00", 3); - ubo.addUniform("vSphericalL1_1", 3); - ubo.addUniform("vSphericalL10", 3); - ubo.addUniform("vSphericalL11", 3); - ubo.addUniform("vSphericalL2_2", 3); - ubo.addUniform("vSphericalL2_1", 3); - ubo.addUniform("vSphericalL20", 3); - ubo.addUniform("vSphericalL21", 3); - ubo.addUniform("vSphericalL22", 3); - - ubo.addUniform("vSphericalX", 3); - ubo.addUniform("vSphericalY", 3); - ubo.addUniform("vSphericalZ", 3); - ubo.addUniform("vSphericalXX_ZZ", 3); - ubo.addUniform("vSphericalYY_ZZ", 3); - ubo.addUniform("vSphericalZZ", 3); - ubo.addUniform("vSphericalXY", 3); - ubo.addUniform("vSphericalYZ", 3); - ubo.addUniform("vSphericalZX", 3); - ubo.addUniform("cameraInfo", 4); - + PrepareUniformLayoutForIBL(ubo, true, true, true); super.buildUniformLayout(); } @@ -2178,73 +2010,6 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { BindTextureMatrix(this._opacityTexture, ubo, "opacity"); } - if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { - ubo.updateMatrix("reflectionMatrix", reflectionTexture.getReflectionTextureMatrix()); - ubo.updateFloat2("vReflectionInfos", reflectionTexture.level * scene.iblIntensity, 0); - - if ((reflectionTexture).boundingBoxSize) { - const cubeTexture = reflectionTexture; - - ubo.updateVector3("vReflectionPosition", cubeTexture.boundingBoxPosition); - ubo.updateVector3("vReflectionSize", cubeTexture.boundingBoxSize); - } - - if (this.realTimeFiltering) { - const width = reflectionTexture.getSize().width; - ubo.updateFloat2("vReflectionFilteringInfo", width, Math.log2(width)); - } - - if (!defines.USEIRRADIANCEMAP) { - const polynomials = reflectionTexture.sphericalPolynomial; - if (defines.USESPHERICALFROMREFLECTIONMAP && polynomials) { - if (defines.SPHERICAL_HARMONICS) { - const preScaledHarmonics = polynomials.preScaledHarmonics; - ubo.updateVector3("vSphericalL00", preScaledHarmonics.l00); - ubo.updateVector3("vSphericalL1_1", preScaledHarmonics.l1_1); - ubo.updateVector3("vSphericalL10", preScaledHarmonics.l10); - ubo.updateVector3("vSphericalL11", preScaledHarmonics.l11); - ubo.updateVector3("vSphericalL2_2", preScaledHarmonics.l2_2); - ubo.updateVector3("vSphericalL2_1", preScaledHarmonics.l2_1); - ubo.updateVector3("vSphericalL20", preScaledHarmonics.l20); - ubo.updateVector3("vSphericalL21", preScaledHarmonics.l21); - ubo.updateVector3("vSphericalL22", preScaledHarmonics.l22); - } else { - ubo.updateFloat3("vSphericalX", polynomials.x.x, polynomials.x.y, polynomials.x.z); - ubo.updateFloat3("vSphericalY", polynomials.y.x, polynomials.y.y, polynomials.y.z); - ubo.updateFloat3("vSphericalZ", polynomials.z.x, polynomials.z.y, polynomials.z.z); - ubo.updateFloat3( - "vSphericalXX_ZZ", - polynomials.xx.x - polynomials.zz.x, - polynomials.xx.y - polynomials.zz.y, - polynomials.xx.z - polynomials.zz.z - ); - ubo.updateFloat3( - "vSphericalYY_ZZ", - polynomials.yy.x - polynomials.zz.x, - polynomials.yy.y - polynomials.zz.y, - polynomials.yy.z - polynomials.zz.z - ); - ubo.updateFloat3("vSphericalZZ", polynomials.zz.x, polynomials.zz.y, polynomials.zz.z); - ubo.updateFloat3("vSphericalXY", polynomials.xy.x, polynomials.xy.y, polynomials.xy.z); - ubo.updateFloat3("vSphericalYZ", polynomials.yz.x, polynomials.yz.y, polynomials.yz.z); - ubo.updateFloat3("vSphericalZX", polynomials.zx.x, polynomials.zx.y, polynomials.zx.z); - } - } - } else { - // If we're using an irradiance map with a dominant direction assigned, set it. - if (defines.USEIRRADIANCEMAP && defines.USE_IRRADIANCE_DOMINANT_DIRECTION) { - ubo.updateVector3("vReflectionDominantDirection", reflectionTexture.irradianceTexture!._dominantDirection!); - } - } - - ubo.updateFloat3( - "vReflectionMicrosurfaceInfos", - reflectionTexture.getSize().width, - reflectionTexture.lodGenerationScale, - reflectionTexture.lodGenerationOffset - ); - } - if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { ubo.updateFloat2("vEmissiveInfos", this._emissiveTexture.coordinatesIndex, this._emissiveTexture.level); BindTextureMatrix(this._emissiveTexture, ubo, "emissive"); @@ -2292,6 +2057,8 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { } } + BindIBLParameters(scene, defines, ubo, reflectionTexture, this.realTimeFiltering, this._reflectionColor); + // Point size if (this.pointsCloud) { ubo.updateFloat("pointSize", this.pointSize); @@ -2316,7 +2083,7 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { } ubo.updateColor3("vEmissiveColor", MaterialFlags.EmissiveTextureEnabled ? this._emissiveColor : Color3.BlackReadOnly); - ubo.updateColor3("vReflectionColor", this._reflectionColor); + if (!defines.SS_REFRACTION && this.subSurface?._linkRefractionWithTransparency) { ubo.updateColor4("vAlbedoColor", this._albedoColor, 1); } else { @@ -2364,25 +2131,7 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { ubo.setTexture("opacitySampler", this._opacityTexture); } - if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { - if (defines.LODBASEDMICROSFURACE) { - ubo.setTexture("reflectionSampler", reflectionTexture); - } else { - ubo.setTexture("reflectionSampler", reflectionTexture._lodTextureMid || reflectionTexture); - ubo.setTexture("reflectionSamplerLow", reflectionTexture._lodTextureLow || reflectionTexture); - ubo.setTexture("reflectionSamplerHigh", reflectionTexture._lodTextureHigh || reflectionTexture); - } - - if (defines.USEIRRADIANCEMAP) { - ubo.setTexture("irradianceSampler", reflectionTexture.irradianceTexture); - } - - //if realtime filtering and using CDF maps, set them. - const cdfGenerator = this.getScene().iblCdfGenerator; - if (this.realTimeFiltering && cdfGenerator) { - ubo.setTexture("icdfSampler", cdfGenerator.getIcdfTexture()); - } - } + BindIBLSamplers(scene, defines, ubo, reflectionTexture, this.realTimeFiltering); if (defines.ENVIRONMENTBRDF) { ubo.setTexture("environmentBrdfSampler", this._environmentBRDFTexture); diff --git a/packages/dev/core/src/Materials/materialHelper.functions.ts b/packages/dev/core/src/Materials/materialHelper.functions.ts index ff19a590ac4..68b5b7dac56 100644 --- a/packages/dev/core/src/Materials/materialHelper.functions.ts +++ b/packages/dev/core/src/Materials/materialHelper.functions.ts @@ -18,7 +18,10 @@ import type { AbstractEngine } from "../Engines/abstractEngine"; import type { Material } from "./material"; import type { Nullable } from "../types"; import { PrepareDefinesForClipPlanes } from "./clipPlaneMaterialHelper"; -import type { MorphTargetManager } from "core/Morph/morphTargetManager"; +import type { MorphTargetManager } from "../Morph/morphTargetManager"; +import { MaterialFlags } from "./materialFlags"; +import { Texture } from "./Textures/texture"; +import type { CubeTexture } from "./Textures/cubeTexture"; // Temps const TempFogColor = Color3.Black(); @@ -266,6 +269,109 @@ export function BindSceneUniformBuffer(effect: Effect, sceneUbo: UniformBuffer): sceneUbo.bindToEffect(effect, "Scene"); } +/** + * Update parameters for IBL + * @param scene The scene + * @param defines The list of shader defines for the material + * @param ubo The uniform buffer to update + * @param reflectionTexture The IBL texture + * @param realTimeFiltering Whether realtime filtering of IBL texture is being used + * @param reflectionColor The color to use for the reflection + */ +export function BindIBLParameters( + scene: Scene, + defines: any, + ubo: UniformBuffer, + reflectionTexture: Nullable = null, + realTimeFiltering: boolean = false, + reflectionColor: Color3 = Color3.White() +): void { + if (scene.texturesEnabled) { + if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { + ubo.updateMatrix("reflectionMatrix", reflectionTexture.getReflectionTextureMatrix()); + ubo.updateFloat2("vReflectionInfos", reflectionTexture.level * scene.iblIntensity, 0); + + if ((reflectionTexture).boundingBoxSize) { + const cubeTexture = reflectionTexture; + + ubo.updateVector3("vReflectionPosition", cubeTexture.boundingBoxPosition); + ubo.updateVector3("vReflectionSize", cubeTexture.boundingBoxSize); + } + + if (realTimeFiltering) { + const width = reflectionTexture.getSize().width; + ubo.updateFloat2("vReflectionFilteringInfo", width, Math.log2(width)); + } + + if (!defines.USEIRRADIANCEMAP) { + const polynomials = reflectionTexture.sphericalPolynomial; + if (defines.USESPHERICALFROMREFLECTIONMAP && polynomials) { + if (defines.SPHERICAL_HARMONICS) { + const preScaledHarmonics = polynomials.preScaledHarmonics; + ubo.updateVector3("vSphericalL00", preScaledHarmonics.l00); + ubo.updateVector3("vSphericalL1_1", preScaledHarmonics.l1_1); + ubo.updateVector3("vSphericalL10", preScaledHarmonics.l10); + ubo.updateVector3("vSphericalL11", preScaledHarmonics.l11); + ubo.updateVector3("vSphericalL2_2", preScaledHarmonics.l2_2); + ubo.updateVector3("vSphericalL2_1", preScaledHarmonics.l2_1); + ubo.updateVector3("vSphericalL20", preScaledHarmonics.l20); + ubo.updateVector3("vSphericalL21", preScaledHarmonics.l21); + ubo.updateVector3("vSphericalL22", preScaledHarmonics.l22); + } else { + ubo.updateFloat3("vSphericalX", polynomials.x.x, polynomials.x.y, polynomials.x.z); + ubo.updateFloat3("vSphericalY", polynomials.y.x, polynomials.y.y, polynomials.y.z); + ubo.updateFloat3("vSphericalZ", polynomials.z.x, polynomials.z.y, polynomials.z.z); + ubo.updateFloat3("vSphericalXX_ZZ", polynomials.xx.x - polynomials.zz.x, polynomials.xx.y - polynomials.zz.y, polynomials.xx.z - polynomials.zz.z); + ubo.updateFloat3("vSphericalYY_ZZ", polynomials.yy.x - polynomials.zz.x, polynomials.yy.y - polynomials.zz.y, polynomials.yy.z - polynomials.zz.z); + ubo.updateFloat3("vSphericalZZ", polynomials.zz.x, polynomials.zz.y, polynomials.zz.z); + ubo.updateFloat3("vSphericalXY", polynomials.xy.x, polynomials.xy.y, polynomials.xy.z); + ubo.updateFloat3("vSphericalYZ", polynomials.yz.x, polynomials.yz.y, polynomials.yz.z); + ubo.updateFloat3("vSphericalZX", polynomials.zx.x, polynomials.zx.y, polynomials.zx.z); + } + } + } else { + // If we're using an irradiance map with a dominant direction assigned, set it. + if (defines.USEIRRADIANCEMAP && defines.USE_IRRADIANCE_DOMINANT_DIRECTION) { + ubo.updateVector3("vReflectionDominantDirection", reflectionTexture.irradianceTexture!._dominantDirection!); + } + } + + ubo.updateFloat3("vReflectionMicrosurfaceInfos", reflectionTexture.getSize().width, reflectionTexture.lodGenerationScale, reflectionTexture.lodGenerationOffset); + } + } + ubo.updateColor3("vReflectionColor", reflectionColor); +} + +/** + * Update parameters for IBL + * @param scene The scene + * @param defines The list of shader defines for the material + * @param ubo The uniform buffer to update + * @param reflectionTexture The IBL texture + * @param realTimeFiltering Whether realtime filtering of IBL texture is being used + */ +export function BindIBLSamplers(scene: Scene, defines: any, ubo: UniformBuffer, reflectionTexture: Nullable = null, realTimeFiltering: boolean = false): void { + if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { + if (defines.LODBASEDMICROSFURACE) { + ubo.setTexture("reflectionSampler", reflectionTexture); + } else { + ubo.setTexture("reflectionSampler", reflectionTexture._lodTextureMid || reflectionTexture); + ubo.setTexture("reflectionSamplerLow", reflectionTexture._lodTextureLow || reflectionTexture); + ubo.setTexture("reflectionSamplerHigh", reflectionTexture._lodTextureHigh || reflectionTexture); + } + + if (defines.USEIRRADIANCEMAP) { + ubo.setTexture("irradianceSampler", reflectionTexture.irradianceTexture); + } + + //if realtime filtering and using CDF maps, set them. + const cdfGenerator = scene.iblCdfGenerator; + if (realTimeFiltering && cdfGenerator) { + ubo.setTexture("icdfSampler", cdfGenerator.getIcdfTexture()); + } + } +} + /** * Helps preparing the defines values about the UVs in used in the effect. * UVs are shared as much as we can across channels in the shaders. @@ -602,6 +708,139 @@ export function PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, define return state.needNormals; } +/** + * Prepare defines relating to IBL logic. + * @param scene The scene + * @param reflectionTexture The texture to use for IBL + * @param defines The defines to update + * @param realTimeFiltering Whether realtime filting of IBL texture is being used + * @param realTimeFilteringQuality The quality of realtime filtering + * @param forceSHInVertex Whether the SH are handled in the vertex shader + */ +export function PrepareDefinesForIBL( + scene: Scene, + reflectionTexture: Nullable, + defines: any, + realTimeFiltering: boolean = false, + realTimeFilteringQuality: number = Constants.TEXTURE_FILTERING_QUALITY_LOW, + forceSHInVertex: boolean = false +) { + if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { + if (!reflectionTexture.isReadyOrNotBlocking()) { + return; + } + defines.REFLECTION = true; + defines.GAMMAREFLECTION = reflectionTexture.gammaSpace; + defines.RGBDREFLECTION = reflectionTexture.isRGBD; + defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha; + defines.LINEARSPECULARREFLECTION = reflectionTexture.linearSpecularLOD; + defines.USEIRRADIANCEMAP = false; + + const engine = scene.getEngine(); + if (realTimeFiltering && realTimeFilteringQuality > 0) { + defines.NUM_SAMPLES = "" + realTimeFilteringQuality; + if (engine._features.needTypeSuffixInShaderConstants) { + defines.NUM_SAMPLES = defines.NUM_SAMPLES + "u"; + } + + defines.REALTIME_FILTERING = true; + if (scene.iblCdfGenerator) { + defines.IBL_CDF_FILTERING = true; + } + } else { + defines.REALTIME_FILTERING = false; + } + + defines.INVERTCUBICMAP = reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE; + defines.REFLECTIONMAP_3D = reflectionTexture.isCube; + defines.REFLECTIONMAP_OPPOSITEZ = defines.REFLECTIONMAP_3D && scene.useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ; + + defines.REFLECTIONMAP_CUBIC = false; + defines.REFLECTIONMAP_EXPLICIT = false; + defines.REFLECTIONMAP_PLANAR = false; + defines.REFLECTIONMAP_PROJECTION = false; + defines.REFLECTIONMAP_SKYBOX = false; + defines.REFLECTIONMAP_SPHERICAL = false; + defines.REFLECTIONMAP_EQUIRECTANGULAR = false; + defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; + defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; + + switch (reflectionTexture.coordinatesMode) { + case Texture.EXPLICIT_MODE: + defines.REFLECTIONMAP_EXPLICIT = true; + break; + case Texture.PLANAR_MODE: + defines.REFLECTIONMAP_PLANAR = true; + break; + case Texture.PROJECTION_MODE: + defines.REFLECTIONMAP_PROJECTION = true; + break; + case Texture.SKYBOX_MODE: + defines.REFLECTIONMAP_SKYBOX = true; + break; + case Texture.SPHERICAL_MODE: + defines.REFLECTIONMAP_SPHERICAL = true; + break; + case Texture.EQUIRECTANGULAR_MODE: + defines.REFLECTIONMAP_EQUIRECTANGULAR = true; + break; + case Texture.FIXED_EQUIRECTANGULAR_MODE: + defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true; + break; + case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE: + defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true; + break; + case Texture.CUBIC_MODE: + case Texture.INVCUBIC_MODE: + default: + defines.REFLECTIONMAP_CUBIC = true; + defines.USE_LOCAL_REFLECTIONMAP_CUBIC = (reflectionTexture).boundingBoxSize ? true : false; + break; + } + + if (reflectionTexture.coordinatesMode !== Texture.SKYBOX_MODE) { + if (reflectionTexture.irradianceTexture) { + defines.USEIRRADIANCEMAP = true; + defines.USESPHERICALFROMREFLECTIONMAP = false; + defines.USESPHERICALINVERTEX = false; + if (reflectionTexture.irradianceTexture._dominantDirection) { + defines.USE_IRRADIANCE_DOMINANT_DIRECTION = true; + } + } + // Assume using spherical polynomial if the reflection texture is a cube map + else if (reflectionTexture.isCube) { + defines.USESPHERICALFROMREFLECTIONMAP = true; + defines.USEIRRADIANCEMAP = false; + defines.USE_IRRADIANCE_DOMINANT_DIRECTION = false; + defines.USESPHERICALINVERTEX = forceSHInVertex; + } + } + } else { + defines.REFLECTION = false; + defines.REFLECTIONMAP_3D = false; + defines.REFLECTIONMAP_SPHERICAL = false; + defines.REFLECTIONMAP_PLANAR = false; + defines.REFLECTIONMAP_CUBIC = false; + defines.USE_LOCAL_REFLECTIONMAP_CUBIC = false; + defines.REFLECTIONMAP_PROJECTION = false; + defines.REFLECTIONMAP_SKYBOX = false; + defines.REFLECTIONMAP_EXPLICIT = false; + defines.REFLECTIONMAP_EQUIRECTANGULAR = false; + defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; + defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; + defines.INVERTCUBICMAP = false; + defines.USESPHERICALFROMREFLECTIONMAP = false; + defines.USEIRRADIANCEMAP = false; + defines.USE_IRRADIANCE_DOMINANT_DIRECTION = false; + defines.USESPHERICALINVERTEX = false; + defines.REFLECTIONMAP_OPPOSITEZ = false; + defines.LODINREFLECTIONALPHA = false; + defines.GAMMAREFLECTION = false; + defines.RGBDREFLECTION = false; + defines.LINEARSPECULARREFLECTION = false; + } +} + /** * Prepares the defines related to the light information passed in parameter * @param scene The scene we are intending to draw @@ -1126,6 +1365,51 @@ export function PrepareUniformsAndSamplersForLight( } } +/** + * Append uniforms and samplers related to IBL to the provided lists + * @param uniformsList The list of uniforms to append to + * @param samplersList The list of samplers to append to + * @param useSH Whether to include spherical harmonics uniforms + */ +export function PrepareUniformsAndSamplersForIBL(uniformsList: string[], samplersList: string[], useSH: boolean): void { + const iblUniforms = [ + "vReflectionMicrosurfaceInfos", + "vReflectionDominantDirection", + "reflectionMatrix", + "vReflectionInfos", + "vReflectionPosition", + "vReflectionSize", + "vReflectionColor", + "vReflectionFilteringInfo", + ]; + if (useSH) { + iblUniforms.push( + "vSphericalX", + "vSphericalY", + "vSphericalZ", + "vSphericalXX_ZZ", + "vSphericalYY_ZZ", + "vSphericalZZ", + "vSphericalXY", + "vSphericalYZ", + "vSphericalZX", + "vSphericalL00", + "vSphericalL1_1", + "vSphericalL10", + "vSphericalL11", + "vSphericalL2_2", + "vSphericalL2_1", + "vSphericalL20", + "vSphericalL21", + "vSphericalL22" + ); + } + uniformsList.push(...iblUniforms); + + const iblSamplers = ["reflectionSampler", "reflectionSamplerLow", "reflectionSamplerHigh", "irradianceSampler", "icdfSampler"]; + samplersList.push(...iblSamplers); +} + /** * Prepares the uniforms and samplers list to be used in the effect * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the list and extra information @@ -1178,3 +1462,58 @@ export function PrepareUniformsAndSamplersList(uniformsListOrOptions: string[] | samplersList.push("bakedVertexAnimationTexture"); } } + +/** + * + * @param ubo Add uniforms to UBO + * @param supportTextureInfo Add uniforms for texture info if true + * @param supportLocalProjection Add uniforms for local projection if true + * @param useAdvanced Add advanced uniforms for IBL if true + * @param supportSH Add uniforms for spherical harmonics if true + */ +export function PrepareUniformLayoutForIBL( + ubo: UniformBuffer, + supportTextureInfo: boolean = false, + supportLocalProjection: boolean = false, + useAdvanced: boolean = false, + supportSH: boolean = false +): void { + ubo.addUniform("vReflectionInfos", 2); + ubo.addUniform("reflectionMatrix", 16); + if (supportTextureInfo) { + ubo.addUniform("vReflectionMicrosurfaceInfos", 3); + } + + if (supportLocalProjection) { + ubo.addUniform("vReflectionPosition", 3); + ubo.addUniform("vReflectionSize", 3); + } + + if (useAdvanced) { + ubo.addUniform("vReflectionFilteringInfo", 2); + ubo.addUniform("vReflectionColor", 3); + ubo.addUniform("vReflectionDominantDirection", 3); + } + + if (supportSH) { + ubo.addUniform("vSphericalL00", 3); + ubo.addUniform("vSphericalL1_1", 3); + ubo.addUniform("vSphericalL10", 3); + ubo.addUniform("vSphericalL11", 3); + ubo.addUniform("vSphericalL2_2", 3); + ubo.addUniform("vSphericalL2_1", 3); + ubo.addUniform("vSphericalL20", 3); + ubo.addUniform("vSphericalL21", 3); + ubo.addUniform("vSphericalL22", 3); + + ubo.addUniform("vSphericalX", 3); + ubo.addUniform("vSphericalY", 3); + ubo.addUniform("vSphericalZ", 3); + ubo.addUniform("vSphericalXX_ZZ", 3); + ubo.addUniform("vSphericalYY_ZZ", 3); + ubo.addUniform("vSphericalZZ", 3); + ubo.addUniform("vSphericalXY", 3); + ubo.addUniform("vSphericalYZ", 3); + ubo.addUniform("vSphericalZX", 3); + } +} diff --git a/packages/dev/core/src/Materials/standardMaterial.ts b/packages/dev/core/src/Materials/standardMaterial.ts index 93a6dd24d6e..6995bd88e66 100644 --- a/packages/dev/core/src/Materials/standardMaterial.ts +++ b/packages/dev/core/src/Materials/standardMaterial.ts @@ -23,7 +23,6 @@ import { MaterialDefines } from "../Materials/materialDefines"; import { PushMaterial } from "./pushMaterial"; import type { BaseTexture } from "../Materials/Textures/baseTexture"; -import { Texture } from "../Materials/Textures/texture"; import type { CubeTexture } from "../Materials/Textures/cubeTexture"; import type { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture"; import { RegisterClass } from "../Misc/typeStore"; @@ -41,6 +40,7 @@ import { BindLogDepth, BindMorphTargetParameters, BindTextureMatrix, + BindIBLParameters, HandleFallbacksForShadows, PrepareAttributesForBakedVertexAnimation, PrepareAttributesForBones, @@ -49,12 +49,15 @@ import { PrepareDefinesForAttributes, PrepareDefinesForFrameBoundValues, PrepareDefinesForLights, + PrepareDefinesForIBL, PrepareDefinesForMergedUV, PrepareDefinesForMisc, PrepareDefinesForMultiview, PrepareDefinesForOIT, PrepareDefinesForPrePass, + PrepareUniformsAndSamplersForIBL, PrepareUniformsAndSamplersList, + PrepareUniformLayoutForIBL, } from "./materialHelper.functions"; import { SerializationHelper } from "../Misc/decorators.serialization"; import { ShaderLanguage } from "./shaderLanguage"; @@ -226,25 +229,6 @@ export class StandardMaterialDefines extends ImageProcessingDefinesMixin(Standar super(externalProperties); this.rebuild(); } - - public setReflectionMode(modeToEnable: string) { - const modes = [ - "REFLECTIONMAP_CUBIC", - "REFLECTIONMAP_EXPLICIT", - "REFLECTIONMAP_PLANAR", - "REFLECTIONMAP_PROJECTION", - "REFLECTIONMAP_PROJECTION", - "REFLECTIONMAP_SKYBOX", - "REFLECTIONMAP_SPHERICAL", - "REFLECTIONMAP_EQUIRECTANGULAR", - "REFLECTIONMAP_EQUIRECTANGULAR_FIXED", - "REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED", - ]; - - for (const mode of modes) { - (this)[mode] = mode === modeToEnable; - } - } } class StandardMaterialBase extends ImageProcessingMixin(PushMaterial) {} @@ -842,60 +826,9 @@ export class StandardMaterial extends StandardMaterialBase { } else { defines.OPACITY = false; } - - if (this._reflectionTexture && StandardMaterial.ReflectionTextureEnabled) { - if (!this._reflectionTexture.isReadyOrNotBlocking()) { - return false; - } else { - defines._needNormals = true; - defines.REFLECTION = true; - - defines.ROUGHNESS = this._roughness > 0; - defines.REFLECTIONOVERALPHA = this._useReflectionOverAlpha; - defines.INVERTCUBICMAP = this._reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE; - defines.REFLECTIONMAP_3D = this._reflectionTexture.isCube; - defines.REFLECTIONMAP_OPPOSITEZ = - defines.REFLECTIONMAP_3D && this.getScene().useRightHandedSystem ? !this._reflectionTexture.invertZ : this._reflectionTexture.invertZ; - defines.RGBDREFLECTION = this._reflectionTexture.isRGBD; - - switch (this._reflectionTexture.coordinatesMode) { - case Texture.EXPLICIT_MODE: - defines.setReflectionMode("REFLECTIONMAP_EXPLICIT"); - break; - case Texture.PLANAR_MODE: - defines.setReflectionMode("REFLECTIONMAP_PLANAR"); - break; - case Texture.PROJECTION_MODE: - defines.setReflectionMode("REFLECTIONMAP_PROJECTION"); - break; - case Texture.SKYBOX_MODE: - defines.setReflectionMode("REFLECTIONMAP_SKYBOX"); - break; - case Texture.SPHERICAL_MODE: - defines.setReflectionMode("REFLECTIONMAP_SPHERICAL"); - break; - case Texture.EQUIRECTANGULAR_MODE: - defines.setReflectionMode("REFLECTIONMAP_EQUIRECTANGULAR"); - break; - case Texture.FIXED_EQUIRECTANGULAR_MODE: - defines.setReflectionMode("REFLECTIONMAP_EQUIRECTANGULAR_FIXED"); - break; - case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE: - defines.setReflectionMode("REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED"); - break; - case Texture.CUBIC_MODE: - case Texture.INVCUBIC_MODE: - default: - defines.setReflectionMode("REFLECTIONMAP_CUBIC"); - break; - } - - defines.USE_LOCAL_REFLECTIONMAP_CUBIC = (this._reflectionTexture).boundingBoxSize ? true : false; - } - } else { - defines.REFLECTION = false; - defines.REFLECTIONMAP_OPPOSITEZ = false; - } + defines.ROUGHNESS = this._roughness > 0; + defines.REFLECTIONOVERALPHA = this._useReflectionOverAlpha; + PrepareDefinesForIBL(scene, this._reflectionTexture, defines); if (this._emissiveTexture && StandardMaterial.EmissiveTextureEnabled) { if (!this._emissiveTexture.isReadyOrNotBlocking()) { @@ -1201,7 +1134,6 @@ export class StandardMaterial extends StandardMaterialBase { "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", - "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", @@ -1211,7 +1143,6 @@ export class StandardMaterial extends StandardMaterialBase { "diffuseMatrix", "ambientMatrix", "opacityMatrix", - "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", @@ -1227,8 +1158,6 @@ export class StandardMaterial extends StandardMaterialBase { "emissiveRightColor", "refractionLeftColor", "refractionRightColor", - "vReflectionPosition", - "vReflectionSize", "vRefractionPosition", "vRefractionSize", "logarithmicDepthConstant", @@ -1260,6 +1189,7 @@ export class StandardMaterial extends StandardMaterialBase { "areaLightsLTC2Sampler", ]; + PrepareUniformsAndSamplersForIBL(uniforms, samplers, false); const uniformBuffers = ["Material", "Scene", "Mesh"]; const indexParameters = { maxSimultaneousLights: this._maxSimultaneousLights, maxSimultaneousMorphTargets: defines.NUM_MORPH_INFLUENCERS }; @@ -1396,9 +1326,6 @@ export class StandardMaterial extends StandardMaterialBase { ubo.addUniform("vDiffuseInfos", 2); ubo.addUniform("vAmbientInfos", 2); ubo.addUniform("vOpacityInfos", 2); - ubo.addUniform("vReflectionInfos", 2); - ubo.addUniform("vReflectionPosition", 3); - ubo.addUniform("vReflectionSize", 3); ubo.addUniform("vEmissiveInfos", 2); ubo.addUniform("vLightmapInfos", 2); ubo.addUniform("vSpecularInfos", 2); @@ -1407,7 +1334,6 @@ export class StandardMaterial extends StandardMaterialBase { ubo.addUniform("diffuseMatrix", 16); ubo.addUniform("ambientMatrix", 16); ubo.addUniform("opacityMatrix", 16); - ubo.addUniform("reflectionMatrix", 16); ubo.addUniform("emissiveMatrix", 16); ubo.addUniform("lightmapMatrix", 16); ubo.addUniform("specularMatrix", 16); @@ -1425,6 +1351,8 @@ export class StandardMaterial extends StandardMaterialBase { ubo.addUniform("vAmbientColor", 3); ubo.addUniform("cameraInfo", 4); + PrepareUniformLayoutForIBL(ubo, false, true); + super.buildUniformLayout(); } @@ -1539,19 +1467,7 @@ export class StandardMaterial extends StandardMaterialBase { ubo.updateFloat("alphaCutOff", this.alphaCutOff); } - if (this._reflectionTexture && StandardMaterial.ReflectionTextureEnabled) { - ubo.updateFloat2("vReflectionInfos", this._reflectionTexture.level, this.roughness); - ubo.updateMatrix("reflectionMatrix", this._reflectionTexture.getReflectionTextureMatrix()); - - if ((this._reflectionTexture).boundingBoxSize) { - const cubeTexture = this._reflectionTexture; - - ubo.updateVector3("vReflectionPosition", cubeTexture.boundingBoxPosition); - ubo.updateVector3("vReflectionSize", cubeTexture.boundingBoxSize); - } - } else { - ubo.updateFloat2("vReflectionInfos", 0.0, this.roughness); - } + BindIBLParameters(scene, defines, ubo, this._reflectionTexture); if (this._emissiveTexture && StandardMaterial.EmissiveTextureEnabled) { ubo.updateFloat2("vEmissiveInfos", this._emissiveTexture.coordinatesIndex, this._emissiveTexture.level); diff --git a/packages/dev/core/src/Shaders/ShadersInclude/backgroundUboDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/backgroundUboDeclaration.fx index 549fcfa18e6..5a6f77003f3 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/backgroundUboDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/backgroundUboDeclaration.fx @@ -5,10 +5,7 @@ uniform Material uniform vec4 vPrimaryColor; uniform vec4 vPrimaryColorShadow; uniform vec2 vDiffuseInfos; - uniform vec2 vReflectionInfos; uniform mat4 diffuseMatrix; - uniform mat4 reflectionMatrix; - uniform vec3 vReflectionMicrosurfaceInfos; uniform float fFovMultiplier; uniform float pointSize; @@ -17,6 +14,10 @@ uniform Material uniform vec3 vBackgroundCenter; uniform vec4 vReflectionControl; uniform vec2 projectedGroundInfos; + + uniform vec2 vReflectionInfos; + uniform mat4 reflectionMatrix; + uniform vec3 vReflectionMicrosurfaceInfos; }; #include diff --git a/packages/dev/core/src/Shaders/ShadersInclude/defaultUboDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/defaultUboDeclaration.fx index b68982042da..64a29678059 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/defaultUboDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/defaultUboDeclaration.fx @@ -14,9 +14,6 @@ uniform Material vec2 vDiffuseInfos; vec2 vAmbientInfos; vec2 vOpacityInfos; - vec2 vReflectionInfos; - vec3 vReflectionPosition; - vec3 vReflectionSize; vec2 vEmissiveInfos; vec2 vLightmapInfos; vec2 vSpecularInfos; @@ -24,7 +21,6 @@ uniform Material mat4 diffuseMatrix; mat4 ambientMatrix; mat4 opacityMatrix; - mat4 reflectionMatrix; mat4 emissiveMatrix; mat4 lightmapMatrix; mat4 specularMatrix; @@ -42,6 +38,11 @@ uniform Material vec3 vAmbientColor; vec4 cameraInfo; + vec2 vReflectionInfos; + mat4 reflectionMatrix; + vec3 vReflectionPosition; + vec3 vReflectionSize; + #define ADDITIONAL_UBO_DECLARATION }; diff --git a/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx index 47a2252ac9d..5842558c3ce 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx @@ -32,10 +32,6 @@ uniform Material { vec2 vLightmapInfos; vec3 vReflectivityInfos; vec2 vMicroSurfaceSamplerInfos; - vec2 vReflectionInfos; - vec2 vReflectionFilteringInfo; - vec3 vReflectionPosition; - vec3 vReflectionSize; vec3 vBumpInfos; mat4 albedoMatrix; mat4 baseWeightMatrix; @@ -48,14 +44,10 @@ uniform Material { mat4 microSurfaceSamplerMatrix; mat4 bumpMatrix; vec2 vTangentSpaceParams; - mat4 reflectionMatrix; - vec3 vReflectionColor; vec4 vAlbedoColor; float baseWeight; float baseDiffuseRoughness; vec4 vLightingIntensity; - vec3 vReflectionMicrosurfaceInfos; - vec3 vReflectionDominantDirection; float pointSize; vec4 vReflectivityColor; vec3 vEmissiveColor; @@ -69,6 +61,15 @@ uniform Material { vec2 vReflectanceInfos; mat4 reflectanceMatrix; + vec2 vReflectionInfos; + mat4 reflectionMatrix; + vec3 vReflectionMicrosurfaceInfos; + vec3 vReflectionPosition; + vec3 vReflectionSize; + vec2 vReflectionFilteringInfo; + vec3 vReflectionColor; + vec3 vReflectionDominantDirection; + vec3 vSphericalL00; vec3 vSphericalL1_1; vec3 vSphericalL10; diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/backgroundUboDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/backgroundUboDeclaration.fx index 98551a79444..f6750a15a3f 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/backgroundUboDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/backgroundUboDeclaration.fx @@ -1,10 +1,7 @@ uniform vPrimaryColor: vec4f; uniform vPrimaryColorShadow: vec4f; -uniform vDiffuseInfos: vec2f; -uniform vReflectionInfos: vec2f; -uniform diffuseMatrix: mat4x4f; -uniform reflectionMatrix: mat4x4f; -uniform vReflectionMicrosurfaceInfos: vec3f; +uniform vDiffuseInfos : vec2f; +uniform diffuseMatrix : mat4x4f; uniform fFovMultiplier: f32; uniform pointSize: f32; @@ -14,4 +11,8 @@ uniform vBackgroundCenter: vec3f; uniform vReflectionControl: vec4f; uniform projectedGroundInfos: vec2f; +uniform vReflectionInfos : vec2f; +uniform reflectionMatrix : mat4x4f; +uniform vReflectionMicrosurfaceInfos : vec3f; + #include diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/defaultUboDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/defaultUboDeclaration.fx index 5aec9a38d81..fe0b782bc3c 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/defaultUboDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/defaultUboDeclaration.fx @@ -10,9 +10,6 @@ uniform emissiveRightColor: vec4f; uniform vDiffuseInfos: vec2f; uniform vAmbientInfos: vec2f; uniform vOpacityInfos: vec2f; -uniform vReflectionInfos: vec2f; -uniform vReflectionPosition: vec3f; -uniform vReflectionSize: vec3f; uniform vEmissiveInfos: vec2f; uniform vLightmapInfos: vec2f; uniform vSpecularInfos: vec2f; @@ -20,7 +17,6 @@ uniform vBumpInfos: vec3f; uniform diffuseMatrix: mat4x4f; uniform ambientMatrix: mat4x4f; uniform opacityMatrix: mat4x4f; -uniform reflectionMatrix: mat4x4f; uniform emissiveMatrix: mat4x4f; uniform lightmapMatrix: mat4x4f; uniform specularMatrix: mat4x4f; @@ -37,6 +33,10 @@ uniform vEmissiveColor: vec3f; uniform vDiffuseColor: vec4f; uniform vAmbientColor: vec3f; uniform cameraInfo: vec4f; +uniform vReflectionInfos: vec2f; +uniform reflectionMatrix: mat4x4f; +uniform vReflectionPosition: vec3f; +uniform vReflectionSize: vec3f; #define ADDITIONAL_UBO_DECLARATION diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx index e0922402feb..f5aeed5f908 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx @@ -7,10 +7,6 @@ uniform vEmissiveInfos: vec2f; uniform vLightmapInfos: vec2f; uniform vReflectivityInfos: vec3f; uniform vMicroSurfaceSamplerInfos: vec2f; -uniform vReflectionInfos: vec2f; -uniform vReflectionFilteringInfo: vec2f; -uniform vReflectionPosition: vec3f; -uniform vReflectionSize: vec3f; uniform vBumpInfos: vec3f; uniform albedoMatrix: mat4x4f; uniform baseWeightMatrix: mat4x4f; @@ -23,14 +19,10 @@ uniform reflectivityMatrix: mat4x4f; uniform microSurfaceSamplerMatrix: mat4x4f; uniform bumpMatrix: mat4x4f; uniform vTangentSpaceParams: vec2f; -uniform reflectionMatrix: mat4x4f; -uniform vReflectionColor: vec3f; uniform vAlbedoColor: vec4f; uniform baseWeight: f32; uniform baseDiffuseRoughness: f32; uniform vLightingIntensity: vec4f; -uniform vReflectionMicrosurfaceInfos: vec3f; -uniform vReflectionDominantDirection: vec3f; uniform pointSize: f32; uniform vReflectivityColor: vec4f; uniform vEmissiveColor: vec3f; @@ -44,6 +36,15 @@ uniform metallicReflectanceMatrix: mat4x4f; uniform vReflectanceInfos: vec2f; uniform reflectanceMatrix: mat4x4f; +uniform vReflectionInfos: vec2f; +uniform reflectionMatrix: mat4x4f; +uniform vReflectionMicrosurfaceInfos: vec3f; +uniform vReflectionPosition: vec3f; +uniform vReflectionSize: vec3f; +uniform vReflectionFilteringInfo: vec2f; +uniform vReflectionColor: vec3f; +uniform vReflectionDominantDirection: vec3f; + uniform vSphericalL00: vec3f; uniform vSphericalL1_1: vec3f; uniform vSphericalL10: vec3f; From 9eee1f0379d17fdedba20340e298f7494845ffbc Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Tue, 24 Jun 2025 15:14:03 -0700 Subject: [PATCH 08/23] Remove pbrBaseMaterial as base class for PBR2 --- .../Background/backgroundMaterial.ts | 2 +- .../core/src/Materials/PBR/pbr2Material.ts | 1865 ++++++++++++++--- .../core/src/Materials/PBR/pbrBaseMaterial.ts | 4 +- .../src/Materials/materialHelper.functions.ts | 39 +- .../core/src/Materials/standardMaterial.ts | 2 +- .../ShadersInclude/pbrUboDeclaration.fx | 2 +- .../ShadersInclude/pbrUboDeclaration.fx | 2 +- .../EXT_materials_diffuse_roughness.ts | 4 +- .../Extensions/KHR_materials_anisotropy.ts | 3 +- .../2.0/Extensions/KHR_materials_clearcoat.ts | 3 +- .../KHR_materials_diffuse_transmission.ts | 3 +- .../Extensions/KHR_materials_dispersion.ts | 3 +- .../glTF/2.0/Extensions/KHR_materials_ior.ts | 3 +- .../Extensions/KHR_materials_iridescence.ts | 3 +- .../2.0/Extensions/KHR_materials_sheen.ts | 3 +- .../Extensions/KHR_materials_transmission.ts | 3 +- .../2.0/Extensions/KHR_materials_volume.ts | 3 +- 17 files changed, 1570 insertions(+), 377 deletions(-) diff --git a/packages/dev/core/src/Materials/Background/backgroundMaterial.ts b/packages/dev/core/src/Materials/Background/backgroundMaterial.ts index e8c272d634d..540ea120722 100644 --- a/packages/dev/core/src/Materials/Background/backgroundMaterial.ts +++ b/packages/dev/core/src/Materials/Background/backgroundMaterial.ts @@ -929,7 +929,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase { BindTextureMatrix(this._diffuseTexture, this._uniformBuffer, "diffuse"); } - BindIBLParameters(scene, defines, this._uniformBuffer, reflectionTexture); + BindIBLParameters(scene, defines, this._uniformBuffer, reflectionTexture, false, true); } if (this.shadowLevel > 0) { diff --git a/packages/dev/core/src/Materials/PBR/pbr2Material.ts b/packages/dev/core/src/Materials/PBR/pbr2Material.ts index e16fe3d2dcf..1d08c1d3969 100644 --- a/packages/dev/core/src/Materials/PBR/pbr2Material.ts +++ b/packages/dev/core/src/Materials/PBR/pbr2Material.ts @@ -2,8 +2,8 @@ import { serialize, serializeAsColor3, expandToProperty, serializeAsTexture } from "../../Misc/decorators"; import { GetEnvironmentBRDFTexture } from "../../Misc/brdfTextureTools"; import type { Nullable } from "../../types"; -import type { Scene } from "../../scene"; -import { Color3, Color4 } from "../../Maths/math.color"; +import { Scene } from "../../scene"; +import { Color3, Color4, TmpColors } from "../../Maths/math.color"; import { ImageProcessingConfiguration } from "../imageProcessingConfiguration"; import type { BaseTexture } from "../Textures/baseTexture"; import { PBRBaseMaterial } from "./pbrBaseMaterial"; @@ -16,14 +16,16 @@ import type { Effect, IEffectCreationOptions } from "../../Materials/effect"; import { MaterialDefines } from "../materialDefines"; import { ImageProcessingDefinesMixin } from "../imageProcessingConfiguration.defines"; import { EffectFallbacks } from "../effectFallbacks"; -import { AddClipPlaneUniforms } from "../clipPlaneMaterialHelper"; +import { AddClipPlaneUniforms, BindClipPlane } from "../clipPlaneMaterialHelper"; import { - // BindBonesParameters, - // BindFogParameters, - // BindLights, - // BindLogDepth, - // BindMorphTargetParameters, - // BindTextureMatrix, + BindBonesParameters, + BindFogParameters, + BindLights, + BindLogDepth, + BindMorphTargetParameters, + BindTextureMatrix, + BindIBLParameters, + BindIBLSamplers, HandleFallbacksForShadows, PrepareAttributesForBakedVertexAnimation, PrepareAttributesForBones, @@ -40,6 +42,7 @@ import { PrepareDefinesForPrePass, PrepareUniformsAndSamplersList, PrepareUniformsAndSamplersForIBL, + PrepareUniformLayoutForIBL, } from "../materialHelper.functions"; import { Constants } from "../../Engines/constants"; import { VertexBuffer } from "../../Buffers/buffer"; @@ -53,6 +56,13 @@ import type { SubMesh } from "../../Meshes/subMesh"; import { Logger } from "core/Misc/logger"; import { UVDefinesMixin } from "../uv.defines"; import { Vector2, Vector3, Vector4 } from "core/Maths/math.vector"; +import type { Matrix } from "core/Maths/math.vector"; +import type { Mesh } from "../../Meshes/mesh"; +import { ImageProcessingMixin } from "../imageProcessing"; +import { PushMaterial } from "../pushMaterial"; +import { SmartArray } from "../../Misc/smartArray"; +import type { RenderTargetTexture } from "../Textures/renderTargetTexture"; +import type { IAnimatable } from "../../Animations/animatable.interface"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; @@ -320,6 +330,7 @@ export class PBR2MaterialDefines extends ImageProcessingDefinesMixin(PBR2Materia } } +class PBR2BaseMaterial extends ImageProcessingMixin(PushMaterial) {} // class PBR2MaterialBase extends ImageProcessingMixin(PBRBaseMaterial) {} /** * The Physically based material of BJS. @@ -328,33 +339,33 @@ export class PBR2MaterialDefines extends ImageProcessingDefinesMixin(PBR2Materia * For more information, please refer to the documentation : * https://doc.babylonjs.com/features/featuresDeepDive/materials/using/introToPBR */ -export class PBR2Material extends PBRBaseMaterial { +export class PBR2Material extends PBR2BaseMaterial { /** * PBR2MaterialTransparencyMode: No transparency mode, Alpha channel is not use. */ - public static override readonly PBRMATERIAL_OPAQUE = PBRBaseMaterial.PBRMATERIAL_OPAQUE; + public static readonly PBRMATERIAL_OPAQUE = PBRBaseMaterial.PBRMATERIAL_OPAQUE; /** * PBR2MaterialTransparencyMode: Alpha Test mode, pixel are discarded below a certain threshold defined by the alpha cutoff value. */ - public static override readonly PBRMATERIAL_ALPHATEST = PBRBaseMaterial.PBRMATERIAL_ALPHATEST; + public static readonly PBRMATERIAL_ALPHATEST = PBRBaseMaterial.PBRMATERIAL_ALPHATEST; /** * PBR2MaterialTransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. */ - public static override readonly PBRMATERIAL_ALPHABLEND = PBRBaseMaterial.PBRMATERIAL_ALPHABLEND; + public static readonly PBRMATERIAL_ALPHABLEND = PBRBaseMaterial.PBRMATERIAL_ALPHABLEND; /** * PBR2MaterialTransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. * They are also discarded below the alpha cutoff threshold to improve performances. */ - public static override readonly PBRMATERIAL_ALPHATESTANDBLEND = PBRBaseMaterial.PBRMATERIAL_ALPHATESTANDBLEND; + public static readonly PBRMATERIAL_ALPHATESTANDBLEND = PBRBaseMaterial.PBRMATERIAL_ALPHATESTANDBLEND; /** * Defines the default value of how much AO map is occluding the analytical lights * (point spot...). */ - public static override DEFAULT_AO_ON_ANALYTICAL_LIGHTS = PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; + public static DEFAULT_AO_ON_ANALYTICAL_LIGHTS = PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; /** * Base Color uniform property. @@ -587,21 +598,6 @@ export class PBR2Material extends PBRBaseMaterial { @expandToProperty("_markAllSubMeshesAsTexturesDirty", null) public lightmapTexture: Nullable; - /** - * Stores the refracted light information in a texture. - */ - public get refractionTexture(): Nullable { - return this.subSurface.refractionTexture; - } - public set refractionTexture(value: Nullable) { - this.subSurface.refractionTexture = value; - if (value) { - this.subSurface.isRefractionEnabled = true; - } else if (!this.subSurface.linkRefractionWithTransparency) { - this.subSurface.isRefractionEnabled = false; - } - } - /** * The color of a material in ambient lighting. */ @@ -658,45 +654,6 @@ export class PBR2Material extends PBRBaseMaterial { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public microSurface = 1.0; - /** - * Index of refraction of the material base layer. - * https://en.wikipedia.org/wiki/List_of_refractive_indices - * - * This does not only impact refraction but also the Base F0 of Dielectric Materials. - * - * From dielectric fresnel rules: F0 = square((iorT - iorI) / (iorT + iorI)) - */ - public get indexOfRefraction(): number { - return this.subSurface.indexOfRefraction; - } - public set indexOfRefraction(value: number) { - this.subSurface.indexOfRefraction = value; - } - - /** - * Controls if refraction needs to be inverted on Y. This could be useful for procedural texture. - */ - public get invertRefractionY(): boolean { - return this.subSurface.invertRefractionY; - } - public set invertRefractionY(value: boolean) { - this.subSurface.invertRefractionY = value; - } - - /** - * This parameters will make the material used its opacity to control how much it is refracting against not. - * Materials half opaque for instance using refraction could benefit from this control. - */ - public get linkRefractionWithTransparency(): boolean { - return this.subSurface.linkRefractionWithTransparency; - } - public set linkRefractionWithTransparency(value: boolean) { - this.subSurface.linkRefractionWithTransparency = value; - if (value) { - this.subSurface.isRefractionEnabled = true; - } - } - /** * If true, the light map contains occlusion information instead of lighting info. */ @@ -990,356 +947,1580 @@ export class PBR2Material extends PBRBaseMaterial { public applyDecalMapAfterDetailMap = false; /** - * Instantiates a new PBR2Material instance. - * - * @param name The material name - * @param scene The scene the material will be use in. - * @param forceGLSL Use the GLSL code generation for the shader (even on WebGPU). Default is false + * PBRMaterialLightFalloff Physical: light is falling off following the inverse squared distance law. */ - constructor(name: string, scene?: Scene, forceGLSL = false) { - super(name, scene, forceGLSL); - this._environmentBRDFTexture = GetEnvironmentBRDFTexture(this.getScene()); - } + public static readonly LIGHTFALLOFF_PHYSICAL = 0; /** - * @returns the name of this material class. + * PBRMaterialLightFalloff gltf: light is falling off as described in the gltf moving to PBR document + * to enhance interoperability with other engines. */ - public override getClassName(): string { - return "gi"; - } + public static readonly LIGHTFALLOFF_GLTF = 1; /** - * Makes a duplicate of the current material. - * @param name - name to use for the new material. - * @param cloneTexturesOnlyOnce - if a texture is used in more than one channel (e.g diffuse and opacity), only clone it once and reuse it on the other channels. Default false. - * @param rootUrl defines the root URL to use to load textures - * @returns cloned material instance + * PBRMaterialLightFalloff Standard: light is falling off like in the standard material + * to enhance interoperability with other materials. */ - public override clone(name: string, cloneTexturesOnlyOnce: boolean = true, rootUrl = ""): PBR2Material { - const clone = SerializationHelper.Clone(() => new PBR2Material(name, this.getScene()), this, { cloneTexturesOnlyOnce }); + public static readonly LIGHTFALLOFF_STANDARD = 2; - clone.id = name; - clone.name = name; + /** + * Force all the PBR materials to compile to glsl even on WebGPU engines. + * False by default. This is mostly meant for backward compatibility. + */ + public static ForceGLSL = false; - this.stencil.copyTo(clone.stencil); + /** + * Intensity of the direct lights e.g. the four lights available in your scene. + * This impacts both the direct diffuse and specular highlights. + * @internal + */ + public _directIntensity: number = 1.0; - this._clonePlugins(clone, rootUrl); + /** + * Intensity of the emissive part of the material. + * This helps controlling the emissive effect without modifying the emissive color. + * @internal + */ + public _emissiveIntensity: number = 1.0; - return clone; - } + /** + * Intensity of the environment e.g. how much the environment will light the object + * either through harmonics for rough material or through the reflection for shiny ones. + * @internal + */ + public _environmentIntensity: number = 1.0; /** - * Serializes this PBR Material. - * @returns - An object with the serialized material. + * This is a special control allowing the reduction of the specular highlights coming from the + * four lights of the scene. Those highlights may not be needed in full environment lighting. + * @internal */ - public override serialize(): any { - const serializationObject = super.serialize(); - serializationObject.customType = "BABYLON.PBR2Material"; + public _specularIntensity: number = 1.0; - return serializationObject; - } + /** + * This stores the direct, emissive, environment, and specular light intensities into a Vector4. + */ + private _lightingInfos: Vector4 = new Vector4(this._directIntensity, this._emissiveIntensity, this._environmentIntensity, this._specularIntensity); - // Statics /** - * Parses a PBR Material from a serialized object. - * @param source - Serialized object. - * @param scene - BJS scene instance. - * @param rootUrl - url for the scene object - * @returns - PBR2Material + * Debug Control allowing disabling the bump map on this material. + * @internal */ - public static override Parse(source: any, scene: Scene, rootUrl: string): PBR2Material { - const material = SerializationHelper.Parse(() => new PBR2Material(source.name, scene), source, scene, rootUrl); + public _disableBumpMap: boolean = false; - if (source.stencil) { - material.stencil.parse(source.stencil, scene, rootUrl); - } + /** + * AKA Diffuse Texture in standard nomenclature. + * @internal + */ + public _albedoTexture: Nullable = null; - Material._ParsePlugins(source, material, scene, rootUrl); + /** + * Base Weight texture (multiplier to the diffuse and metal lobes). + * @internal + */ + public _baseWeightTexture: Nullable = null; - // The code block below ensures backward compatibility with serialized materials before plugins are automatically serialized. - if (source.clearCoat) { - material.clearCoat.parse(source.clearCoat, scene, rootUrl); - } - if (source.anisotropy) { - material.anisotropy.parse(source.anisotropy, scene, rootUrl); - } - if (source.brdf) { - material.brdf.parse(source.brdf, scene, rootUrl); - } - if (source.sheen) { - material.sheen.parse(source.sheen, scene, rootUrl); - } - if (source.subSurface) { - material.subSurface.parse(source.subSurface, scene, rootUrl); - } - if (source.iridescence) { - material.iridescence.parse(source.iridescence, scene, rootUrl); - } + /** + * Base Diffuse Roughness texture (roughness of the diffuse lobe). + * @internal + */ + public _baseDiffuseRoughnessTexture: Nullable = null; - return material; - } + /** + * AKA Occlusion Texture in other nomenclature. + * @internal + */ + public _ambientTexture: Nullable = null; /** - * Force shader compilation - * @param mesh - Define the mesh we want to force the compilation for - * @param onCompiled - Define a callback triggered when the compilation completes - * @param options - Define the options used to create the compilation + * AKA Occlusion Texture Intensity in other nomenclature. + * @internal */ - public override forceCompilation(mesh: AbstractMesh, onCompiled?: (material: Material) => void, options?: Partial): void { - const localOptions = { - clipPlane: false, - useInstances: false, - ...options, - }; + public _ambientTextureStrength: number = 1.0; - if (!this._uniformBufferLayoutBuilt) { - this.buildUniformLayout(); - } + /** + * Defines how much the AO map is occluding the analytical lights (point spot...). + * 1 means it completely occludes it + * 0 mean it has no impact + * @internal + */ + public _ambientTextureImpactOnAnalyticalLights: number = PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; - this._callbackPluginEventGeneric(MaterialPluginEvent.GetDefineNames, this._eventInfo); - const checkReady = () => { - if (this._breakShaderLoadedCheck2) { - return; - } - const defines = new PBR2MaterialDefines(this._eventInfo.defineNames); - const effect = this._prepareEffect2(mesh, defines, undefined, undefined, localOptions.useInstances, localOptions.clipPlane, mesh.hasThinInstances)!; - if (this._onEffectCreatedObservable) { - onCreatedEffectParameters.effect = effect; - onCreatedEffectParameters.subMesh = null; - this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters); - } - if (effect.isReady()) { - if (onCompiled) { - onCompiled(this); - } - } else { - effect.onCompileObservable.add(() => { - if (onCompiled) { - onCompiled(this); - } - }); - } - }; - checkReady(); - } + /** + * Stores the alpha values in a texture. + * @internal + */ + public _opacityTexture: Nullable = null; /** - * Specifies that the submesh is ready to be used. - * @param mesh - BJS mesh. - * @param subMesh - A submesh of the BJS mesh. Used to check if it is ready. - * @param useInstances - Specifies that instances should be used. - * @returns - boolean indicating that the submesh is ready or not. + * Stores the reflection values in a texture. + * @internal */ - public override isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean { - if (!this._uniformBufferLayoutBuilt) { - this.buildUniformLayout(); - } + public _reflectionTexture: Nullable = null; - const drawWrapper = subMesh._drawWrapper; + /** + * Stores the emissive values in a texture. + * @internal + */ + public _emissiveTexture: Nullable = null; - if (drawWrapper.effect && this.isFrozen) { - if (drawWrapper._wasPreviouslyReady && drawWrapper._wasPreviouslyUsingInstances === useInstances) { - return true; - } - } + /** + * AKA Specular texture in other nomenclature. + * @internal + */ + public _reflectivityTexture: Nullable = null; - if (!subMesh.materialDefines) { - this._callbackPluginEventGeneric(MaterialPluginEvent.GetDefineNames, this._eventInfo); - subMesh.materialDefines = new PBR2MaterialDefines(this._eventInfo.defineNames); - } + /** + * Used to switch from specular/glossiness to metallic/roughness workflow. + * @internal + */ + public _metallicTexture: Nullable = null; - const defines = subMesh.materialDefines; - if (this._isReadyForSubMesh(subMesh)) { - return true; - } + /** + * Specifies the metallic scalar of the metallic/roughness workflow. + * Can also be used to scale the metalness values of the metallic texture. + * @internal + */ + public _metallic: Nullable = null; - const scene = this.getScene(); - const engine = scene.getEngine(); + /** + * Specifies the roughness scalar of the metallic/roughness workflow. + * Can also be used to scale the roughness values of the metallic texture. + * @internal + */ + public _roughness: Nullable = null; - if (defines._areTexturesDirty) { - this._eventInfo.hasRenderTargetTextures = false; - this._callbackPluginEventHasRenderTargetTextures(this._eventInfo); - this._cacheHasRenderTargetTextures = this._eventInfo.hasRenderTargetTextures; - if (scene.texturesEnabled) { - if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { - if (!this._albedoTexture.isReadyOrNotBlocking()) { - return false; - } - } + /** + * In metallic workflow, specifies an F0 factor to help configuring the material F0. + * By default the indexOfrefraction is used to compute F0; + * + * This is used as a factor against the default reflectance at normal incidence to tweak it. + * + * F0 = defaultF0 * metallicF0Factor * metallicReflectanceColor; + * F90 = metallicReflectanceColor; + * @internal + */ + public _metallicF0Factor = 1; - if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { - if (!this._baseWeightTexture.isReadyOrNotBlocking()) { - return false; - } + /** + * In metallic workflow, specifies an F0 color. + * By default the F90 is always 1; + * + * Please note that this factor is also used as a factor against the default reflectance at normal incidence. + * + * F0 = defaultF0_from_IOR * metallicF0Factor * metallicReflectanceColor + * F90 = metallicF0Factor; + * @internal + */ + public _metallicReflectanceColor = Color3.White(); + + /** + * Specifies that only the A channel from _metallicReflectanceTexture should be used. + * If false, both RGB and A channels will be used + * @internal + */ + public _useOnlyMetallicFromMetallicReflectanceTexture = false; + + /** + * Defines to store metallicReflectanceColor in RGB and metallicF0Factor in A + * This is multiply against the scalar values defined in the material. + * @internal + */ + public _metallicReflectanceTexture: Nullable = null; + + /** + * Defines to store reflectanceColor in RGB + * This is multiplied against the scalar values defined in the material. + * If both _reflectanceTexture and _metallicReflectanceTexture textures are provided and _useOnlyMetallicFromMetallicReflectanceTexture + * is false, _metallicReflectanceTexture takes precedence and _reflectanceTexture is not used + * @internal + */ + public _reflectanceTexture: Nullable = null; + + /** + * Used to enable roughness/glossiness fetch from a separate channel depending on the current mode. + * Gray Scale represents roughness in metallic mode and glossiness in specular mode. + * @internal + */ + public _microSurfaceTexture: Nullable = null; + + /** + * Stores surface normal data used to displace a mesh in a texture. + * @internal + */ + public _bumpTexture: Nullable = null; + + /** + * Stores the pre-calculated light information of a mesh in a texture. + * @internal + */ + public _lightmapTexture: Nullable = null; + + /** + * The color of a material in ambient lighting. + * @internal + */ + public _ambientColor = new Color3(0, 0, 0); + + /** + * AKA Diffuse Color in other nomenclature. + * @internal + */ + public _albedoColor = new Color3(1, 1, 1); + + /** + * Base Weight (multiplier to the diffuse and metal lobes). + * @internal + */ + public _baseWeight = 1; + + /** + * Base Diffuse Roughness (roughness of the diffuse lobe). + * Can also be used to scale the corresponding texture. + * @internal + */ + public _baseDiffuseRoughness: Nullable = null; + + /** + * AKA Specular Color in other nomenclature. + * @internal + */ + public _reflectivityColor = new Color3(1, 1, 1); + + /** + * The color applied when light is reflected from a material. + * @internal + */ + public _reflectionColor = new Color3(1, 1, 1); + + /** + * The color applied when light is emitted from a material. + * @internal + */ + public _emissiveColor = new Color3(0, 0, 0); + + /** + * AKA Glossiness in other nomenclature. + * @internal + */ + public _microSurface = 0.9; + + /** + * Specifies that the material will use the light map as a show map. + * @internal + */ + public _useLightmapAsShadowmap = false; + + /** + * This parameters will enable/disable Horizon occlusion to prevent normal maps to look shiny when the normal + * makes the reflect vector face the model (under horizon). + * @internal + */ + public _useHorizonOcclusion = true; + + /** + * This parameters will enable/disable radiance occlusion by preventing the radiance to lit + * too much the area relying on ambient texture to define their ambient occlusion. + * @internal + */ + public _useRadianceOcclusion = true; + + /** + * Specifies that the alpha is coming form the albedo channel alpha channel for alpha blending. + * @internal + */ + public _useAlphaFromAlbedoTexture = false; + + /** + * Specifies that the material will keeps the specular highlights over a transparent surface (only the most luminous ones). + * A car glass is a good example of that. When sun reflects on it you can not see what is behind. + * @internal + */ + public _useSpecularOverAlpha = true; + + /** + * Specifies if the reflectivity texture contains the glossiness information in its alpha channel. + * @internal + */ + public _useMicroSurfaceFromReflectivityMapAlpha = false; + + /** + * Specifies if the metallic texture contains the roughness information in its alpha channel. + * @internal + */ + public _useRoughnessFromMetallicTextureAlpha = true; + + /** + * Specifies if the metallic texture contains the roughness information in its green channel. + * @internal + */ + public _useRoughnessFromMetallicTextureGreen = false; + + /** + * Specifies if the metallic texture contains the metallness information in its blue channel. + * @internal + */ + public _useMetallnessFromMetallicTextureBlue = false; + + /** + * Specifies if the metallic texture contains the ambient occlusion information in its red channel. + * @internal + */ + public _useAmbientOcclusionFromMetallicTextureRed = false; + + /** + * Specifies if the ambient texture contains the ambient occlusion information in its red channel only. + * @internal + */ + public _useAmbientInGrayScale = false; + + /** + * In case the reflectivity map does not contain the microsurface information in its alpha channel, + * The material will try to infer what glossiness each pixel should be. + * @internal + */ + public _useAutoMicroSurfaceFromReflectivityMap = false; + + /** + * Defines the falloff type used in this material. + * It by default is Physical. + * @internal + */ + public _lightFalloff = PBRBaseMaterial.LIGHTFALLOFF_PHYSICAL; + + /** + * Specifies that the material will keeps the reflection highlights over a transparent surface (only the most luminous ones). + * A car glass is a good example of that. When the street lights reflects on it you can not see what is behind. + * @internal + */ + public _useRadianceOverAlpha = true; + + /** + * Allows using an object space normal map (instead of tangent space). + * @internal + */ + public _useObjectSpaceNormalMap = false; + + /** + * Allows using the bump map in parallax mode. + * @internal + */ + public _useParallax = false; + + /** + * Allows using the bump map in parallax occlusion mode. + * @internal + */ + public _useParallaxOcclusion = false; + + /** + * Controls the scale bias of the parallax mode. + * @internal + */ + public _parallaxScaleBias = 0.05; + + /** + * If sets to true, disables all the lights affecting the material. + * @internal + */ + public _disableLighting = false; + + /** + * Number of Simultaneous lights allowed on the material. + * @internal + */ + public _maxSimultaneousLights = 4; + + /** + * If sets to true, x component of normal map value will be inverted (x = 1.0 - x). + * @internal + */ + public _invertNormalMapX = false; + + /** + * If sets to true, y component of normal map value will be inverted (y = 1.0 - y). + * @internal + */ + public _invertNormalMapY = false; + + /** + * If sets to true and backfaceCulling is false, normals will be flipped on the backside. + * @internal + */ + public _twoSidedLighting = false; + + /** + * Defines the alpha limits in alpha test mode. + * @internal + */ + public _alphaCutOff = 0.4; + + /** + * A fresnel is applied to the alpha of the model to ensure grazing angles edges are not alpha tested. + * And/Or occlude the blended part. (alpha is converted to gamma to compute the fresnel) + * @internal + */ + public _useAlphaFresnel = false; + + /** + * A fresnel is applied to the alpha of the model to ensure grazing angles edges are not alpha tested. + * And/Or occlude the blended part. (alpha stays linear to compute the fresnel) + * @internal + */ + public _useLinearAlphaFresnel = false; + + /** + * Specifies the environment BRDF texture used to compute the scale and offset roughness values + * from cos theta and roughness: + * http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf + * @internal + */ + public _environmentBRDFTexture: Nullable = null; + + /** + * Force the shader to compute irradiance in the fragment shader in order to take bump in account. + * @internal + */ + public _forceIrradianceInFragment = false; + + private _realTimeFiltering: boolean = false; + /** + * Enables realtime filtering on the texture. + */ + public get realTimeFiltering() { + return this._realTimeFiltering; + } + public set realTimeFiltering(b: boolean) { + this._realTimeFiltering = b; + this.markAsDirty(Constants.MATERIAL_TextureDirtyFlag); + } + + private _realTimeFilteringQuality: number = Constants.TEXTURE_FILTERING_QUALITY_LOW; + /** + * Quality switch for realtime filtering + */ + public get realTimeFilteringQuality(): number { + return this._realTimeFilteringQuality; + } + public set realTimeFilteringQuality(n: number) { + this._realTimeFilteringQuality = n; + this.markAsDirty(Constants.MATERIAL_TextureDirtyFlag); + } + + /** + * Can this material render to several textures at once + */ + public override get canRenderToMRT() { + return true; + } + + /** + * Force normal to face away from face. + * @internal + */ + public _forceNormalForward = false; + + /** + * Enables specular anti aliasing in the PBR shader. + * It will both interacts on the Geometry for analytical and IBL lighting. + * It also prefilter the roughness map based on the bump values. + * @internal + */ + public _enableSpecularAntiAliasing = false; + + /** + * Stores the available render targets. + */ + private _renderTargets = new SmartArray(16); + + /** + * Sets the global ambient color for the material used in lighting calculations. + */ + private _globalAmbientColor = new Color3(0, 0, 0); + + /** + * If set to true, no lighting calculations will be applied. + */ + private _unlit = false; + + /** + * If sets to true, the decal map will be applied after the detail map. Else, it is applied before (default: false) + */ + private _applyDecalMapAfterDetailMap = false; + + private _debugMode = 0; + + private _shadersLoaded = false; + private _breakShaderLoadedCheck = false; + + /** + * @internal + * This is reserved for the inspector. + * Defines the material debug mode. + * It helps seeing only some components of the material while troubleshooting. + */ + @expandToProperty("_markAllSubMeshesAsMiscDirty") + public debugMode = 0; + + /** + * @internal + * This is reserved for the inspector. + * Specify from where on screen the debug mode should start. + * The value goes from -1 (full screen) to 1 (not visible) + * It helps with side by side comparison against the final render + * This defaults to -1 + */ + public debugLimit = -1; + + /** + * @internal + * This is reserved for the inspector. + * As the default viewing range might not be enough (if the ambient is really small for instance) + * You can use the factor to better multiply the final value. + */ + public debugFactor = 1; + + /** + * Defines additional PrePass parameters for the material. + */ + public readonly prePassConfiguration: PrePassConfiguration; + + protected _cacheHasRenderTargetTextures = false; + + /** + * Instantiates a new PBR2Material instance. + * + * @param name The material name + * @param scene The scene the material will be use in. + * @param forceGLSL Use the GLSL code generation for the shader (even on WebGPU). Default is false + */ + constructor(name: string, scene?: Scene, forceGLSL = false) { + super(name, scene, undefined, forceGLSL || PBRBaseMaterial.ForceGLSL); + + // Setup the default processing configuration to the scene. + this._attachImageProcessingConfiguration(null); + + this.getRenderTargetTextures = (): SmartArray => { + this._renderTargets.reset(); + + if (MaterialFlags.ReflectionTextureEnabled && this._reflectionTexture && this._reflectionTexture.isRenderTarget) { + this._renderTargets.push(this._reflectionTexture); + } + + this._eventInfo.renderTargets = this._renderTargets; + this._callbackPluginEventFillRenderTargetTextures(this._eventInfo); + + return this._renderTargets; + }; + + this._environmentBRDFTexture = GetEnvironmentBRDFTexture(this.getScene()); + this.prePassConfiguration = new PrePassConfiguration(); + this._environmentBRDFTexture = GetEnvironmentBRDFTexture(this.getScene()); + } + + /** + * Gets a boolean indicating that current material needs to register RTT + */ + public override get hasRenderTargetTextures(): boolean { + if (MaterialFlags.ReflectionTextureEnabled && this._reflectionTexture && this._reflectionTexture.isRenderTarget) { + return true; + } + + return this._cacheHasRenderTargetTextures; + } + + /** + * Can this material render to prepass + */ + public override get isPrePassCapable(): boolean { + return !this.disableDepthWrite; + } + + /** + * @returns the name of the material class. + */ + public override getClassName(): string { + return "PBR2Material"; + } + + /** + * Returns true if alpha blending should be disabled. + */ + protected override get _disableAlphaBlending(): boolean { + return this._transparencyMode === PBRBaseMaterial.PBRMATERIAL_OPAQUE || this._transparencyMode === PBRBaseMaterial.PBRMATERIAL_ALPHATEST; + } + + /** + * @returns whether or not this material should be rendered in alpha blend mode. + */ + public override needAlphaBlending(): boolean { + if (this._hasTransparencyMode) { + return this._transparencyModeIsBlend; + } + + if (this._disableAlphaBlending) { + return false; + } + + return this.alpha < 1.0 || this._opacityTexture != null || this._shouldUseAlphaFromAlbedoTexture(); + } + + /** + * @returns whether or not this material should be rendered in alpha test mode. + */ + public override needAlphaTesting(): boolean { + if (this._hasTransparencyMode) { + return this._transparencyModeIsTest; + } + + return this._hasAlphaChannel() && (this._transparencyMode == null || this._transparencyMode === PBRBaseMaterial.PBRMATERIAL_ALPHATEST); + } + + /** + * @returns whether or not the alpha value of the albedo texture should be used for alpha blending. + */ + protected _shouldUseAlphaFromAlbedoTexture(): boolean { + return this._albedoTexture != null && this._albedoTexture.hasAlpha && this._useAlphaFromAlbedoTexture && this._transparencyMode !== PBRBaseMaterial.PBRMATERIAL_OPAQUE; + } + + /** + * @returns whether or not there is a usable alpha channel for transparency. + */ + protected _hasAlphaChannel(): boolean { + return (this._albedoTexture != null && this._albedoTexture.hasAlpha) || this._opacityTexture != null; + } + + /** + * @returns the texture used for the alpha test. + */ + public override getAlphaTestTexture(): Nullable { + return this._albedoTexture; + } + + /** + * Makes a duplicate of the current material. + * @param name - name to use for the new material. + * @param cloneTexturesOnlyOnce - if a texture is used in more than one channel (e.g diffuse and opacity), only clone it once and reuse it on the other channels. Default false. + * @param rootUrl defines the root URL to use to load textures + * @returns cloned material instance + */ + public override clone(name: string, cloneTexturesOnlyOnce: boolean = true, rootUrl = ""): PBR2Material { + const clone = SerializationHelper.Clone(() => new PBR2Material(name, this.getScene()), this, { cloneTexturesOnlyOnce }); + + clone.id = name; + clone.name = name; + + this.stencil.copyTo(clone.stencil); + + this._clonePlugins(clone, rootUrl); + + return clone; + } + + /** + * Serializes this PBR Material. + * @returns - An object with the serialized material. + */ + public override serialize(): any { + const serializationObject = super.serialize(); + serializationObject.customType = "BABYLON.PBR2Material"; + + return serializationObject; + } + + // Statics + /** + * Parses a PBR Material from a serialized object. + * @param source - Serialized object. + * @param scene - BJS scene instance. + * @param rootUrl - url for the scene object + * @returns - PBR2Material + */ + public static override Parse(source: any, scene: Scene, rootUrl: string): PBR2Material { + const material = SerializationHelper.Parse(() => new PBR2Material(source.name, scene), source, scene, rootUrl); + + if (source.stencil) { + material.stencil.parse(source.stencil, scene, rootUrl); + } + + Material._ParsePlugins(source, material, scene, rootUrl); + + return material; + } + + /** + * Force shader compilation + * @param mesh - Define the mesh we want to force the compilation for + * @param onCompiled - Define a callback triggered when the compilation completes + * @param options - Define the options used to create the compilation + */ + public override forceCompilation(mesh: AbstractMesh, onCompiled?: (material: Material) => void, options?: Partial): void { + const localOptions = { + clipPlane: false, + useInstances: false, + ...options, + }; + + if (!this._uniformBufferLayoutBuilt) { + this.buildUniformLayout(); + } + + this._callbackPluginEventGeneric(MaterialPluginEvent.GetDefineNames, this._eventInfo); + const checkReady = () => { + if (this._breakShaderLoadedCheck) { + return; + } + const defines = new PBR2MaterialDefines(this._eventInfo.defineNames); + const effect = this._prepareEffect(mesh, defines, undefined, undefined, localOptions.useInstances, localOptions.clipPlane, mesh.hasThinInstances)!; + if (this._onEffectCreatedObservable) { + onCreatedEffectParameters.effect = effect; + onCreatedEffectParameters.subMesh = null; + this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters); + } + if (effect.isReady()) { + if (onCompiled) { + onCompiled(this); + } + } else { + effect.onCompileObservable.add(() => { + if (onCompiled) { + onCompiled(this); + } + }); + } + }; + checkReady(); + } + + /** + * Specifies that the submesh is ready to be used. + * @param mesh - BJS mesh. + * @param subMesh - A submesh of the BJS mesh. Used to check if it is ready. + * @param useInstances - Specifies that instances should be used. + * @returns - boolean indicating that the submesh is ready or not. + */ + public override isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean { + if (!this._uniformBufferLayoutBuilt) { + this.buildUniformLayout(); + } + + const drawWrapper = subMesh._drawWrapper; + + if (drawWrapper.effect && this.isFrozen) { + if (drawWrapper._wasPreviouslyReady && drawWrapper._wasPreviouslyUsingInstances === useInstances) { + return true; + } + } + + if (!subMesh.materialDefines) { + this._callbackPluginEventGeneric(MaterialPluginEvent.GetDefineNames, this._eventInfo); + subMesh.materialDefines = new PBR2MaterialDefines(this._eventInfo.defineNames); + } + + const defines = subMesh.materialDefines; + if (this._isReadyForSubMesh(subMesh)) { + return true; + } + + const scene = this.getScene(); + const engine = scene.getEngine(); + + if (defines._areTexturesDirty) { + this._eventInfo.hasRenderTargetTextures = false; + this._callbackPluginEventHasRenderTargetTextures(this._eventInfo); + this._cacheHasRenderTargetTextures = this._eventInfo.hasRenderTargetTextures; + if (scene.texturesEnabled) { + if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { + if (!this._albedoTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { + if (!this._baseWeightTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._baseDiffuseRoughnessTexture && MaterialFlags.BaseDiffuseRoughnessTextureEnabled) { + if (!this._baseDiffuseRoughnessTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { + if (!this._ambientTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._opacityTexture && MaterialFlags.OpacityTextureEnabled) { + if (!this._opacityTexture.isReadyOrNotBlocking()) { + return false; + } + } + + const reflectionTexture = this._getReflectionTexture2(); + if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { + if (!reflectionTexture.isReadyOrNotBlocking()) { + return false; + } + if (reflectionTexture.irradianceTexture) { + if (!reflectionTexture.irradianceTexture.isReadyOrNotBlocking()) { + return false; + } + } else { + // Not ready until spherical are ready too. + if (!reflectionTexture.sphericalPolynomial && reflectionTexture.getInternalTexture()?._sphericalPolynomialPromise) { + return false; + } + } + } + + if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { + if (!this._lightmapTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { + if (!this._emissiveTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (MaterialFlags.SpecularTextureEnabled) { + if (this._metallicTexture) { + if (!this._metallicTexture.isReadyOrNotBlocking()) { + return false; + } + } else if (this._reflectivityTexture) { + if (!this._reflectivityTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._metallicReflectanceTexture) { + if (!this._metallicReflectanceTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._reflectanceTexture) { + if (!this._reflectanceTexture.isReadyOrNotBlocking()) { + return false; + } + } + + if (this._microSurfaceTexture) { + if (!this._microSurfaceTexture.isReadyOrNotBlocking()) { + return false; + } + } + } + + if (engine.getCaps().standardDerivatives && this._bumpTexture && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { + // Bump texture cannot be not blocking. + if (!this._bumpTexture.isReady()) { + return false; + } + } + + if (this._environmentBRDFTexture && MaterialFlags.ReflectionTextureEnabled) { + // This is blocking. + if (!this._environmentBRDFTexture.isReady()) { + return false; + } + } + } + } + + this._eventInfo.isReadyForSubMesh = true; + this._eventInfo.defines = defines; + this._eventInfo.subMesh = subMesh; + this._callbackPluginEventIsReadyForSubMesh(this._eventInfo); + + if (!this._eventInfo.isReadyForSubMesh) { + return false; + } + + if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) { + if (!this._imageProcessingConfiguration.isReady()) { + return false; + } + } + + // Check if Area Lights have LTC texture. + if (defines["AREALIGHTUSED"]) { + for (let index = 0; index < mesh.lightSources.length; index++) { + if (!mesh.lightSources[index]._isReady()) { + return false; + } + } + } + + if (!engine.getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) { + mesh.createNormals(true); + Logger.Warn("PBR2Material: Normals have been created for the mesh: " + mesh.name); + } + + const previousEffect = subMesh.effect; + const lightDisposed = defines._areLightsDisposed; + let effect = this._prepareEffect(mesh, defines, this.onCompiled, this.onError, useInstances, null, subMesh.getRenderingMesh().hasThinInstances); + + let forceWasNotReadyPreviously = false; + + if (effect) { + if (this._onEffectCreatedObservable) { + onCreatedEffectParameters.effect = effect; + onCreatedEffectParameters.subMesh = subMesh; + this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters); + } + + // Use previous effect while new one is compiling + if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) { + effect = previousEffect; + defines.markAsUnprocessed(); + + forceWasNotReadyPreviously = this.isFrozen; + + if (lightDisposed) { + // re register in case it takes more than one frame. + defines._areLightsDisposed = true; + return false; + } + } else { + scene.resetCachedMaterial(); + subMesh.setEffect(effect, defines, this._materialContext); + } + } + + if (!subMesh.effect || !subMesh.effect.isReady()) { + return false; + } + + defines._renderId = scene.getRenderId(); + drawWrapper._wasPreviouslyReady = forceWasNotReadyPreviously ? false : true; + drawWrapper._wasPreviouslyUsingInstances = !!useInstances; + + this._checkScenePerformancePriority(); + + return true; + } + + /** + * Initializes the uniform buffer layout for the shader. + */ + public override buildUniformLayout(): void { + // Order is important ! + const ubo = this._uniformBuffer; + ubo.addUniform("vAlbedoInfos", 2); + ubo.addUniform("vBaseWeightInfos", 2); + ubo.addUniform("vBaseDiffuseRoughnessInfos", 2); + ubo.addUniform("vAmbientInfos", 4); + ubo.addUniform("vOpacityInfos", 2); + ubo.addUniform("vEmissiveInfos", 2); + ubo.addUniform("vLightmapInfos", 2); + ubo.addUniform("vReflectivityInfos", 3); + ubo.addUniform("vMicroSurfaceSamplerInfos", 2); + ubo.addUniform("vBumpInfos", 3); + ubo.addUniform("albedoMatrix", 16); + ubo.addUniform("baseWeightMatrix", 16); + ubo.addUniform("baseDiffuseRoughnessMatrix", 16); + ubo.addUniform("ambientMatrix", 16); + ubo.addUniform("opacityMatrix", 16); + ubo.addUniform("emissiveMatrix", 16); + ubo.addUniform("lightmapMatrix", 16); + ubo.addUniform("reflectivityMatrix", 16); + ubo.addUniform("microSurfaceSamplerMatrix", 16); + ubo.addUniform("bumpMatrix", 16); + ubo.addUniform("vTangentSpaceParams", 2); + ubo.addUniform("vAlbedoColor", 4); + ubo.addUniform("baseWeight", 1); + ubo.addUniform("baseDiffuseRoughness", 1); + ubo.addUniform("vLightingIntensity", 4); + + ubo.addUniform("pointSize", 1); + ubo.addUniform("vReflectivityColor", 4); + ubo.addUniform("vEmissiveColor", 3); + ubo.addUniform("vAmbientColor", 3); + + ubo.addUniform("vDebugMode", 2); + + ubo.addUniform("vMetallicReflectanceFactors", 4); + ubo.addUniform("vMetallicReflectanceInfos", 2); + ubo.addUniform("metallicReflectanceMatrix", 16); + ubo.addUniform("vReflectanceInfos", 2); + ubo.addUniform("reflectanceMatrix", 16); + + ubo.addUniform("cameraInfo", 4); + PrepareUniformLayoutForIBL(ubo, true, true, true, true, true); + super.buildUniformLayout(); + } + + /** + * Binds the submesh data. + * @param world - The world matrix. + * @param mesh - The BJS mesh. + * @param subMesh - A submesh of the BJS mesh. + */ + public override bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void { + const scene = this.getScene(); + + const defines = subMesh.materialDefines; + if (!defines) { + return; + } + + const effect = subMesh.effect; + + if (!effect) { + return; + } + + this._activeEffect = effect; + + // Matrices Mesh. + mesh.getMeshUniformBuffer().bindToEffect(effect, "Mesh"); + mesh.transferToEffect(world); + + const engine = scene.getEngine(); + + // Binding unconditionally + this._uniformBuffer.bindToEffect(effect, "Material"); + + this.prePassConfiguration.bindForSubMesh(this._activeEffect, scene, mesh, world, this.isFrozen); + + MaterialHelperGeometryRendering.Bind(engine.currentRenderPassId, this._activeEffect, mesh, world, this); + + const camera = scene.activeCamera; + if (camera) { + this._uniformBuffer.updateFloat4("cameraInfo", camera.minZ, camera.maxZ, 0, 0); + } else { + this._uniformBuffer.updateFloat4("cameraInfo", 0, 0, 0, 0); + } + + this._eventInfo.subMesh = subMesh; + this._callbackPluginEventHardBindForSubMesh(this._eventInfo); + + // Normal Matrix + if (defines.OBJECTSPACE_NORMALMAP) { + world.toNormalMatrix(this._normalMatrix); + this.bindOnlyNormalMatrix(this._normalMatrix); + } + + const mustRebind = this._mustRebind(scene, effect, subMesh, mesh.visibility); + + // Bones + BindBonesParameters(mesh, this._activeEffect, this.prePassConfiguration); + + let reflectionTexture: Nullable = null; + const ubo = this._uniformBuffer; + if (mustRebind) { + this.bindViewProjection(effect); + reflectionTexture = this._getReflectionTexture(); + + if (!ubo.useUbo || !this.isFrozen || !ubo.isSync || subMesh._drawWrapper._forceRebindOnNextCall) { + // Texture uniforms + if (scene.texturesEnabled) { + if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { + ubo.updateFloat2("vAlbedoInfos", this._albedoTexture.coordinatesIndex, this._albedoTexture.level); + BindTextureMatrix(this._albedoTexture, ubo, "albedo"); + } + + if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { + ubo.updateFloat2("vBaseWeightInfos", this._baseWeightTexture.coordinatesIndex, this._baseWeightTexture.level); + BindTextureMatrix(this._baseWeightTexture, ubo, "baseWeight"); + } + + if (this._baseDiffuseRoughnessTexture && MaterialFlags.BaseDiffuseRoughnessTextureEnabled) { + ubo.updateFloat2("vBaseDiffuseRoughnessInfos", this._baseDiffuseRoughnessTexture.coordinatesIndex, this._baseDiffuseRoughnessTexture.level); + BindTextureMatrix(this._baseDiffuseRoughnessTexture, ubo, "baseDiffuseRoughness"); + } + + if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { + ubo.updateFloat4( + "vAmbientInfos", + this._ambientTexture.coordinatesIndex, + this._ambientTexture.level, + this._ambientTextureStrength, + this._ambientTextureImpactOnAnalyticalLights + ); + BindTextureMatrix(this._ambientTexture, ubo, "ambient"); + } + + if (this._opacityTexture && MaterialFlags.OpacityTextureEnabled) { + ubo.updateFloat2("vOpacityInfos", this._opacityTexture.coordinatesIndex, this._opacityTexture.level); + BindTextureMatrix(this._opacityTexture, ubo, "opacity"); + } + + if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { + ubo.updateFloat2("vEmissiveInfos", this._emissiveTexture.coordinatesIndex, this._emissiveTexture.level); + BindTextureMatrix(this._emissiveTexture, ubo, "emissive"); + } + + if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { + ubo.updateFloat2("vLightmapInfos", this._lightmapTexture.coordinatesIndex, this._lightmapTexture.level); + BindTextureMatrix(this._lightmapTexture, ubo, "lightmap"); + } + + if (MaterialFlags.SpecularTextureEnabled) { + if (this._metallicTexture) { + ubo.updateFloat3("vReflectivityInfos", this._metallicTexture.coordinatesIndex, this._metallicTexture.level, this._ambientTextureStrength); + BindTextureMatrix(this._metallicTexture, ubo, "reflectivity"); + } else if (this._reflectivityTexture) { + ubo.updateFloat3("vReflectivityInfos", this._reflectivityTexture.coordinatesIndex, this._reflectivityTexture.level, 1.0); + BindTextureMatrix(this._reflectivityTexture, ubo, "reflectivity"); + } + + if (this._metallicReflectanceTexture) { + ubo.updateFloat2("vMetallicReflectanceInfos", this._metallicReflectanceTexture.coordinatesIndex, this._metallicReflectanceTexture.level); + BindTextureMatrix(this._metallicReflectanceTexture, ubo, "metallicReflectance"); + } + + if (this._reflectanceTexture && defines.REFLECTANCE) { + ubo.updateFloat2("vReflectanceInfos", this._reflectanceTexture.coordinatesIndex, this._reflectanceTexture.level); + BindTextureMatrix(this._reflectanceTexture, ubo, "reflectance"); + } + + if (this._microSurfaceTexture) { + ubo.updateFloat2("vMicroSurfaceSamplerInfos", this._microSurfaceTexture.coordinatesIndex, this._microSurfaceTexture.level); + BindTextureMatrix(this._microSurfaceTexture, ubo, "microSurfaceSampler"); + } + } + + if (this._bumpTexture && engine.getCaps().standardDerivatives && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { + ubo.updateFloat3("vBumpInfos", this._bumpTexture.coordinatesIndex, this._bumpTexture.level, this._parallaxScaleBias); + BindTextureMatrix(this._bumpTexture, ubo, "bump"); + + if (scene._mirroredCameraPosition) { + ubo.updateFloat2("vTangentSpaceParams", this._invertNormalMapX ? 1.0 : -1.0, this._invertNormalMapY ? 1.0 : -1.0); + } else { + ubo.updateFloat2("vTangentSpaceParams", this._invertNormalMapX ? -1.0 : 1.0, this._invertNormalMapY ? -1.0 : 1.0); + } + } + } + + BindIBLParameters(scene, defines, ubo, reflectionTexture, this.realTimeFiltering, true, true, true, true, true, this._reflectionColor); + + // Point size + if (this.pointsCloud) { + ubo.updateFloat("pointSize", this.pointSize); + } + + // Colors + if (defines.METALLICWORKFLOW) { + TmpColors.Color4[0].r = this._metallic === undefined || this._metallic === null ? 1 : this._metallic; + TmpColors.Color4[0].g = this._roughness === undefined || this._roughness === null ? 1 : this._roughness; + const ior = 1.5; + const outsideIOR = 1; // consider air as clear coat and other layers would remap in the shader. + TmpColors.Color4[0].b = ior; + // We are here deriving our default reflectance from a common value for none metallic surface. + // Based of the schlick fresnel approximation model + // for dielectrics. + const f0 = Math.pow((ior - outsideIOR) / (ior + outsideIOR), 2); + TmpColors.Color4[0].a = f0; + ubo.updateDirectColor4("vReflectivityColor", TmpColors.Color4[0]); + ubo.updateColor4("vMetallicReflectanceFactors", this._metallicReflectanceColor, this._metallicF0Factor); + } else { + ubo.updateColor4("vReflectivityColor", this._reflectivityColor, this._microSurface); + } + + ubo.updateColor3("vEmissiveColor", MaterialFlags.EmissiveTextureEnabled ? this._emissiveColor : Color3.BlackReadOnly); + + ubo.updateColor4("vAlbedoColor", this._albedoColor, this.alpha); + + ubo.updateFloat("baseWeight", this._baseWeight); + ubo.updateFloat("baseDiffuseRoughness", this._baseDiffuseRoughness || 0.0); + + // Misc + this._lightingInfos.x = this._directIntensity; + this._lightingInfos.y = this._emissiveIntensity; + this._lightingInfos.z = this._environmentIntensity * scene.environmentIntensity; + this._lightingInfos.w = this._specularIntensity; + + ubo.updateVector4("vLightingIntensity", this._lightingInfos); + + // Colors + scene.ambientColor.multiplyToRef(this._ambientColor, this._globalAmbientColor); + + ubo.updateColor3("vAmbientColor", this._globalAmbientColor); + + ubo.updateFloat2("vDebugMode", this.debugLimit, this.debugFactor); + } + + // Textures + if (scene.texturesEnabled) { + if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { + ubo.setTexture("albedoSampler", this._albedoTexture); + } + + if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { + ubo.setTexture("baseWeightSampler", this._baseWeightTexture); } if (this._baseDiffuseRoughnessTexture && MaterialFlags.BaseDiffuseRoughnessTextureEnabled) { - if (!this._baseDiffuseRoughnessTexture.isReadyOrNotBlocking()) { - return false; - } + ubo.setTexture("baseDiffuseRoughnessSampler", this._baseDiffuseRoughnessTexture); } if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { - if (!this._ambientTexture.isReadyOrNotBlocking()) { - return false; - } + ubo.setTexture("ambientSampler", this._ambientTexture); } if (this._opacityTexture && MaterialFlags.OpacityTextureEnabled) { - if (!this._opacityTexture.isReadyOrNotBlocking()) { - return false; - } + ubo.setTexture("opacitySampler", this._opacityTexture); } - const reflectionTexture = this._getReflectionTexture2(); - if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { - if (!reflectionTexture.isReadyOrNotBlocking()) { - return false; - } - if (reflectionTexture.irradianceTexture) { - if (!reflectionTexture.irradianceTexture.isReadyOrNotBlocking()) { - return false; - } - } else { - // Not ready until spherical are ready too. - if (!reflectionTexture.sphericalPolynomial && reflectionTexture.getInternalTexture()?._sphericalPolynomialPromise) { - return false; - } - } - } + BindIBLSamplers(scene, defines, ubo, reflectionTexture, this.realTimeFiltering); - if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { - if (!this._lightmapTexture.isReadyOrNotBlocking()) { - return false; - } + if (defines.ENVIRONMENTBRDF) { + ubo.setTexture("environmentBrdfSampler", this._environmentBRDFTexture); } if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { - if (!this._emissiveTexture.isReadyOrNotBlocking()) { - return false; - } + ubo.setTexture("emissiveSampler", this._emissiveTexture); + } + + if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { + ubo.setTexture("lightmapSampler", this._lightmapTexture); } if (MaterialFlags.SpecularTextureEnabled) { if (this._metallicTexture) { - if (!this._metallicTexture.isReadyOrNotBlocking()) { - return false; - } + ubo.setTexture("reflectivitySampler", this._metallicTexture); } else if (this._reflectivityTexture) { - if (!this._reflectivityTexture.isReadyOrNotBlocking()) { - return false; - } + ubo.setTexture("reflectivitySampler", this._reflectivityTexture); } if (this._metallicReflectanceTexture) { - if (!this._metallicReflectanceTexture.isReadyOrNotBlocking()) { - return false; - } + ubo.setTexture("metallicReflectanceSampler", this._metallicReflectanceTexture); } - if (this._reflectanceTexture) { - if (!this._reflectanceTexture.isReadyOrNotBlocking()) { - return false; - } + if (this._reflectanceTexture && defines.REFLECTANCE) { + ubo.setTexture("reflectanceSampler", this._reflectanceTexture); } if (this._microSurfaceTexture) { - if (!this._microSurfaceTexture.isReadyOrNotBlocking()) { - return false; - } + ubo.setTexture("microSurfaceSampler", this._microSurfaceTexture); } } - if (engine.getCaps().standardDerivatives && this._bumpTexture && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { - // Bump texture cannot be not blocking. - if (!this._bumpTexture.isReady()) { - return false; - } + if (this._bumpTexture && engine.getCaps().standardDerivatives && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { + ubo.setTexture("bumpSampler", this._bumpTexture); } + } - if (this._environmentBRDFTexture && MaterialFlags.ReflectionTextureEnabled) { - // This is blocking. - if (!this._environmentBRDFTexture.isReady()) { - return false; - } - } + // OIT with depth peeling + if (this.getScene().useOrderIndependentTransparency && this.needAlphaBlendingForMesh(mesh)) { + this.getScene().depthPeelingRenderer!.bind(effect); } - } - this._eventInfo.isReadyForSubMesh = true; - this._eventInfo.defines = defines; - this._eventInfo.subMesh = subMesh; - this._callbackPluginEventIsReadyForSubMesh(this._eventInfo); + this._eventInfo.subMesh = subMesh; + this._callbackPluginEventBindForSubMesh(this._eventInfo); - if (!this._eventInfo.isReadyForSubMesh) { - return false; + // Clip plane + BindClipPlane(this._activeEffect, this, scene); + + this.bindEyePosition(effect); + } else if (scene.getEngine()._features.needToAlwaysBindUniformBuffers) { + this._needToBindSceneUbo = true; } - if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) { - if (!this._imageProcessingConfiguration.isReady()) { - return false; + if (mustRebind || !this.isFrozen) { + // Lights + if (scene.lightsEnabled && !this._disableLighting) { + BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights); } - } - // Check if Area Lights have LTC texture. - if (defines["AREALIGHTUSED"]) { - for (let index = 0; index < mesh.lightSources.length; index++) { - if (!mesh.lightSources[index]._isReady()) { - return false; - } + // View + if ((scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) || reflectionTexture || mesh.receiveShadows || defines.PREPASS) { + this.bindView(effect); + } + + // Fog + BindFogParameters(scene, mesh, this._activeEffect, true); + + // Morph targets + if (defines.NUM_MORPH_INFLUENCERS) { + BindMorphTargetParameters(mesh, this._activeEffect); + } + + if (defines.BAKED_VERTEX_ANIMATION_TEXTURE) { + mesh.bakedVertexAnimationManager?.bind(effect, defines.INSTANCES); } + + // image processing + this._imageProcessingConfiguration.bind(this._activeEffect); + + // Log. depth + BindLogDepth(defines, this._activeEffect, scene); } - if (!engine.getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) { - mesh.createNormals(true); - Logger.Warn("PBR2Material: Normals have been created for the mesh: " + mesh.name); + this._afterBind(mesh, this._activeEffect, subMesh); + + ubo.update(); + } + + /** + * Returns the animatable textures. + * If material have animatable metallic texture, then reflectivity texture will not be returned, even if it has animations. + * @returns - Array of animatable textures. + */ + public override getAnimatables(): IAnimatable[] { + const results = super.getAnimatables(); + + if (this._albedoTexture && this._albedoTexture.animations && this._albedoTexture.animations.length > 0) { + results.push(this._albedoTexture); } - const previousEffect = subMesh.effect; - const lightDisposed = defines._areLightsDisposed; - let effect = this._prepareEffect2(mesh, defines, this.onCompiled, this.onError, useInstances, null, subMesh.getRenderingMesh().hasThinInstances); + if (this._baseWeightTexture && this._baseWeightTexture.animations && this._baseWeightTexture.animations.length > 0) { + results.push(this._baseWeightTexture); + } - let forceWasNotReadyPreviously = false; + if (this._baseDiffuseRoughnessTexture && this._baseDiffuseRoughnessTexture.animations && this._baseDiffuseRoughnessTexture.animations.length > 0) { + results.push(this._baseDiffuseRoughnessTexture); + } - if (effect) { - if (this._onEffectCreatedObservable) { - onCreatedEffectParameters.effect = effect; - onCreatedEffectParameters.subMesh = subMesh; - this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters); - } + if (this._ambientTexture && this._ambientTexture.animations && this._ambientTexture.animations.length > 0) { + results.push(this._ambientTexture); + } - // Use previous effect while new one is compiling - if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) { - effect = previousEffect; - defines.markAsUnprocessed(); + if (this._opacityTexture && this._opacityTexture.animations && this._opacityTexture.animations.length > 0) { + results.push(this._opacityTexture); + } - forceWasNotReadyPreviously = this.isFrozen; + if (this._reflectionTexture && this._reflectionTexture.animations && this._reflectionTexture.animations.length > 0) { + results.push(this._reflectionTexture); + } - if (lightDisposed) { - // re register in case it takes more than one frame. - defines._areLightsDisposed = true; - return false; - } - } else { - scene.resetCachedMaterial(); - subMesh.setEffect(effect, defines, this._materialContext); + if (this._emissiveTexture && this._emissiveTexture.animations && this._emissiveTexture.animations.length > 0) { + results.push(this._emissiveTexture); + } + + if (this._metallicTexture && this._metallicTexture.animations && this._metallicTexture.animations.length > 0) { + results.push(this._metallicTexture); + } else if (this._reflectivityTexture && this._reflectivityTexture.animations && this._reflectivityTexture.animations.length > 0) { + results.push(this._reflectivityTexture); + } + + if (this._bumpTexture && this._bumpTexture.animations && this._bumpTexture.animations.length > 0) { + results.push(this._bumpTexture); + } + + if (this._lightmapTexture && this._lightmapTexture.animations && this._lightmapTexture.animations.length > 0) { + results.push(this._lightmapTexture); + } + + if (this._metallicReflectanceTexture && this._metallicReflectanceTexture.animations && this._metallicReflectanceTexture.animations.length > 0) { + results.push(this._metallicReflectanceTexture); + } + + if (this._reflectanceTexture && this._reflectanceTexture.animations && this._reflectanceTexture.animations.length > 0) { + results.push(this._reflectanceTexture); + } + + if (this._microSurfaceTexture && this._microSurfaceTexture.animations && this._microSurfaceTexture.animations.length > 0) { + results.push(this._microSurfaceTexture); + } + + return results; + } + + /** + * Returns an array of the actively used textures. + * @returns - Array of BaseTextures + */ + public override getActiveTextures(): BaseTexture[] { + const activeTextures = super.getActiveTextures(); + + if (this._albedoTexture) { + activeTextures.push(this._albedoTexture); + } + + if (this._baseWeightTexture) { + activeTextures.push(this._baseWeightTexture); + } + + if (this._baseDiffuseRoughnessTexture) { + activeTextures.push(this._baseDiffuseRoughnessTexture); + } + + if (this._ambientTexture) { + activeTextures.push(this._ambientTexture); + } + + if (this._opacityTexture) { + activeTextures.push(this._opacityTexture); + } + + if (this._reflectionTexture) { + activeTextures.push(this._reflectionTexture); + } + + if (this._emissiveTexture) { + activeTextures.push(this._emissiveTexture); + } + + if (this._reflectivityTexture) { + activeTextures.push(this._reflectivityTexture); + } + + if (this._metallicTexture) { + activeTextures.push(this._metallicTexture); + } + + if (this._metallicReflectanceTexture) { + activeTextures.push(this._metallicReflectanceTexture); + } + + if (this._reflectanceTexture) { + activeTextures.push(this._reflectanceTexture); + } + + if (this._microSurfaceTexture) { + activeTextures.push(this._microSurfaceTexture); + } + + if (this._bumpTexture) { + activeTextures.push(this._bumpTexture); + } + + if (this._lightmapTexture) { + activeTextures.push(this._lightmapTexture); + } + + return activeTextures; + } + + /** + * Checks to see if a texture is used in the material. + * @param texture - Base texture to use. + * @returns - Boolean specifying if a texture is used in the material. + */ + public override hasTexture(texture: BaseTexture): boolean { + if (super.hasTexture(texture)) { + return true; + } + + if (this._albedoTexture === texture) { + return true; + } + + if (this._baseWeightTexture === texture) { + return true; + } + + if (this._baseDiffuseRoughnessTexture === texture) { + return true; + } + + if (this._ambientTexture === texture) { + return true; + } + + if (this._opacityTexture === texture) { + return true; + } + + if (this._reflectionTexture === texture) { + return true; + } + + if (this._emissiveTexture === texture) { + return true; + } + + if (this._reflectivityTexture === texture) { + return true; + } + + if (this._metallicTexture === texture) { + return true; + } + + if (this._metallicReflectanceTexture === texture) { + return true; + } + + if (this._reflectanceTexture === texture) { + return true; + } + + if (this._microSurfaceTexture === texture) { + return true; + } + + if (this._bumpTexture === texture) { + return true; + } + + if (this._lightmapTexture === texture) { + return true; + } + + return false; + } + + /** + * Sets the required values to the prepass renderer. + * It can't be sets when subsurface scattering of this material is disabled. + * When scene have ability to enable subsurface prepass effect, it will enable. + * @returns - If prepass is enabled or not. + */ + public override setPrePassRenderer(): boolean { + return false; + } + + /** + * Disposes the resources of the material. + * @param forceDisposeEffect - Forces the disposal of effects. + * @param forceDisposeTextures - Forces the disposal of all textures. + */ + public override dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void { + this._breakShaderLoadedCheck = true; + if (forceDisposeTextures) { + if (this._environmentBRDFTexture && this.getScene().environmentBRDFTexture !== this._environmentBRDFTexture) { + this._environmentBRDFTexture.dispose(); } + + this._albedoTexture?.dispose(); + this._baseWeightTexture?.dispose(); + this._baseDiffuseRoughnessTexture?.dispose(); + this._ambientTexture?.dispose(); + this._opacityTexture?.dispose(); + this._reflectionTexture?.dispose(); + this._emissiveTexture?.dispose(); + this._metallicTexture?.dispose(); + this._reflectivityTexture?.dispose(); + this._bumpTexture?.dispose(); + this._lightmapTexture?.dispose(); + this._metallicReflectanceTexture?.dispose(); + this._reflectanceTexture?.dispose(); + this._microSurfaceTexture?.dispose(); } - if (!subMesh.effect || !subMesh.effect.isReady()) { - return false; + this._renderTargets.dispose(); + + if (this._imageProcessingConfiguration && this._imageProcessingObserver) { + this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver); } - defines._renderId = scene.getRenderId(); - drawWrapper._wasPreviouslyReady = forceWasNotReadyPreviously ? false : true; - drawWrapper._wasPreviouslyUsingInstances = !!useInstances; + super.dispose(forceDisposeEffect, forceDisposeTextures); + } - this._checkScenePerformancePriority(); + /** + * Returns the texture used for reflections. + * @returns - Reflection texture if present. Otherwise, returns the environment texture. + */ + private _getReflectionTexture(): Nullable { + if (this._reflectionTexture) { + return this._reflectionTexture; + } - return true; + return this.getScene().environmentTexture; } - private _prepareEffect2( + private _prepareEffect( mesh: AbstractMesh, defines: PBR2MaterialDefines, onCompiled: Nullable<(effect: Effect) => void> = null, @@ -1348,7 +2529,7 @@ export class PBR2Material extends PBRBaseMaterial { useClipPlane: Nullable = null, useThinInstances: boolean ): Nullable { - this._prepareDefines2(mesh, defines, useInstances, useClipPlane, useThinInstances); + this._prepareDefines(mesh, defines, useInstances, useClipPlane, useThinInstances); if (!defines.isDirty) { return null; @@ -1605,7 +2786,7 @@ export class PBR2Material extends PBRBaseMaterial { processCodeAfterIncludes: this._eventInfo.customCode, multiTarget: defines.PREPASS, shaderLanguage: this._shaderLanguage, - extraInitializationsAsync: this._shadersLoaded2 + extraInitializationsAsync: this._shadersLoaded ? undefined : async () => { if (this.shaderLanguage === ShaderLanguage.WGSL) { @@ -1614,7 +2795,7 @@ export class PBR2Material extends PBRBaseMaterial { await Promise.all([import("../../Shaders/pbr2.vertex"), import("../../Shaders/pbr2.fragment")]); } - this._shadersLoaded2 = true; + this._shadersLoaded = true; }, }, engine @@ -1625,7 +2806,7 @@ export class PBR2Material extends PBRBaseMaterial { return effect; } - private _prepareDefines2( + private _prepareDefines( mesh: AbstractMesh, defines: PBR2MaterialDefines, useInstances: Nullable = null, @@ -1652,7 +2833,7 @@ export class PBR2Material extends PBRBaseMaterial { MaterialHelperGeometryRendering.PrepareDefines(engine.currentRenderPassId, mesh, defines); // Textures - defines.METALLICWORKFLOW = this.isMetallicWorkflow(); + defines.METALLICWORKFLOW = true; if (defines._areTexturesDirty) { defines._needUVs = false; for (let i = 1; i <= Constants.MAX_SUPPORTED_UV_SETS; ++i) { @@ -1660,6 +2841,8 @@ export class PBR2Material extends PBRBaseMaterial { } if (scene.texturesEnabled) { defines.ALBEDODIRECTUV = 0; + defines.BASE_WEIGHTDIRECTUV = 0; + defines.BASE_DIFFUSE_ROUGHNESSDIRECTUV = 0; defines.AMBIENTDIRECTUV = 0; defines.OPACITYDIRECTUV = 0; defines.EMISSIVEDIRECTUV = 0; @@ -1863,9 +3046,18 @@ export class PBR2Material extends PBRBaseMaterial { // Misc. if (defines._areMiscDirty) { - PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, this.needAlphaTestingForMesh(mesh), defines, false); - defines.UNLIT = this._unlit2 || ((this.pointsCloud || this.wireframe) && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)); - defines.DEBUGMODE = this._debugMode2; + PrepareDefinesForMisc( + mesh, + scene, + this._useLogarithmicDepth, + this.pointsCloud, + this.fogEnabled, + this.needAlphaTestingForMesh(mesh), + defines, + this._applyDecalMapAfterDetailMap + ); + defines.UNLIT = this._unlit || ((this.pointsCloud || this.wireframe) && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)); + defines.DEBUGMODE = this._debugMode; } // Values that need to be evaluated on every frame @@ -1894,17 +3086,6 @@ export class PBR2Material extends PBRBaseMaterial { return this.getScene().environmentTexture; } - - private _shadersLoaded2 = false; - - /** - * If set to true, no lighting calculations will be applied. - */ - private _unlit2 = false; - - private _debugMode2 = 0; - - private _breakShaderLoadedCheck2 = false; } RegisterClass("BABYLON.PBR2Material", PBR2Material); diff --git a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts index f9539a22508..4bd4ff4ec10 100644 --- a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts @@ -1910,7 +1910,7 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { ubo.addUniform("reflectanceMatrix", 16); ubo.addUniform("cameraInfo", 4); - PrepareUniformLayoutForIBL(ubo, true, true, true); + PrepareUniformLayoutForIBL(ubo, true, true, true, true, true); super.buildUniformLayout(); } @@ -2057,7 +2057,7 @@ export abstract class PBRBaseMaterial extends PBRBaseMaterialBase { } } - BindIBLParameters(scene, defines, ubo, reflectionTexture, this.realTimeFiltering, this._reflectionColor); + BindIBLParameters(scene, defines, ubo, reflectionTexture, this.realTimeFiltering, true, true, true, true, true, this._reflectionColor); // Point size if (this.pointsCloud) { diff --git a/packages/dev/core/src/Materials/materialHelper.functions.ts b/packages/dev/core/src/Materials/materialHelper.functions.ts index 68b5b7dac56..d01e6f73c41 100644 --- a/packages/dev/core/src/Materials/materialHelper.functions.ts +++ b/packages/dev/core/src/Materials/materialHelper.functions.ts @@ -276,6 +276,11 @@ export function BindSceneUniformBuffer(effect: Effect, sceneUbo: UniformBuffer): * @param ubo The uniform buffer to update * @param reflectionTexture The IBL texture * @param realTimeFiltering Whether realtime filtering of IBL texture is being used + * @param supportTextureInfo Whether the texture info is supported + * @param supportLocalProjection Whether local projection is supported + * @param usePBR Whether PBR is being used + * @param supportSH Whether spherical harmonics are supported + * @param useColor Whether to use the reflection color * @param reflectionColor The color to use for the reflection */ export function BindIBLParameters( @@ -284,6 +289,11 @@ export function BindIBLParameters( ubo: UniformBuffer, reflectionTexture: Nullable = null, realTimeFiltering: boolean = false, + supportTextureInfo: boolean = false, + supportLocalProjection: boolean = false, + usePBR: boolean = false, + supportSH: boolean = false, + useColor: boolean = false, reflectionColor: Color3 = Color3.White() ): void { if (scene.texturesEnabled) { @@ -291,7 +301,7 @@ export function BindIBLParameters( ubo.updateMatrix("reflectionMatrix", reflectionTexture.getReflectionTextureMatrix()); ubo.updateFloat2("vReflectionInfos", reflectionTexture.level * scene.iblIntensity, 0); - if ((reflectionTexture).boundingBoxSize) { + if (supportLocalProjection && (reflectionTexture).boundingBoxSize) { const cubeTexture = reflectionTexture; ubo.updateVector3("vReflectionPosition", cubeTexture.boundingBoxPosition); @@ -303,7 +313,7 @@ export function BindIBLParameters( ubo.updateFloat2("vReflectionFilteringInfo", width, Math.log2(width)); } - if (!defines.USEIRRADIANCEMAP) { + if (supportSH && !defines.USEIRRADIANCEMAP) { const polynomials = reflectionTexture.sphericalPolynomial; if (defines.USESPHERICALFROMREFLECTIONMAP && polynomials) { if (defines.SPHERICAL_HARMONICS) { @@ -329,17 +339,21 @@ export function BindIBLParameters( ubo.updateFloat3("vSphericalZX", polynomials.zx.x, polynomials.zx.y, polynomials.zx.z); } } - } else { + } else if (usePBR) { // If we're using an irradiance map with a dominant direction assigned, set it. if (defines.USEIRRADIANCEMAP && defines.USE_IRRADIANCE_DOMINANT_DIRECTION) { ubo.updateVector3("vReflectionDominantDirection", reflectionTexture.irradianceTexture!._dominantDirection!); } } - ubo.updateFloat3("vReflectionMicrosurfaceInfos", reflectionTexture.getSize().width, reflectionTexture.lodGenerationScale, reflectionTexture.lodGenerationOffset); + if (supportTextureInfo) { + ubo.updateFloat3("vReflectionMicrosurfaceInfos", reflectionTexture.getSize().width, reflectionTexture.lodGenerationScale, reflectionTexture.lodGenerationOffset); + } } } - ubo.updateColor3("vReflectionColor", reflectionColor); + if (useColor) { + ubo.updateColor3("vReflectionColor", reflectionColor); + } } /** @@ -1468,15 +1482,17 @@ export function PrepareUniformsAndSamplersList(uniformsListOrOptions: string[] | * @param ubo Add uniforms to UBO * @param supportTextureInfo Add uniforms for texture info if true * @param supportLocalProjection Add uniforms for local projection if true - * @param useAdvanced Add advanced uniforms for IBL if true + * @param usePBR Add uniforms for IBL if true * @param supportSH Add uniforms for spherical harmonics if true + * @param useColor Add uniforms for reflection color if true */ export function PrepareUniformLayoutForIBL( ubo: UniformBuffer, supportTextureInfo: boolean = false, supportLocalProjection: boolean = false, - useAdvanced: boolean = false, - supportSH: boolean = false + usePBR: boolean = false, + supportSH: boolean = false, + useColor: boolean = false ): void { ubo.addUniform("vReflectionInfos", 2); ubo.addUniform("reflectionMatrix", 16); @@ -1489,12 +1505,15 @@ export function PrepareUniformLayoutForIBL( ubo.addUniform("vReflectionSize", 3); } - if (useAdvanced) { + if (usePBR) { ubo.addUniform("vReflectionFilteringInfo", 2); - ubo.addUniform("vReflectionColor", 3); ubo.addUniform("vReflectionDominantDirection", 3); } + if (useColor) { + ubo.addUniform("vReflectionColor", 3); + } + if (supportSH) { ubo.addUniform("vSphericalL00", 3); ubo.addUniform("vSphericalL1_1", 3); diff --git a/packages/dev/core/src/Materials/standardMaterial.ts b/packages/dev/core/src/Materials/standardMaterial.ts index 6995bd88e66..48045debfa0 100644 --- a/packages/dev/core/src/Materials/standardMaterial.ts +++ b/packages/dev/core/src/Materials/standardMaterial.ts @@ -1467,7 +1467,7 @@ export class StandardMaterial extends StandardMaterialBase { ubo.updateFloat("alphaCutOff", this.alphaCutOff); } - BindIBLParameters(scene, defines, ubo, this._reflectionTexture); + BindIBLParameters(scene, defines, ubo, this._reflectionTexture, false, true, true); if (this._emissiveTexture && StandardMaterial.EmissiveTextureEnabled) { ubo.updateFloat2("vEmissiveInfos", this._emissiveTexture.coordinatesIndex, this._emissiveTexture.level); diff --git a/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx index 5842558c3ce..ccfbcae5566 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx @@ -67,8 +67,8 @@ uniform Material { vec3 vReflectionPosition; vec3 vReflectionSize; vec2 vReflectionFilteringInfo; - vec3 vReflectionColor; vec3 vReflectionDominantDirection; + vec3 vReflectionColor; vec3 vSphericalL00; vec3 vSphericalL1_1; diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx index f5aeed5f908..3f434da4696 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx @@ -42,8 +42,8 @@ uniform vReflectionMicrosurfaceInfos: vec3f; uniform vReflectionPosition: vec3f; uniform vReflectionSize: vec3f; uniform vReflectionFilteringInfo: vec2f; -uniform vReflectionColor: vec3f; uniform vReflectionDominantDirection: vec3f; +uniform vReflectionColor: vec3f; uniform vSphericalL00: vec3f; uniform vSphericalL1_1: vec3f; diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts index 2029a3aaf1f..0044eb966b6 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts @@ -81,7 +81,9 @@ export class EXT_materials_diffuse_roughness implements IGLTFLoaderExtension { const promises = new Array>(); - babylonMaterial.brdf.baseDiffuseModel = Constants.MATERIAL_DIFFUSE_MODEL_E_OREN_NAYAR; + if (babylonMaterial instanceof PBRMaterial) { + babylonMaterial.brdf.baseDiffuseModel = Constants.MATERIAL_DIFFUSE_MODEL_E_OREN_NAYAR; + } if (properties.diffuseRoughnessFactor != undefined) { babylonMaterial.baseDiffuseRoughness = properties.diffuseRoughnessFactor; diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts index 2a89f37a970..c425c295da5 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts @@ -1,6 +1,5 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -71,7 +70,7 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { } private async _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsAnisotropy, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts index 438c5e49dda..bc394cd1040 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts @@ -1,6 +1,5 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -73,7 +72,7 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts index 88185371315..5507ebfb1ab 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts @@ -1,7 +1,6 @@ /* eslint-disable github/no-then */ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -78,7 +77,7 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async private _loadTranslucentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDiffuseTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } 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 c4d12526646..1a99485b358 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 @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -74,7 +73,7 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadDispersionPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDispersion): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts index b7aefce1d72..ad70f99ba58 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts @@ -1,6 +1,5 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -78,7 +77,7 @@ export class KHR_materials_ior implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts index 1c9a62c37eb..11168af02da 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts @@ -1,6 +1,5 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -73,7 +72,7 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts index c4d3aba8b9e..4816792a5e3 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts @@ -1,6 +1,5 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -75,7 +74,7 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts index a11e95c6f56..5f91a41d555 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts @@ -1,6 +1,5 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -379,7 +378,7 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } const pbrMaterial = babylonMaterial; diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts index 513052f2896..349cbd67c10 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -82,7 +81,7 @@ export class KHR_materials_volume implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } From 0b4cc8abcf4cd2bdd7383d4fdc14d304b2c7f154 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Tue, 24 Jun 2025 15:23:51 -0700 Subject: [PATCH 09/23] Rename PBR2 to OpenPBR --- packages/dev/core/src/Materials/PBR/index.ts | 10 ++-- .../{pbr2Material.ts => openPbrMaterial.ts} | 57 +++++++++---------- .../{pbr2.fragment.fx => openpbr.fragment.fx} | 0 .../{pbr2.vertex.fx => openpbr.vertex.fx} | 1 + .../{pbr2.fragment.fx => openpbr.fragment.fx} | 0 .../{pbr2.vertex.fx => openpbr.vertex.fx} | 0 .../EXT_materials_diffuse_roughness.ts | 4 +- .../KHR_materials_emissive_strength.ts | 4 +- .../KHR_materials_pbrSpecularGlossiness.ts | 4 +- .../2.0/Extensions/KHR_materials_specular.ts | 4 +- .../2.0/Extensions/KHR_materials_unlit.ts | 4 +- .../glTF/2.0/Extensions/MSFT_minecraftMesh.ts | 4 +- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 4 +- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 10 ++-- 14 files changed, 53 insertions(+), 53 deletions(-) rename packages/dev/core/src/Materials/PBR/{pbr2Material.ts => openPbrMaterial.ts} (95%) rename packages/dev/core/src/Shaders/{pbr2.fragment.fx => openpbr.fragment.fx} (100%) rename packages/dev/core/src/Shaders/{pbr2.vertex.fx => openpbr.vertex.fx} (97%) rename packages/dev/core/src/ShadersWGSL/{pbr2.fragment.fx => openpbr.fragment.fx} (100%) rename packages/dev/core/src/ShadersWGSL/{pbr2.vertex.fx => openpbr.vertex.fx} (100%) diff --git a/packages/dev/core/src/Materials/PBR/index.ts b/packages/dev/core/src/Materials/PBR/index.ts index c97b2aa4adc..1137c63f604 100644 --- a/packages/dev/core/src/Materials/PBR/index.ts +++ b/packages/dev/core/src/Materials/PBR/index.ts @@ -5,7 +5,7 @@ export * from "./pbrBRDFConfiguration"; export * from "./pbrClearCoatConfiguration"; export * from "./pbrIridescenceConfiguration"; export * from "./pbrMaterial"; -export * from "./pbr2Material"; +export * from "./openPbrMaterial"; export * from "./pbrMetallicRoughnessMaterial"; export * from "./pbrSpecularGlossinessMaterial"; export * from "./pbrSheenConfiguration"; @@ -16,7 +16,7 @@ export * from "../../ShadersWGSL/pbr.vertex"; export * from "../../ShadersWGSL/pbr.fragment"; export * from "../../Shaders/pbr.vertex"; export * from "../../Shaders/pbr.fragment"; -export * from "../../ShadersWGSL/pbr2.vertex"; -export * from "../../ShadersWGSL/pbr2.fragment"; -export * from "../../Shaders/pbr2.vertex"; -export * from "../../Shaders/pbr2.fragment"; +export * from "../../ShadersWGSL/openpbr.vertex"; +export * from "../../ShadersWGSL/openpbr.fragment"; +export * from "../../Shaders/openpbr.vertex"; +export * from "../../Shaders/openpbr.fragment"; diff --git a/packages/dev/core/src/Materials/PBR/pbr2Material.ts b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts similarity index 95% rename from packages/dev/core/src/Materials/PBR/pbr2Material.ts rename to packages/dev/core/src/Materials/PBR/openPbrMaterial.ts index 1d08c1d3969..c0869b94d73 100644 --- a/packages/dev/core/src/Materials/PBR/pbr2Material.ts +++ b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts @@ -67,7 +67,7 @@ import type { IAnimatable } from "../../Animations/animatable.interface"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; /** - * Defines a property for the PBR2Material. + * Defines a property for the OpenPBRMaterial. */ class Property { /** @@ -110,12 +110,12 @@ class Sampler { ) {} } -class PBR2MaterialDefinesBase extends UVDefinesMixin(MaterialDefines) {} +class OpenPBRMaterialDefinesBase extends UVDefinesMixin(MaterialDefines) {} /** * Manages the defines for the PBR Material. * @internal */ -export class PBR2MaterialDefines extends ImageProcessingDefinesMixin(PBR2MaterialDefinesBase) { +export class OpenPBRMaterialDefines extends ImageProcessingDefinesMixin(OpenPBRMaterialDefinesBase) { public PBR = true; public NUM_SAMPLES = "0"; @@ -330,8 +330,7 @@ export class PBR2MaterialDefines extends ImageProcessingDefinesMixin(PBR2Materia } } -class PBR2BaseMaterial extends ImageProcessingMixin(PushMaterial) {} -// class PBR2MaterialBase extends ImageProcessingMixin(PBRBaseMaterial) {} +class OpenPBRMaterialBase extends ImageProcessingMixin(PushMaterial) {} /** * The Physically based material of BJS. * @@ -339,24 +338,24 @@ class PBR2BaseMaterial extends ImageProcessingMixin(PushMaterial) {} * For more information, please refer to the documentation : * https://doc.babylonjs.com/features/featuresDeepDive/materials/using/introToPBR */ -export class PBR2Material extends PBR2BaseMaterial { +export class OpenPBRMaterial extends OpenPBRMaterialBase { /** - * PBR2MaterialTransparencyMode: No transparency mode, Alpha channel is not use. + * OpenPBRMaterialTransparencyMode: No transparency mode, Alpha channel is not use. */ public static readonly PBRMATERIAL_OPAQUE = PBRBaseMaterial.PBRMATERIAL_OPAQUE; /** - * PBR2MaterialTransparencyMode: Alpha Test mode, pixel are discarded below a certain threshold defined by the alpha cutoff value. + * OpenPBRMaterialTransparencyMode: Alpha Test mode, pixel are discarded below a certain threshold defined by the alpha cutoff value. */ public static readonly PBRMATERIAL_ALPHATEST = PBRBaseMaterial.PBRMATERIAL_ALPHATEST; /** - * PBR2MaterialTransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. + * OpenPBRMaterialTransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. */ public static readonly PBRMATERIAL_ALPHABLEND = PBRBaseMaterial.PBRMATERIAL_ALPHABLEND; /** - * PBR2MaterialTransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. + * OpenPBRMaterialTransparencyMode: Pixels are blended (according to the alpha mode) with the already drawn pixels in the current frame buffer. * They are also discarded below the alpha cutoff threshold to improve performances. */ public static readonly PBRMATERIAL_ALPHATESTANDBLEND = PBRBaseMaterial.PBRMATERIAL_ALPHATESTANDBLEND; @@ -470,7 +469,7 @@ export class PBR2Material extends PBR2BaseMaterial { */ @serialize() @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public ambientTextureImpactOnAnalyticalLights: number = PBR2Material.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; + public ambientTextureImpactOnAnalyticalLights: number = OpenPBRMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; /** * Stores the alpha values in a texture. Use luminance if texture.getAlphaFromRGB is true. @@ -1488,7 +1487,7 @@ export class PBR2Material extends PBR2BaseMaterial { protected _cacheHasRenderTargetTextures = false; /** - * Instantiates a new PBR2Material instance. + * Instantiates a new OpenPBRMaterial instance. * * @param name The material name * @param scene The scene the material will be use in. @@ -1540,7 +1539,7 @@ export class PBR2Material extends PBR2BaseMaterial { * @returns the name of the material class. */ public override getClassName(): string { - return "PBR2Material"; + return "OpenPBRMaterial"; } /** @@ -1604,8 +1603,8 @@ export class PBR2Material extends PBR2BaseMaterial { * @param rootUrl defines the root URL to use to load textures * @returns cloned material instance */ - public override clone(name: string, cloneTexturesOnlyOnce: boolean = true, rootUrl = ""): PBR2Material { - const clone = SerializationHelper.Clone(() => new PBR2Material(name, this.getScene()), this, { cloneTexturesOnlyOnce }); + public override clone(name: string, cloneTexturesOnlyOnce: boolean = true, rootUrl = ""): OpenPBRMaterial { + const clone = SerializationHelper.Clone(() => new OpenPBRMaterial(name, this.getScene()), this, { cloneTexturesOnlyOnce }); clone.id = name; clone.name = name; @@ -1623,7 +1622,7 @@ export class PBR2Material extends PBR2BaseMaterial { */ public override serialize(): any { const serializationObject = super.serialize(); - serializationObject.customType = "BABYLON.PBR2Material"; + serializationObject.customType = "BABYLON.OpenPBRMaterial"; return serializationObject; } @@ -1634,10 +1633,10 @@ export class PBR2Material extends PBR2BaseMaterial { * @param source - Serialized object. * @param scene - BJS scene instance. * @param rootUrl - url for the scene object - * @returns - PBR2Material + * @returns - OpenPBRMaterial */ - public static override Parse(source: any, scene: Scene, rootUrl: string): PBR2Material { - const material = SerializationHelper.Parse(() => new PBR2Material(source.name, scene), source, scene, rootUrl); + public static override Parse(source: any, scene: Scene, rootUrl: string): OpenPBRMaterial { + const material = SerializationHelper.Parse(() => new OpenPBRMaterial(source.name, scene), source, scene, rootUrl); if (source.stencil) { material.stencil.parse(source.stencil, scene, rootUrl); @@ -1670,7 +1669,7 @@ export class PBR2Material extends PBR2BaseMaterial { if (this._breakShaderLoadedCheck) { return; } - const defines = new PBR2MaterialDefines(this._eventInfo.defineNames); + const defines = new OpenPBRMaterialDefines(this._eventInfo.defineNames); const effect = this._prepareEffect(mesh, defines, undefined, undefined, localOptions.useInstances, localOptions.clipPlane, mesh.hasThinInstances)!; if (this._onEffectCreatedObservable) { onCreatedEffectParameters.effect = effect; @@ -1714,10 +1713,10 @@ export class PBR2Material extends PBR2BaseMaterial { if (!subMesh.materialDefines) { this._callbackPluginEventGeneric(MaterialPluginEvent.GetDefineNames, this._eventInfo); - subMesh.materialDefines = new PBR2MaterialDefines(this._eventInfo.defineNames); + subMesh.materialDefines = new OpenPBRMaterialDefines(this._eventInfo.defineNames); } - const defines = subMesh.materialDefines; + const defines = subMesh.materialDefines; if (this._isReadyForSubMesh(subMesh)) { return true; } @@ -1861,7 +1860,7 @@ export class PBR2Material extends PBR2BaseMaterial { if (!engine.getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) { mesh.createNormals(true); - Logger.Warn("PBR2Material: Normals have been created for the mesh: " + mesh.name); + Logger.Warn("OpenPBRMaterial: Normals have been created for the mesh: " + mesh.name); } const previousEffect = subMesh.effect; @@ -1967,7 +1966,7 @@ export class PBR2Material extends PBR2BaseMaterial { public override bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void { const scene = this.getScene(); - const defines = subMesh.materialDefines; + const defines = subMesh.materialDefines; if (!defines) { return; } @@ -2522,7 +2521,7 @@ export class PBR2Material extends PBR2BaseMaterial { private _prepareEffect( mesh: AbstractMesh, - defines: PBR2MaterialDefines, + defines: OpenPBRMaterialDefines, onCompiled: Nullable<(effect: Effect) => void> = null, onError: Nullable<(effect: Effect, errors: string) => void> = null, useInstances: Nullable = null, @@ -2790,9 +2789,9 @@ export class PBR2Material extends PBR2BaseMaterial { ? undefined : async () => { if (this.shaderLanguage === ShaderLanguage.WGSL) { - await Promise.all([import("../../ShadersWGSL/pbr2.vertex"), import("../../ShadersWGSL/pbr2.fragment")]); + await Promise.all([import("../../ShadersWGSL/openpbr.vertex"), import("../../ShadersWGSL/openpbr.fragment")]); } else { - await Promise.all([import("../../Shaders/pbr2.vertex"), import("../../Shaders/pbr2.fragment")]); + await Promise.all([import("../../Shaders/openpbr.vertex"), import("../../Shaders/openpbr.fragment")]); } this._shadersLoaded = true; @@ -2808,7 +2807,7 @@ export class PBR2Material extends PBR2BaseMaterial { private _prepareDefines( mesh: AbstractMesh, - defines: PBR2MaterialDefines, + defines: OpenPBRMaterialDefines, useInstances: Nullable = null, useClipPlane: Nullable = null, useThinInstances: boolean = false @@ -3088,4 +3087,4 @@ export class PBR2Material extends PBR2BaseMaterial { } } -RegisterClass("BABYLON.PBR2Material", PBR2Material); +RegisterClass("BABYLON.OpenPBRMaterial", OpenPBRMaterial); diff --git a/packages/dev/core/src/Shaders/pbr2.fragment.fx b/packages/dev/core/src/Shaders/openpbr.fragment.fx similarity index 100% rename from packages/dev/core/src/Shaders/pbr2.fragment.fx rename to packages/dev/core/src/Shaders/openpbr.fragment.fx diff --git a/packages/dev/core/src/Shaders/pbr2.vertex.fx b/packages/dev/core/src/Shaders/openpbr.vertex.fx similarity index 97% rename from packages/dev/core/src/Shaders/pbr2.vertex.fx rename to packages/dev/core/src/Shaders/openpbr.vertex.fx index 778fa33de08..c35a32bf701 100644 --- a/packages/dev/core/src/Shaders/pbr2.vertex.fx +++ b/packages/dev/core/src/Shaders/openpbr.vertex.fx @@ -95,6 +95,7 @@ varying vec3 vPositionW; varying vec4 vColor; #endif +// This is just including TBN, if needed. "Bump" isn't really a great name. #include #include #include diff --git a/packages/dev/core/src/ShadersWGSL/pbr2.fragment.fx b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx similarity index 100% rename from packages/dev/core/src/ShadersWGSL/pbr2.fragment.fx rename to packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx diff --git a/packages/dev/core/src/ShadersWGSL/pbr2.vertex.fx b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx similarity index 100% rename from packages/dev/core/src/ShadersWGSL/pbr2.vertex.fx rename to packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts index 0044eb966b6..6fad1d1968f 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -75,7 +75,7 @@ export class EXT_materials_diffuse_roughness implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadDiffuseRoughnessPropertiesAsync(context: string, properties: IEXTMaterialsDiffuseRoughness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts index 15b30b78e65..47785510fe7 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -71,7 +71,7 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { } private _loadEmissiveProperties(context: string, properties: IKHRMaterialsEmissiveStrength, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts index 54081698e17..d342c82d3ff 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import { Color3 } from "core/Maths/math.color"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -75,7 +75,7 @@ export class KHR_materials_pbrSpecularGlossiness implements IGLTFLoaderExtension // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSpecularGlossinessPropertiesAsync(context: string, properties: IKHRMaterialsPbrSpecularGlossiness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts index 25d7d3ccf8b..a55f058dca1 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -84,7 +84,7 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts index 15a0390af36..cae66552046 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import { Color3 } from "core/Maths/math.color"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -69,7 +69,7 @@ export class KHR_materials_unlit implements IGLTFLoaderExtension { // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadUnlitPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts index 82a6559ba80..f52207f3e74 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -48,7 +48,7 @@ export class MSFT_minecraftMesh implements IGLTFLoaderExtension { public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { if (extra) { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${extraContext}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index f45fc79ed69..aaff3b5b7ec 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -48,7 +48,7 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { if (extra) { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${extraContext}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index f3a2fd646bd..24a2f2a47dc 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -17,7 +17,7 @@ import { Bone } from "core/Bones/bone"; import { Skeleton } from "core/Bones/skeleton"; import { Material } from "core/Materials/material"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { PBR2Material } from "core/Materials/PBR/pbr2Material"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { ITextureCreationOptions } from "core/Materials/Textures/texture"; import { Texture } from "core/Materials/Textures/texture"; @@ -2128,7 +2128,7 @@ export class GLTFLoader implements IGLTFLoader { } private _loadMaterialMetallicRoughnessPropertiesAsync(context: string, properties: IMaterialPbrMetallicRoughness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } @@ -2230,7 +2230,7 @@ export class GLTFLoader implements IGLTFLoader { this._babylonScene._blockEntityCollection = !!this._assetContainer; let babylonMaterial; if (this.parent.usePBR2) { - babylonMaterial = new PBR2Material(name, this._babylonScene); + babylonMaterial = new OpenPBRMaterial(name, this._babylonScene); } else { babylonMaterial = new PBRMaterial(name, this._babylonScene); } @@ -2301,7 +2301,7 @@ export class GLTFLoader implements IGLTFLoader { * @returns A promise that resolves when the load is complete */ public loadMaterialBasePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } @@ -2366,7 +2366,7 @@ export class GLTFLoader implements IGLTFLoader { * @param babylonMaterial The Babylon material */ public loadMaterialAlphaProperties(context: string, material: IMaterial, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof PBR2Material)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } From f4b185660cf843c457b216c51188ee5fc1f74646 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Wed, 25 Jun 2025 13:37:06 -0700 Subject: [PATCH 10/23] Minor changes --- .../core/src/Materials/PBR/openPbrMaterial.ts | 6 ++-- .../core/src/Materials/PBR/pbrBaseMaterial.ts | 20 ++++++------- .../dev/core/src/Materials/imageProcessing.ts | 8 +++--- .../dev/core/src/Shaders/openpbr.vertex.fx | 28 ------------------- 4 files changed, 16 insertions(+), 46 deletions(-) diff --git a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts index c0869b94d73..3eec674b50a 100644 --- a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts @@ -5,7 +5,7 @@ import type { Nullable } from "../../types"; import { Scene } from "../../scene"; import { Color3, Color4, TmpColors } from "../../Maths/math.color"; import { ImageProcessingConfiguration } from "../imageProcessingConfiguration"; -import type { BaseTexture } from "../Textures/baseTexture"; +import type { BaseTexture } from "../../Materials/Textures/baseTexture"; import { PBRBaseMaterial } from "./pbrBaseMaterial"; import { RegisterClass } from "../../Misc/typeStore"; import { Material } from "../material"; @@ -166,7 +166,7 @@ export class OpenPBRMaterialDefines extends ImageProcessingDefinesMixin(OpenPBRM public MICROSURFACEMAP = false; public MICROSURFACEMAPDIRECTUV = 0; - public METALLICWORKFLOW = false; + public METALLICWORKFLOW = true; public ROUGHNESSSTOREINMETALMAPALPHA = false; public ROUGHNESSSTOREINMETALMAPGREEN = false; public METALLNESSSTOREINMETALMAPBLUE = false; @@ -2121,8 +2121,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { TmpColors.Color4[0].a = f0; ubo.updateDirectColor4("vReflectivityColor", TmpColors.Color4[0]); ubo.updateColor4("vMetallicReflectanceFactors", this._metallicReflectanceColor, this._metallicF0Factor); - } else { - ubo.updateColor4("vReflectivityColor", this._reflectivityColor, this._microSurface); } ubo.updateColor3("vEmissiveColor", MaterialFlags.EmissiveTextureEnabled ? this._emissiveColor : Color3.BlackReadOnly); diff --git a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts index 4bd4ff4ec10..711a8d62c65 100644 --- a/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts @@ -15,23 +15,23 @@ import { PBRBRDFConfiguration } from "./pbrBRDFConfiguration"; import { PrePassConfiguration } from "../prePassConfiguration"; import { Color3, TmpColors } from "../../Maths/math.color"; -import { ImageProcessingDefinesMixin } from "../imageProcessingConfiguration.defines"; -import { ImageProcessingConfiguration } from "../imageProcessingConfiguration"; -import type { Effect, IEffectCreationOptions } from "../effect"; -import type { IMaterialCompilationOptions, ICustomShaderNameResolveOptions } from "../material"; -import { Material } from "../material"; +import { ImageProcessingDefinesMixin } from "../../Materials/imageProcessingConfiguration.defines"; +import { ImageProcessingConfiguration } from "../../Materials/imageProcessingConfiguration"; +import type { Effect, IEffectCreationOptions } from "../../Materials/effect"; +import type { IMaterialCompilationOptions, ICustomShaderNameResolveOptions } from "../../Materials/material"; +import { Material } from "../../Materials/material"; import { MaterialPluginEvent } from "../materialPluginEvent"; -import { MaterialDefines } from "../materialDefines"; -import { PushMaterial } from "../pushMaterial"; +import { MaterialDefines } from "../../Materials/materialDefines"; +import { PushMaterial } from "../../Materials/pushMaterial"; -import type { BaseTexture } from "../Textures/baseTexture"; -import type { RenderTargetTexture } from "../Textures/renderTargetTexture"; +import type { BaseTexture } from "../../Materials/Textures/baseTexture"; +import type { RenderTargetTexture } from "../../Materials/Textures/renderTargetTexture"; import { MaterialFlags } from "../materialFlags"; import { Constants } from "../../Engines/constants"; import type { IAnimatable } from "../../Animations/animatable.interface"; -import "../Textures/baseTexture.polynomial"; +import "../../Materials/Textures/baseTexture.polynomial"; import { EffectFallbacks } from "../effectFallbacks"; import { PBRClearCoatConfiguration } from "./pbrClearCoatConfiguration"; diff --git a/packages/dev/core/src/Materials/imageProcessing.ts b/packages/dev/core/src/Materials/imageProcessing.ts index 7b9f29727f1..ab9d8f5da2d 100644 --- a/packages/dev/core/src/Materials/imageProcessing.ts +++ b/packages/dev/core/src/Materials/imageProcessing.ts @@ -3,12 +3,12 @@ import { serializeAsImageProcessingConfiguration } from "../Misc/decorators"; import type { Nullable } from "../types"; import type { ImageProcessingConfiguration } from "./imageProcessingConfiguration"; import type { Observer } from "../Misc/observable"; -import type { BaseTexture } from "./Textures/baseTexture"; -import type { ColorCurves } from "./colorCurves"; +import type { BaseTexture } from "../Materials/Textures/baseTexture"; +import type { ColorCurves } from "../Materials/colorCurves"; // Explicit re-export of types to help TypeScript resolve them in declaration files -export type { Observer } from "../Misc/observable"; -export type { ColorCurves } from "./colorCurves"; +// export type { Observer } from "../Misc/observable"; +// export type { ColorCurves } from "./colorCurves"; type Constructor = new (...args: any[]) => T; diff --git a/packages/dev/core/src/Shaders/openpbr.vertex.fx b/packages/dev/core/src/Shaders/openpbr.vertex.fx index c35a32bf701..46a3f34338c 100644 --- a/packages/dev/core/src/Shaders/openpbr.vertex.fx +++ b/packages/dev/core/src/Shaders/openpbr.vertex.fx @@ -48,34 +48,6 @@ attribute vec4 color; #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal) -#ifdef CLEARCOAT - #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat) - #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness) - #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump) - #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint) -#endif - -#ifdef IRIDESCENCE - #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence) - #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness) -#endif - -#ifdef SHEEN - #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen) - #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness) -#endif - -#ifdef ANISOTROPIC - #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy) -#endif - -#ifdef SUBSURFACE - #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness) - #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity) - #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity) - #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor) -#endif - // Output varying vec3 vPositionW; #if DEBUGMODE > 0 From f1564301932db23156184a55582c63145dcccae3 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Thu, 26 Jun 2025 13:22:36 -0700 Subject: [PATCH 11/23] Fixes for OpenPBRMaterial. --- .../core/src/Materials/PBR/openPbrMaterial.ts | 13 +- .../IBLShadows/iblShadowsPluginMaterial.ts | 45 +- .../IBLShadows/iblShadowsRenderPipeline.ts | 3 +- .../ShadersInclude/openPbrUboDeclaration.fx | 98 ++ .../ShadersInclude/pbrUboDeclaration.fx | 3 +- .../ShadersInclude/openPbrUboDeclaration.fx | 73 + .../ShadersInclude/pbrUboDeclaration.fx | 3 +- .../core/src/ShadersWGSL/openpbr.fragment.fx | 2 +- .../core/src/ShadersWGSL/openpbr.vertex.fx | 2 +- .../tabs/propertyGridTabComponent.tsx | 12 + .../pbrMaterialPropertyGridComponent.tsx | 1252 +++++++++-------- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 2 +- .../dev/loaders/src/glTF/glTFFileLoader.ts | 4 +- .../sandbox/src/tools/environmentTools.ts | 3 +- 14 files changed, 890 insertions(+), 625 deletions(-) create mode 100644 packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx create mode 100644 packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx diff --git a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts index 3eec674b50a..177005cc765 100644 --- a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts @@ -310,6 +310,17 @@ export class OpenPBRMaterialDefines extends ImageProcessingDefinesMixin(OpenPBRM public DEBUGMODE = 0; + // BRDF defines + BRDF_V_HEIGHT_CORRELATED = true; + MS_BRDF_ENERGY_CONSERVATION = true; + SPHERICAL_HARMONICS = true; + SPECULAR_GLOSSINESS_ENERGY_CONSERVATION = true; + MIX_IBL_RADIANCE_WITH_IRRADIANCE = true; + LEGACY_SPECULAR_ENERGY_CONSERVATION = false; + BASE_DIFFUSE_MODEL = Constants.MATERIAL_DIFFUSE_MODEL_E_OREN_NAYAR; + DIELECTRIC_SPECULAR_MODEL = Constants.MATERIAL_DIELECTRIC_SPECULAR_MODEL_OPENPBR; + CONDUCTOR_SPECULAR_MODEL = Constants.MATERIAL_CONDUCTOR_SPECULAR_MODEL_OPENPBR; + /** * Initializes the PBR Material defines. * @param externalProperties The external properties @@ -2646,7 +2657,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { PrepareAttributesForMorphTargets(attribs, mesh, defines); PrepareAttributesForBakedVertexAnimation(attribs, mesh, defines); - let shaderName = "pbr2"; + let shaderName = "openpbr"; const uniforms = [ "world", diff --git a/packages/dev/core/src/Rendering/IBLShadows/iblShadowsPluginMaterial.ts b/packages/dev/core/src/Rendering/IBLShadows/iblShadowsPluginMaterial.ts index 666d6a90324..409e699f3ae 100644 --- a/packages/dev/core/src/Rendering/IBLShadows/iblShadowsPluginMaterial.ts +++ b/packages/dev/core/src/Rendering/IBLShadows/iblShadowsPluginMaterial.ts @@ -10,6 +10,7 @@ import { expandToProperty, serialize } from "core/Misc/decorators"; import { RegisterClass } from "core/Misc/typeStore"; import { ShaderLanguage } from "core/Materials/shaderLanguage"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; /** * @internal */ @@ -72,7 +73,7 @@ export class IBLShadowsPluginMaterial extends MaterialPluginBase { return true; } - constructor(material: Material | StandardMaterial | PBRBaseMaterial) { + constructor(material: Material | StandardMaterial | PBRBaseMaterial | OpenPBRMaterial) { super(material, IBLShadowsPluginMaterial.Name, 310, new MaterialIBLShadowsRenderDefines()); this._internalMarkAllSubMeshesAsTexturesDirty = material._dirtyCallbacks[Constants.MATERIAL_TextureDirtyFlag]; } @@ -160,6 +161,27 @@ export class IBLShadowsPluginMaterial extends MaterialPluginBase { #endif #endif `; + } else if (this._material instanceof OpenPBRMaterial) { + // eslint-disable-next-line @typescript-eslint/naming-convention + frag["CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION"] = ` + #ifdef RENDER_WITH_IBL_SHADOWS + #ifndef UNLIT + #ifdef REFLECTION + #ifdef COLORED_IBL_SHADOWS + var shadowValue: vec3f = computeIndirectShadow(); + finalIrradiance *= shadowValue; + finalRadianceScaled *= mix(vec3f(1.0), shadowValue, roughness); + #else + var shadowValue: vec2f = computeIndirectShadow(); + finalIrradiance *= vec3f(shadowValue.x); + finalRadianceScaled *= vec3f(mix(pow(shadowValue.y, 4.0), shadowValue.x, roughness)); + #endif + #endif + #else + finalDiffuse *= computeIndirectShadow().x; + #endif + #endif + `; } else { frag["CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR"] = ` #ifdef RENDER_WITH_IBL_SHADOWS @@ -217,6 +239,27 @@ export class IBLShadowsPluginMaterial extends MaterialPluginBase { #endif #endif `; + } else if (this._material instanceof OpenPBRMaterial) { + // eslint-disable-next-line @typescript-eslint/naming-convention + frag["CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION"] = ` + #ifdef RENDER_WITH_IBL_SHADOWS + #ifndef UNLIT + #ifdef REFLECTION + #ifdef COLORED_IBL_SHADOWS + vec3 shadowValue = computeIndirectShadow(); + finalIrradiance.rgb *= shadowValue.rgb; + finalRadianceScaled *= mix(vec3(1.0), shadowValue.rgb, roughness); + #else + vec2 shadowValue = computeIndirectShadow(); + finalIrradiance *= shadowValue.x; + finalRadianceScaled *= mix(pow(shadowValue.y, 4.0), shadowValue.x, roughness); + #endif + #endif + #else + finalDiffuse *= computeIndirectShadow().x; + #endif + #endif + `; } else { frag["CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR"] = ` #ifdef RENDER_WITH_IBL_SHADOWS diff --git a/packages/dev/core/src/Rendering/IBLShadows/iblShadowsRenderPipeline.ts b/packages/dev/core/src/Rendering/IBLShadows/iblShadowsRenderPipeline.ts index 010593f29a0..6eeb74c406c 100644 --- a/packages/dev/core/src/Rendering/IBLShadows/iblShadowsRenderPipeline.ts +++ b/packages/dev/core/src/Rendering/IBLShadows/iblShadowsRenderPipeline.ts @@ -27,6 +27,7 @@ import type { Material } from "core/Materials/material"; import { Observable } from "core/Misc/observable"; import "../geometryBufferRendererSceneComponent"; import "../iblCdfGeneratorSceneComponent"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; interface IIblShadowsSettings { /** @@ -1115,7 +1116,7 @@ export class IblShadowsRenderPipeline extends PostProcessRenderPipeline { } protected _addShadowSupportToMaterial(material: Material) { - if (!(material instanceof PBRBaseMaterial) && !(material instanceof StandardMaterial)) { + if (!(material instanceof PBRBaseMaterial) && !(material instanceof StandardMaterial) && !(material instanceof OpenPBRMaterial)) { return; } let plugin = material.pluginManager?.getPlugin(IBLShadowsPluginMaterial.Name); diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx new file mode 100644 index 00000000000..cddb7c45b7a --- /dev/null +++ b/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx @@ -0,0 +1,98 @@ +layout(std140, column_major) uniform; + +// layout(set = 0, binding = 0) uniform Harmonics +// { +// uniform vec3 vSphericalL00; +// uniform vec3 vSphericalL1_1; +// uniform vec3 vSphericalL10; +// uniform vec3 vSphericalL11; +// uniform vec3 vSphericalL2_2; +// uniform vec3 vSphericalL2_1; +// uniform vec3 vSphericalL20; +// uniform vec3 vSphericalL21; +// uniform vec3 vSphericalL22; +// uniform vec3 vSphericalX; +// uniform vec3 vSphericalY; +// uniform vec3 vSphericalZ; +// uniform vec3 vSphericalXX_ZZ; +// uniform vec3 vSphericalYY_ZZ; +// uniform vec3 vSphericalZZ; +// uniform vec3 vSphericalXY; +// uniform vec3 vSphericalYZ; +// uniform vec3 vSphericalZX; +// } + +uniform Material { + vec2 vAlbedoInfos; + vec2 vBaseWeightInfos; + vec2 vBaseDiffuseRoughnessInfos; + vec4 vAmbientInfos; + vec2 vOpacityInfos; + vec2 vEmissiveInfos; + vec2 vLightmapInfos; + vec3 vReflectivityInfos; + vec2 vMicroSurfaceSamplerInfos; + vec3 vBumpInfos; + mat4 albedoMatrix; + mat4 baseWeightMatrix; + mat4 baseDiffuseRoughnessMatrix; + mat4 ambientMatrix; + mat4 opacityMatrix; + mat4 emissiveMatrix; + mat4 lightmapMatrix; + mat4 reflectivityMatrix; + mat4 microSurfaceSamplerMatrix; + mat4 bumpMatrix; + vec2 vTangentSpaceParams; + vec4 vAlbedoColor; + float baseWeight; + float baseDiffuseRoughness; + vec4 vLightingIntensity; + float pointSize; + vec4 vReflectivityColor; + vec3 vEmissiveColor; + vec3 vAmbientColor; + + vec2 vDebugMode; + + vec4 vMetallicReflectanceFactors; + vec2 vMetallicReflectanceInfos; + mat4 metallicReflectanceMatrix; + vec2 vReflectanceInfos; + mat4 reflectanceMatrix; + vec4 cameraInfo; + + vec2 vReflectionInfos; + mat4 reflectionMatrix; + vec3 vReflectionMicrosurfaceInfos; + vec3 vReflectionPosition; + vec3 vReflectionSize; + vec2 vReflectionFilteringInfo; + vec3 vReflectionDominantDirection; + vec3 vReflectionColor; + + vec3 vSphericalL00; + vec3 vSphericalL1_1; + vec3 vSphericalL10; + vec3 vSphericalL11; + vec3 vSphericalL2_2; + vec3 vSphericalL2_1; + vec3 vSphericalL20; + vec3 vSphericalL21; + vec3 vSphericalL22; + + vec3 vSphericalX; + vec3 vSphericalY; + vec3 vSphericalZ; + vec3 vSphericalXX_ZZ; + vec3 vSphericalYY_ZZ; + vec3 vSphericalZZ; + vec3 vSphericalXY; + vec3 vSphericalYZ; + vec3 vSphericalZX; + + #define ADDITIONAL_UBO_DECLARATION +}; + +#include +#include diff --git a/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx index ccfbcae5566..cddb7c45b7a 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/pbrUboDeclaration.fx @@ -60,6 +60,7 @@ uniform Material { mat4 metallicReflectanceMatrix; vec2 vReflectanceInfos; mat4 reflectanceMatrix; + vec4 cameraInfo; vec2 vReflectionInfos; mat4 reflectionMatrix; @@ -90,8 +91,6 @@ uniform Material { vec3 vSphericalYZ; vec3 vSphericalZX; - vec4 cameraInfo; - #define ADDITIONAL_UBO_DECLARATION }; diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx new file mode 100644 index 00000000000..6eacae512da --- /dev/null +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx @@ -0,0 +1,73 @@ +uniform vAlbedoInfos: vec2f; +uniform vBaseWeightInfos: vec2f; +uniform vBaseDiffuseRoughnessInfos: vec2f; +uniform vAmbientInfos: vec4f; +uniform vOpacityInfos: vec2f; +uniform vEmissiveInfos: vec2f; +uniform vLightmapInfos: vec2f; +uniform vReflectivityInfos: vec3f; +uniform vMicroSurfaceSamplerInfos: vec2f; +uniform vBumpInfos: vec3f; +uniform albedoMatrix: mat4x4f; +uniform baseWeightMatrix: mat4x4f; +uniform baseDiffuseRoughnessMatrix: mat4x4f; +uniform ambientMatrix: mat4x4f; +uniform opacityMatrix: mat4x4f; +uniform emissiveMatrix: mat4x4f; +uniform lightmapMatrix: mat4x4f; +uniform reflectivityMatrix: mat4x4f; +uniform microSurfaceSamplerMatrix: mat4x4f; +uniform bumpMatrix: mat4x4f; +uniform vTangentSpaceParams: vec2f; +uniform vAlbedoColor: vec4f; +uniform baseWeight: f32; +uniform baseDiffuseRoughness: f32; +uniform vLightingIntensity: vec4f; +uniform pointSize: f32; +uniform vReflectivityColor: vec4f; +uniform vEmissiveColor: vec3f; +uniform vAmbientColor: vec3f; + +uniform vDebugMode: vec2f; + +uniform vMetallicReflectanceFactors: vec4f; +uniform vMetallicReflectanceInfos: vec2f; +uniform metallicReflectanceMatrix: mat4x4f; +uniform vReflectanceInfos: vec2f; +uniform reflectanceMatrix: mat4x4f; +uniform cameraInfo: vec4f; + +uniform vReflectionInfos: vec2f; +uniform reflectionMatrix: mat4x4f; +uniform vReflectionMicrosurfaceInfos: vec3f; +uniform vReflectionPosition: vec3f; +uniform vReflectionSize: vec3f; +uniform vReflectionFilteringInfo: vec2f; +uniform vReflectionDominantDirection: vec3f; +uniform vReflectionColor: vec3f; + +uniform vSphericalL00: vec3f; +uniform vSphericalL1_1: vec3f; +uniform vSphericalL10: vec3f; +uniform vSphericalL11: vec3f; +uniform vSphericalL2_2: vec3f; +uniform vSphericalL2_1: vec3f; +uniform vSphericalL20: vec3f; +uniform vSphericalL21: vec3f; +uniform vSphericalL22: vec3f; + +uniform vSphericalX: vec3f; +uniform vSphericalY: vec3f; +uniform vSphericalZ: vec3f; +uniform vSphericalXX_ZZ: vec3f; +uniform vSphericalYY_ZZ: vec3f; +uniform vSphericalZZ: vec3f; +uniform vSphericalXY: vec3f; +uniform vSphericalYZ: vec3f; +uniform vSphericalZX: vec3f; + +#define ADDITIONAL_UBO_DECLARATION + + +#include +#include diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx index 3f434da4696..6eacae512da 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrUboDeclaration.fx @@ -35,6 +35,7 @@ uniform vMetallicReflectanceInfos: vec2f; uniform metallicReflectanceMatrix: mat4x4f; uniform vReflectanceInfos: vec2f; uniform reflectanceMatrix: mat4x4f; +uniform cameraInfo: vec4f; uniform vReflectionInfos: vec2f; uniform reflectionMatrix: mat4x4f; @@ -65,8 +66,6 @@ uniform vSphericalXY: vec3f; uniform vSphericalYZ: vec3f; uniform vSphericalZX: vec3f; -uniform cameraInfo: vec4f; - #define ADDITIONAL_UBO_DECLARATION diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx index 91bae999b44..83f4b634711 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx @@ -11,7 +11,7 @@ #endif // Declaration -#include +#include #include #include[0..maxSimultaneousLights] diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx index dd7d851f241..11eea0f2e3d 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx @@ -1,6 +1,6 @@ #define PBR_VERTEX_SHADER -#include +#include #define CUSTOM_VERTEX_BEGIN diff --git a/packages/dev/inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx b/packages/dev/inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx index d67eb582f9c..0d2dd7ca61a 100644 --- a/packages/dev/inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx +++ b/packages/dev/inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx @@ -117,6 +117,7 @@ import { Tags } from "core/Misc/tags"; import { LineContainerComponent } from "shared-ui-components/lines/lineContainerComponent"; import type { RectAreaLight } from "core/Lights/rectAreaLight"; import { FluentToolWrapper } from "shared-ui-components/fluent/hoc/fluentToolWrapper"; +import { OpenPBRMaterial } from "core/Materials"; export class PropertyGridTabComponent extends PaneComponent { private _timerIntervalId: number; @@ -396,6 +397,17 @@ export class PropertyGridTabComponent extends PaneComponent { onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> ); + } else if (className === "OpenPBRMaterial") { + const material = entity as OpenPBRMaterial; + return ( + + ); } if (className === "PBRMetallicRoughnessMaterial") { 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 32df71c593e..457913824eb 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 @@ -1,7 +1,7 @@ import * as React from "react"; import { Observable } from "core/Misc/observable"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import { Constants } from "core/Engines/constants"; import type { PropertyChangedEvent } from "../../../../propertyChangedEvent"; @@ -19,10 +19,11 @@ import { Vector2LineComponent } from "shared-ui-components/lines/vector2LineComp import "core/Materials/material.decalMap"; import "core/Rendering/prePassRendererSceneComponent"; import "core/Rendering/subSurfaceSceneComponent"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; interface IPBRMaterialPropertyGridComponentProps { globalState: GlobalState; - material: PBRMaterial; + material: PBRMaterial | OpenPBRMaterial; lockObject: LockObject; onSelectionChangedObservable?: Observable; onPropertyChangedObservable?: Observable; @@ -86,14 +87,16 @@ export class PBRMaterialPropertyGridComponent extends React.Component - + {material instanceof PBRMaterial && ( + + )} - (material.detailMap.texture = texture)} - onTextureRemoved={() => (material.detailMap.texture = null)} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} - /> - - - {material.decalMap && ( + {material instanceof PBRMaterial && ( + <> + (material.detailMap.texture = texture)} + onTextureRemoved={() => (material.detailMap.texture = null)} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} + /> + + + + )} + {material instanceof PBRMaterial && material.decalMap && ( - - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - {material.clearCoat.isEnabled && ( -
- - - + {material instanceof PBRMaterial && ( + <> + this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> - (material.clearCoat.texture = texture)} - onTextureRemoved={() => (material.clearCoat.texture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - (material.clearCoat.textureRoughness = texture)} - onTextureRemoved={() => (material.clearCoat.textureRoughness = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - (material.clearCoat.bumpTexture = texture)} - onTextureRemoved={() => (material.clearCoat.bumpTexture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - {material.clearCoat.bumpTexture && ( - + {material.clearCoat.isEnabled && ( +
+ + + + + (material.clearCoat.texture = texture)} + onTextureRemoved={() => (material.clearCoat.texture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + (material.clearCoat.textureRoughness = texture)} + onTextureRemoved={() => (material.clearCoat.textureRoughness = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + (material.clearCoat.bumpTexture = texture)} + onTextureRemoved={() => (material.clearCoat.bumpTexture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + {material.clearCoat.bumpTexture && ( + + )} + + + {material.clearCoat.isEnabled && material.clearCoat.isTintEnabled && ( + + )} + {material.clearCoat.isEnabled && material.clearCoat.isTintEnabled && ( + + )} + {material.clearCoat.isEnabled && material.clearCoat.isTintEnabled && ( + + )} + {material.clearCoat.isEnabled && material.clearCoat.isTintEnabled && ( + (material.clearCoat.tintTexture = texture)} + onTextureRemoved={() => (material.clearCoat.tintTexture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + )} +
)} +
+ - - {material.clearCoat.isEnabled && material.clearCoat.isTintEnabled && ( - - )} - {material.clearCoat.isEnabled && material.clearCoat.isTintEnabled && ( - - )} - {material.clearCoat.isEnabled && material.clearCoat.isTintEnabled && ( - - )} - {material.clearCoat.isEnabled && material.clearCoat.isTintEnabled && ( - (material.clearCoat.tintTexture = texture)} - onTextureRemoved={() => (material.clearCoat.tintTexture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - )} -
- )} -
- - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - {material.iridescence.isEnabled && ( -
- - - - this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> - (material.iridescence.texture = texture)} - onTextureRemoved={() => (material.iridescence.texture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - (material.iridescence.thicknessTexture = texture)} - onTextureRemoved={() => (material.iridescence.thicknessTexture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> -
- )} -
- - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - {material.anisotropy.isEnabled && ( -
+ {material.iridescence.isEnabled && ( +
+ + + + + (material.iridescence.texture = texture)} + onTextureRemoved={() => (material.iridescence.texture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + (material.iridescence.thicknessTexture = texture)} + onTextureRemoved={() => (material.iridescence.thicknessTexture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> +
+ )} + + this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> - - - (material.anisotropy.texture = texture)} - onTextureRemoved={() => (material.anisotropy.texture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> -
- )} -
- - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - {material.sheen.isEnabled && ( -
- - - - (material.sheen.texture = texture)} - onTextureRemoved={() => (material.sheen.texture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - (material.sheen.textureRoughness = texture)} - onTextureRemoved={() => (material.sheen.textureRoughness = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - - {(material.sheen as any)._useRoughness && ( - + {material.anisotropy.isEnabled && ( +
+ this.forceUpdate()} + onPropertyChangedObservable={this.props.onPropertyChangedObservable} + /> + + + (material.anisotropy.texture = texture)} + onTextureRemoved={() => (material.anisotropy.texture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> +
)} + + - this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> -
- )} -
- - (material.subSurface.thicknessTexture = texture)} - onTextureRemoved={() => (material.subSurface.thicknessTexture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - - - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - + {material.sheen.isEnabled && ( +
+ + + + (material.sheen.texture = texture)} + onTextureRemoved={() => (material.sheen.texture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + (material.sheen.textureRoughness = texture)} + onTextureRemoved={() => (material.sheen.textureRoughness = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + + {(material.sheen as any)._useRoughness && ( + + )} + + +
+ )} +
- this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - {(material.subSurface as any).isScatteringEnabled && material.getScene().prePassRenderer && material.getScene().subSurfaceConfiguration && ( -
- -
- )} - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - {material.subSurface.isRefractionEnabled && ( -
- + (material.subSurface.refractionIntensityTexture = texture)} - onTextureRemoved={() => (material.subSurface.refractionIntensityTexture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - (material.subSurface.refractionTexture = texture)} - onTextureRemoved={() => (material.subSurface.refractionTexture = null)} + label="Thickness" + texture={material.subSurface.thicknessTexture} + onTextureCreated={(texture) => (material.subSurface.thicknessTexture = texture)} + onTextureRemoved={() => (material.subSurface.thicknessTexture = null)} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} /> this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> -
- )} - - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - {material.subSurface.isDispersionEnabled && ( -
- this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> -
- )} - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - {material.subSurface.isTranslucencyEnabled && ( -
- - (material.subSurface.translucencyIntensityTexture = texture)} - onTextureRemoved={() => (material.subSurface.translucencyIntensityTexture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} - isLinear={true} /> + {(material.subSurface as any).isScatteringEnabled && material.getScene().prePassRenderer && material.getScene().subSurfaceConfiguration && ( +
+ +
+ )} this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> - + + (material.subSurface.refractionIntensityTexture = texture)} + onTextureRemoved={() => (material.subSurface.refractionIntensityTexture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + (material.subSurface.refractionTexture = texture)} + onTextureRemoved={() => (material.subSurface.refractionTexture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + + + + +
+ )} + + this.forceUpdate()} onPropertyChangedObservable={this.props.onPropertyChangedObservable} - isLinear={true} /> - (material.subSurface.translucencyColorTexture = texture)} - onTextureRemoved={() => (material.subSurface.translucencyColorTexture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + {material.subSurface.isDispersionEnabled && ( +
+ +
+ )} + this.forceUpdate()} + onPropertyChangedObservable={this.props.onPropertyChangedObservable} /> - - )} - + {material.subSurface.isTranslucencyEnabled && ( +
+ + (material.subSurface.translucencyIntensityTexture = texture)} + onTextureRemoved={() => (material.subSurface.translucencyIntensityTexture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + + + + (material.subSurface.translucencyColorTexture = texture)} + onTextureRemoved={() => (material.subSurface.translucencyColorTexture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> +
+ )} + + + )} )} - {material.clearCoat.texture && ( + {material instanceof PBRMaterial && material.clearCoat.texture && ( )} - {material.clearCoat.bumpTexture && ( + {material instanceof PBRMaterial && material.clearCoat.bumpTexture && ( )} - {material.clearCoat.tintTexture && false /* level is not used for the clear coat tint texture */ && ( + {material instanceof PBRMaterial && material.clearCoat.tintTexture && false /* level is not used for the clear coat tint texture */ && ( )} - {material.anisotropy.texture && ( + {material instanceof PBRMaterial && material.anisotropy.texture && ( )} - {material.sheen.texture && ( + {material instanceof PBRMaterial && material.sheen.texture && ( )} - {material.subSurface.thicknessTexture && ( + {material instanceof PBRMaterial && material.subSurface.thicknessTexture && ( )} - {material.subSurface.refractionTexture && ( + {material instanceof PBRMaterial && material.subSurface.refractionTexture && ( )} - {material.detailMap.isEnabled && ( + {material instanceof PBRMaterial && material.detailMap.isEnabled && ( <> - - - + {material instanceof PBRMaterial && ( + + )} + {material instanceof PBRMaterial && ( + + )} + {material instanceof PBRMaterial && ( + + )} - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> + {material instanceof PBRMaterial && ( + <> + this.forceUpdate()} + onPropertyChangedObservable={this.props.onPropertyChangedObservable} + /> + this.forceUpdate()} + onPropertyChangedObservable={this.props.onPropertyChangedObservable} + /> + + )} - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> - this.forceUpdate()} - onPropertyChangedObservable={this.props.onPropertyChangedObservable} - /> + {material instanceof PBRMaterial && ( + <> + this.forceUpdate()} + onPropertyChangedObservable={this.props.onPropertyChangedObservable} + /> + this.forceUpdate()} + onPropertyChangedObservable={this.props.onPropertyChangedObservable} + /> + + )} diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index 24a2f2a47dc..a772397e428 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -2229,7 +2229,7 @@ export class GLTFLoader implements IGLTFLoader { private _createDefaultMaterial(name: string, babylonDrawMode: number): Material { this._babylonScene._blockEntityCollection = !!this._assetContainer; let babylonMaterial; - if (this.parent.usePBR2) { + if (this.parent.useOpenPBR) { babylonMaterial = new OpenPBRMaterial(name, this._babylonScene); } else { babylonMaterial = new PBRMaterial(name, this._babylonScene); diff --git a/packages/dev/loaders/src/glTF/glTFFileLoader.ts b/packages/dev/loaders/src/glTF/glTFFileLoader.ts index 38f287c9d7b..2e0e712506b 100644 --- a/packages/dev/loaders/src/glTF/glTFFileLoader.ts +++ b/packages/dev/loaders/src/glTF/glTFFileLoader.ts @@ -206,7 +206,7 @@ abstract class GLTFLoaderOptions { this.compileShadowGenerators = options.compileShadowGenerators ?? this.compileShadowGenerators; this.transparencyAsCoverage = options.transparencyAsCoverage ?? this.transparencyAsCoverage; this.useRangeRequests = options.useRangeRequests ?? this.useRangeRequests; - this.usePBR2 = options.usePBR2 ?? this.usePBR2; + this.useOpenPBR = options.useOpenPBR ?? this.useOpenPBR; this.createInstances = options.createInstances ?? this.createInstances; this.alwaysComputeBoundingBox = options.alwaysComputeBoundingBox ?? this.alwaysComputeBoundingBox; this.loadAllMaterials = options.loadAllMaterials ?? this.loadAllMaterials; @@ -298,7 +298,7 @@ abstract class GLTFLoaderOptions { /** * Load the glTF files using the PBR2 material. */ - public usePBR2 = false; + public useOpenPBR = false; /** * Defines if the loader should create instances when multiple glTF nodes point to the same glTF mesh. Defaults to true. diff --git a/packages/tools/sandbox/src/tools/environmentTools.ts b/packages/tools/sandbox/src/tools/environmentTools.ts index e1bc486f171..ef2d57e0407 100644 --- a/packages/tools/sandbox/src/tools/environmentTools.ts +++ b/packages/tools/sandbox/src/tools/environmentTools.ts @@ -7,6 +7,7 @@ import type { StandardMaterial } from "core/Materials/standardMaterial"; import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import { Texture } from "core/Materials/Textures/texture"; import { EngineStore } from "core/Engines/engineStore"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; export class EnvironmentTools { public static SkyboxPath = ""; @@ -56,7 +57,7 @@ export class EnvironmentTools { currentScene.environmentTexture = this.LoadSkyboxPathTexture(currentScene); for (let i = 0; i < currentScene.materials.length; i++) { - const material = currentScene.materials[i] as StandardMaterial | PBRMaterial; + const material = currentScene.materials[i] as StandardMaterial | PBRMaterial | OpenPBRMaterial; if (material.name === "skyBox") { const reflectionTexture = material.reflectionTexture; if (reflectionTexture && reflectionTexture.coordinatesMode === Texture.SKYBOX_MODE) { From e908eee09ea0352ef2cd32b39c9bab2c58646d10 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Wed, 9 Jul 2025 18:32:30 -0700 Subject: [PATCH 12/23] Adding properties to OpenPBRMaterial --- .../core/src/Materials/PBR/openPbrMaterial.ts | 579 ++++++++++-------- packages/dev/core/src/Misc/decorators.ts | 30 + .../ShadersInclude/openPbrUboDeclaration.fx | 24 +- .../openpbrFragmentDeclaration.fx | 254 ++++++++ .../openpbrFragmentSamplersDeclaration.fx | 124 ++++ .../openpbrVertexDeclaration.fx | 206 +++++++ .../ShadersInclude/pbrBRDFFunctions.fx | 2 +- .../dev/core/src/Shaders/openpbr.fragment.fx | 26 +- .../dev/core/src/Shaders/openpbr.vertex.fx | 4 +- .../ShadersInclude/openPbrUboDeclaration.fx | 23 +- .../openpbrFragmentSamplersDeclaration.fx | 134 ++++ .../ShadersInclude/pbrBRDFFunctions.fx | 2 +- .../core/src/ShadersWGSL/openpbr.fragment.fx | 26 +- .../core/src/ShadersWGSL/openpbr.vertex.fx | 6 +- .../tabs/propertyGridTabComponent.tsx | 2 +- .../pbrMaterialPropertyGridComponent.tsx | 18 +- .../KHR_materials_pbrSpecularGlossiness.ts | 18 +- .../2.0/Extensions/KHR_materials_unlit.ts | 19 +- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 10 +- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 39 +- 20 files changed, 1200 insertions(+), 346 deletions(-) create mode 100644 packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx create mode 100644 packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx create mode 100644 packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx create mode 100644 packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx diff --git a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts index 177005cc765..534ba8992c4 100644 --- a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { serialize, serializeAsColor3, expandToProperty, serializeAsTexture } from "../../Misc/decorators"; +import { serialize, serializeAsColor3, expandToProperty, serializeAsTexture, addAccessorsForMaterialProperty } from "../../Misc/decorators"; import { GetEnvironmentBRDFTexture } from "../../Misc/brdfTextureTools"; import type { Nullable } from "../../types"; import { Scene } from "../../scene"; @@ -55,7 +55,7 @@ import { MaterialFlags } from "../materialFlags"; import type { SubMesh } from "../../Meshes/subMesh"; import { Logger } from "core/Misc/logger"; import { UVDefinesMixin } from "../uv.defines"; -import { Vector2, Vector3, Vector4 } from "core/Maths/math.vector"; +import { Vector2, Vector3, Vector4, TmpVectors } from "core/Maths/math.vector"; import type { Matrix } from "core/Maths/math.vector"; import type { Mesh } from "../../Meshes/mesh"; import { ImageProcessingMixin } from "../imageProcessing"; @@ -66,28 +66,79 @@ import type { IAnimatable } from "../../Animations/animatable.interface"; const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable }; +class Uniform { + public name: string; + public numComponents: number; + public linkedProperties: { [name: string]: Property } = {}; + public populateVectorFromLinkedProperties(vector: Vector4 | Vector3 | Vector2): void { + const destinationSize = vector instanceof Vector4 ? 4 : vector instanceof Vector3 ? 3 : vector instanceof Vector2 ? 2 : 1; + for (const propKey in this.linkedProperties) { + const prop = this.linkedProperties[propKey]; + const sourceSize = prop.numComponents; + if (destinationSize < sourceSize || prop.targetUniformComponentOffset > destinationSize - sourceSize) { + if (sourceSize == 1) { + Logger.Error(`Float property ${prop.name} has an offset that is too large.`); + } else { + Logger.Error(`Vector${sourceSize} property ${prop.name} won't fit in Vector${destinationSize} or has an offset that is too large.`); + } + return; + } + if (typeof prop.value === "number") { + Uniform._tmpArray[prop.targetUniformComponentOffset] = prop.value; + } else { + prop.value.toArray(Uniform._tmpArray, prop.targetUniformComponentOffset); + } + } + vector.fromArray(Uniform._tmpArray); + } + public constructor(name: string, componentNum: number) { + this.name = name; + this.numComponents = componentNum; + } + private static _tmpArray: number[] = [0, 0, 0, 0]; +} + /** * Defines a property for the OpenPBRMaterial. */ class Property { + public name: string; + public targetUniformName: string; + public defaultValue: T; + public value: T; + // public includeAlphaFromProp: string = ""; + + /** + * If not given a type, there will be no uniform defined for this property and + * it will be assumed that the value will be packed into the already existing "uniformName" uniform. + */ + public targetUniformComponentNum: number = 4; // Default to vec4 + public targetUniformComponentOffset: number = 0; + /** * Creates a new Property instance. * @param name The name of the property in the shader * @param defaultValue The default value of the property - * @param value The current value of the property, defaults to defaultValue - */ - constructor( - public name: string, - public defaultValue: T, - public value: T = defaultValue - ) {} + * @param targetUniformName The name of the property in the shader uniform block + * @param targetUniformComponentNum The number of components in the target uniform. All properties that are + * packed into the same uniform must agree on the size of the target uniform. + * @param targetUniformComponentOffset The offset in the uniform where this property will be packed. + */ + constructor(name: string, defaultValue: T, targetUniformName: string, targetUniformComponentNum: number, targetUniformComponentOffset: number = 0) { + this.name = name; + this.targetUniformName = targetUniformName; + this.defaultValue = defaultValue; + this.value = defaultValue; + this.targetUniformComponentNum = targetUniformComponentNum; + this.targetUniformComponentOffset = targetUniformComponentOffset; + } /** - * Returns the number of components of the property based on its type. + * Returns the number of components of the property based on its default value type. */ public get numComponents(): number { if (typeof this.defaultValue === "number") { - return 1; // Single float + return 1; } else if (this.defaultValue instanceof Color3) { return 3; } else if (this.defaultValue instanceof Color4) { @@ -104,10 +155,50 @@ class Property { } class Sampler { - constructor( - public name: string, // Name in the shader - public value: Nullable = null // Texture value, default to null - ) {} + public name: string; + public value: Nullable = null; // Texture value, default to null + public samplerPrefix: string = ""; // The name of the sampler in the shader + public textureDefine: string = ""; // The define used in the shader for this sampler + + /** + * The name of the sampler used in the shader. + * If this naming changes, we'll also need to change: + * - samplerFragmentDeclaration.fx + * - openpbr.fragment.fx + */ + public get samplerName(): string { + return this.samplerPrefix + "Sampler"; + } + /** + * The name of the sampler info used in the shader. + * If this naming changes, we'll also need to change: + * - openpbr.vertex.fx + * - openpbr.fragment.fx + */ + public get samplerInfoName(): string { + return this.samplerPrefix + "Infos"; + } + /** + * The name of the matrix used for this sampler in the shader. + * If this naming changes, we'll also need to change: + * - materialHelper.functions.BindTextureMatrix + * - samplerVertexImplementation.fx + * - openpbr.fragment.fx + */ + public get samplerMatrixName(): string { + return this.samplerPrefix + "Matrix"; + } + /** + * Creates a new Sampler instance. + * @param name The name of the texture property + * @param samplerPrefix The prefix used for the name of the sampler in the shader + * @param textureDefine The define used in the shader for this sampler + */ + constructor(name: string, samplerPrefix: string, textureDefine: string) { + this.name = name; + this.samplerPrefix = samplerPrefix; + this.textureDefine = textureDefine; + } } class OpenPBRMaterialDefinesBase extends UVDefinesMixin(MaterialDefines) {} @@ -128,7 +219,9 @@ export class OpenPBRMaterialDefines extends ImageProcessingDefinesMixin(OpenPBRM public VERTEXCOLOR = false; public BASE_WEIGHT = false; + public BASE_WEIGHTDIRECTUV = 0; public BASE_DIFFUSE_ROUGHNESS = false; + public BASE_DIFFUSE_ROUGHNESSDIRECTUV = 0; public BAKED_VERTEX_ANIMATION_TEXTURE = false; @@ -378,26 +471,78 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { public static DEFAULT_AO_ON_ANALYTICAL_LIGHTS = PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; /** - * Base Color uniform property. + * Base Weight is a multiplier on the diffuse and metal lobes. + * See OpenPBR's specs for base_weight */ - get baseColor(): Color3 { - return this._baseColor.value; - } - set baseColor(color: Color3) { - this._baseColor.value = color; - } - private _baseColor: Property = new Property("baseColor", Color3.White()); + public baseWeight: number; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "baseWeight") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _baseWeight: Property = new Property("base_weight", 1, "baseWeight", 1); + + /** + * Base Weight is a multiplier on the diffuse and metal lobes. + * See OpenPBR's specs for base_weight + */ + public baseWeightTexture: BaseTexture; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "baseColorTexture") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _baseWeightTexture: Sampler = new Sampler("base_weight", "baseWeight", "BASE_WEIGHT"); + + /** + * Color of the base diffuse lobe. + * See OpenPBR's specs for base_color + */ + public baseColor: Color3; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "baseColor") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _baseColor: Property = new Property("base_color", Color3.White(), "vBaseColor", 4); /** * Base Color Texture property. + * See OpenPBR's specs for base_color */ - get baseColorTexture(): Nullable { - return this._baseColorTexture.value; - } - set baseColorTexture(texture: Nullable) { - this._baseColorTexture.value = texture; - } - private _baseColorTexture: Sampler = new Sampler("baseColor"); + public baseColorTexture: BaseTexture; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "baseColorTexture") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _baseColorTexture: Sampler = new Sampler("base_color", "baseColor", "ALBEDO"); + + /** + * Roughness of the diffuse lobe. + * See OpenPBR's specs for base_diffuse_roughness + */ + public baseDiffuseRoughness: number; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "baseDiffuseRoughness") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _baseDiffuseRoughness: Property = new Property("base_diffuse_roughness", 0, "vBaseDiffuseRoughness", 1); + + /** + * Roughness of the diffuse lobe. + * See OpenPBR's specs for base_diffuse_roughness + */ + public baseDiffuseRoughnessTexture: BaseTexture; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "baseDiffuseRoughnessTexture") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _baseDiffuseRoughnessTexture: Sampler = new Sampler("base_diffuse_roughness", "baseDiffuseRoughness", "BASE_DIFFUSE_ROUGHNESS"); + + /** + * Defines the opacity of the material's geometry. See OpenPBR's specs for geometry_opacity + */ + public geometryOpacity: number; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "geometryOpacity") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _geometryOpacity: Property = new Property("geometry_opacity", 1.0, "vBaseColor", 4, 3); + + /** + * Defines the color of the material's emission. See OpenPBR's specs for emission_color + */ + public emissionColor: Color3; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "emissionColor") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _emissionColor: Property = new Property("emission_color", Color3.Black(), "vEmissiveColor", 3); + + private _propertyList: { [name: string]: Property }; + private _uniformsList: { [name: string]: Uniform } = {}; + private _samplersList: { [name: string]: Sampler } = {}; /** * Intensity of the direct lights e.g. the four lights available in your scene. @@ -423,14 +568,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public environmentIntensity: number = 1.0; - /** - * This is a special control allowing the reduction of the specular highlights coming from the - * four lights of the scene. Those highlights may not be needed in full environment lighting. - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public specularIntensity: number = 1.0; - /** * Debug Control allowing disabling the bump map on this material. */ @@ -438,27 +575,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public disableBumpMap: boolean = false; - /** - * AKA Diffuse Texture in standard nomenclature. - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public albedoTexture: Nullable; - - /** - * OpenPBR Base Weight texture (multiplier to the diffuse and metal lobes). - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public baseWeightTexture: Nullable; - - /** - * OpenPBR Base Diffuse Roughness texture (roughness of the diffuse lobe). - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public baseDiffuseRoughnessTexture: Nullable; - /** * AKA Occlusion Texture in other nomenclature. */ @@ -615,27 +731,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public ambientColor = new Color3(0, 0, 0); - /** - * AKA Diffuse Color in other nomenclature. - */ - @serializeAsColor3("albedo") - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public albedoColor = new Color3(1, 1, 1); - - /** - * OpenPBR Base Weight (multiplier to the diffuse and metal lobes). - */ - @serialize("baseWeight") - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public baseWeight = 1; - - /** - * OpenPBR Base Diffuse Roughness (roughness of the diffuse lobe). - */ - @serialize("baseDiffuseRoughness") - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public baseDiffuseRoughness: Nullable; - /** * AKA Specular Color in other nomenclature. */ @@ -650,13 +745,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public reflectionColor = new Color3(1.0, 1.0, 1.0); - /** - * The color emitted from the material. - */ - @serializeAsColor3("emissive") - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public emissiveColor = new Color3(0, 0, 0); - /** * AKA Glossiness in other nomenclature. */ @@ -1000,17 +1088,10 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { */ public _environmentIntensity: number = 1.0; - /** - * This is a special control allowing the reduction of the specular highlights coming from the - * four lights of the scene. Those highlights may not be needed in full environment lighting. - * @internal - */ - public _specularIntensity: number = 1.0; - /** * This stores the direct, emissive, environment, and specular light intensities into a Vector4. */ - private _lightingInfos: Vector4 = new Vector4(this._directIntensity, this._emissiveIntensity, this._environmentIntensity, this._specularIntensity); + private _lightingInfos: Vector4 = new Vector4(this._directIntensity, this._emissiveIntensity, this._environmentIntensity, 1.0); /** * Debug Control allowing disabling the bump map on this material. @@ -1018,24 +1099,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { */ public _disableBumpMap: boolean = false; - /** - * AKA Diffuse Texture in standard nomenclature. - * @internal - */ - public _albedoTexture: Nullable = null; - - /** - * Base Weight texture (multiplier to the diffuse and metal lobes). - * @internal - */ - public _baseWeightTexture: Nullable = null; - - /** - * Base Diffuse Roughness texture (roughness of the diffuse lobe). - * @internal - */ - public _baseDiffuseRoughnessTexture: Nullable = null; - /** * AKA Occlusion Texture in other nomenclature. * @internal @@ -1172,25 +1235,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { */ public _ambientColor = new Color3(0, 0, 0); - /** - * AKA Diffuse Color in other nomenclature. - * @internal - */ - public _albedoColor = new Color3(1, 1, 1); - - /** - * Base Weight (multiplier to the diffuse and metal lobes). - * @internal - */ - public _baseWeight = 1; - - /** - * Base Diffuse Roughness (roughness of the diffuse lobe). - * Can also be used to scale the corresponding texture. - * @internal - */ - public _baseDiffuseRoughness: Nullable = null; - /** * AKA Specular Color in other nomenclature. * @internal @@ -1203,12 +1247,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { */ public _reflectionColor = new Color3(1, 1, 1); - /** - * The color applied when light is emitted from a material. - * @internal - */ - public _emissiveColor = new Color3(0, 0, 0); - /** * AKA Glossiness in other nomenclature. * @internal @@ -1526,6 +1564,48 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { this._environmentBRDFTexture = GetEnvironmentBRDFTexture(this.getScene()); this.prePassConfiguration = new PrePassConfiguration(); this._environmentBRDFTexture = GetEnvironmentBRDFTexture(this.getScene()); + + // Build the internal property list that can be used to generate and update the uniform buffer + this._propertyList = {}; + for (const key of Object.getOwnPropertyNames(this)) { + const value = (this as any)[key]; + if (value instanceof Property) { + this._propertyList[key] = value; + } + } + // Build the internal uniforms list that is used for combining and updating + // property values in the uniform buffer + const propertyKeys = Object.keys(this._propertyList); + propertyKeys.forEach((key) => { + const prop = this._propertyList[key]; + let uniform = this._uniformsList[prop.targetUniformName]; + if (!uniform) { + uniform = new Uniform(prop.targetUniformName, prop.targetUniformComponentNum); + this._uniformsList[prop.targetUniformName] = uniform; + } else if (uniform.numComponents !== prop.targetUniformComponentNum) { + Logger.Error(`Uniform ${prop.targetUniformName} already exists of size ${uniform.numComponents}, but trying to set it to ${prop.targetUniformComponentNum}.`); + } + uniform.linkedProperties[prop.name] = prop; + }); + + // Build the internal list of samplers + this._samplersList = {}; + for (const key of Object.getOwnPropertyNames(this)) { + const value = (this as any)[key]; + if (value instanceof Sampler) { + this._samplersList[key] = value; + } + } + + // Arg. Why do I have to add these references to get rid of the linting errors? + this._baseWeight; + this._baseWeightTexture; + this._baseColor; + this._baseColorTexture; + this._baseDiffuseRoughness; + this._baseDiffuseRoughnessTexture; + this._geometryOpacity; + this._emissionColor; } /** @@ -1572,7 +1652,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { return false; } - return this.alpha < 1.0 || this._opacityTexture != null || this._shouldUseAlphaFromAlbedoTexture(); + return this.geometryOpacity < 1.0 || this._opacityTexture != null || this._shouldUseAlphaFromAlbedoTexture(); } /** @@ -1590,21 +1670,14 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { * @returns whether or not the alpha value of the albedo texture should be used for alpha blending. */ protected _shouldUseAlphaFromAlbedoTexture(): boolean { - return this._albedoTexture != null && this._albedoTexture.hasAlpha && this._useAlphaFromAlbedoTexture && this._transparencyMode !== PBRBaseMaterial.PBRMATERIAL_OPAQUE; + return this.baseColorTexture != null && this.baseColorTexture.hasAlpha && this._useAlphaFromAlbedoTexture && this._transparencyMode !== PBRBaseMaterial.PBRMATERIAL_OPAQUE; } /** * @returns whether or not there is a usable alpha channel for transparency. */ protected _hasAlphaChannel(): boolean { - return (this._albedoTexture != null && this._albedoTexture.hasAlpha) || this._opacityTexture != null; - } - - /** - * @returns the texture used for the alpha test. - */ - public override getAlphaTestTexture(): Nullable { - return this._albedoTexture; + return this._opacityTexture != null; } /** @@ -1740,21 +1813,13 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { this._callbackPluginEventHasRenderTargetTextures(this._eventInfo); this._cacheHasRenderTargetTextures = this._eventInfo.hasRenderTargetTextures; if (scene.texturesEnabled) { - if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { - if (!this._albedoTexture.isReadyOrNotBlocking()) { - return false; - } - } - - if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { - if (!this._baseWeightTexture.isReadyOrNotBlocking()) { - return false; - } - } - - if (this._baseDiffuseRoughnessTexture && MaterialFlags.BaseDiffuseRoughnessTextureEnabled) { - if (!this._baseDiffuseRoughnessTexture.isReadyOrNotBlocking()) { - return false; + // Loop through samplers, check MaterialFlag and whether the texture is ready or not. + for (const key in this._samplersList) { + const sampler = this._samplersList[key]; + if (sampler.value) { + if (!sampler.value.isReadyOrNotBlocking()) { + return false; + } } } @@ -1924,9 +1989,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { public override buildUniformLayout(): void { // Order is important ! const ubo = this._uniformBuffer; - ubo.addUniform("vAlbedoInfos", 2); - ubo.addUniform("vBaseWeightInfos", 2); - ubo.addUniform("vBaseDiffuseRoughnessInfos", 2); ubo.addUniform("vAmbientInfos", 4); ubo.addUniform("vOpacityInfos", 2); ubo.addUniform("vEmissiveInfos", 2); @@ -1934,9 +1996,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { ubo.addUniform("vReflectivityInfos", 3); ubo.addUniform("vMicroSurfaceSamplerInfos", 2); ubo.addUniform("vBumpInfos", 3); - ubo.addUniform("albedoMatrix", 16); - ubo.addUniform("baseWeightMatrix", 16); - ubo.addUniform("baseDiffuseRoughnessMatrix", 16); ubo.addUniform("ambientMatrix", 16); ubo.addUniform("opacityMatrix", 16); ubo.addUniform("emissiveMatrix", 16); @@ -1945,14 +2004,11 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { ubo.addUniform("microSurfaceSamplerMatrix", 16); ubo.addUniform("bumpMatrix", 16); ubo.addUniform("vTangentSpaceParams", 2); - ubo.addUniform("vAlbedoColor", 4); - ubo.addUniform("baseWeight", 1); - ubo.addUniform("baseDiffuseRoughness", 1); ubo.addUniform("vLightingIntensity", 4); ubo.addUniform("pointSize", 1); ubo.addUniform("vReflectivityColor", 4); - ubo.addUniform("vEmissiveColor", 3); + // ubo.addUniform("vEmissiveColor", 3); ubo.addUniform("vAmbientColor", 3); ubo.addUniform("vDebugMode", 2); @@ -1965,6 +2021,16 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { ubo.addUniform("cameraInfo", 4); PrepareUniformLayoutForIBL(ubo, true, true, true, true, true); + + Object.values(this._uniformsList).forEach((uniform) => { + ubo.addUniform(uniform.name, uniform.numComponents); + }); + + Object.values(this._samplersList).forEach((sampler) => { + ubo.addUniform(sampler.samplerInfoName, 2); + ubo.addUniform(sampler.samplerMatrixName, 16); + }); + super.buildUniformLayout(); } @@ -2033,19 +2099,13 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { if (!ubo.useUbo || !this.isFrozen || !ubo.isSync || subMesh._drawWrapper._forceRebindOnNextCall) { // Texture uniforms if (scene.texturesEnabled) { - if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { - ubo.updateFloat2("vAlbedoInfos", this._albedoTexture.coordinatesIndex, this._albedoTexture.level); - BindTextureMatrix(this._albedoTexture, ubo, "albedo"); - } - - if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { - ubo.updateFloat2("vBaseWeightInfos", this._baseWeightTexture.coordinatesIndex, this._baseWeightTexture.level); - BindTextureMatrix(this._baseWeightTexture, ubo, "baseWeight"); - } - - if (this._baseDiffuseRoughnessTexture && MaterialFlags.BaseDiffuseRoughnessTextureEnabled) { - ubo.updateFloat2("vBaseDiffuseRoughnessInfos", this._baseDiffuseRoughnessTexture.coordinatesIndex, this._baseDiffuseRoughnessTexture.level); - BindTextureMatrix(this._baseDiffuseRoughnessTexture, ubo, "baseDiffuseRoughness"); + // Loop through samplers and bind info and matrix for each texture. + for (const key in this._samplersList) { + const sampler = this._samplersList[key]; + if (sampler.value) { + ubo.updateFloat2(sampler.samplerInfoName, sampler.value.coordinatesIndex, sampler.value.level); + BindTextureMatrix(sampler.value, ubo, sampler.samplerPrefix); + } } if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { @@ -2134,18 +2194,29 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { ubo.updateColor4("vMetallicReflectanceFactors", this._metallicReflectanceColor, this._metallicF0Factor); } - ubo.updateColor3("vEmissiveColor", MaterialFlags.EmissiveTextureEnabled ? this._emissiveColor : Color3.BlackReadOnly); - - ubo.updateColor4("vAlbedoColor", this._albedoColor, this.alpha); - - ubo.updateFloat("baseWeight", this._baseWeight); - ubo.updateFloat("baseDiffuseRoughness", this._baseDiffuseRoughness || 0.0); + // ubo.updateColor3("vEmissiveColor", MaterialFlags.EmissiveTextureEnabled ? this._emissiveColor : Color3.BlackReadOnly); + + Object.values(this._uniformsList).forEach((uniform) => { + // If the property actually defines a uniform, update it. + if (uniform.numComponents === 4) { + uniform.populateVectorFromLinkedProperties(TmpVectors.Vector4[0]); + ubo.updateVector4(uniform.name, TmpVectors.Vector4[0]); + } else if (uniform.numComponents === 3) { + uniform.populateVectorFromLinkedProperties(TmpVectors.Vector3[0]); + ubo.updateVector3(uniform.name, TmpVectors.Vector3[0]); + } else if (uniform.numComponents === 2) { + uniform.populateVectorFromLinkedProperties(TmpVectors.Vector2[0]); + ubo.updateFloat2(uniform.name, TmpVectors.Vector2[0].x, TmpVectors.Vector2[0].y); + } else if (uniform.numComponents === 1) { + ubo.updateFloat(uniform.name, uniform.linkedProperties[Object.keys(uniform.linkedProperties)[0]].value); + } + }); // Misc this._lightingInfos.x = this._directIntensity; this._lightingInfos.y = this._emissiveIntensity; this._lightingInfos.z = this._environmentIntensity * scene.environmentIntensity; - this._lightingInfos.w = this._specularIntensity; + this._lightingInfos.w = 1.0; // This is used to be _specularIntensity. ubo.updateVector4("vLightingIntensity", this._lightingInfos); @@ -2159,16 +2230,12 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { // Textures if (scene.texturesEnabled) { - if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { - ubo.setTexture("albedoSampler", this._albedoTexture); - } - - if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { - ubo.setTexture("baseWeightSampler", this._baseWeightTexture); - } - - if (this._baseDiffuseRoughnessTexture && MaterialFlags.BaseDiffuseRoughnessTextureEnabled) { - ubo.setTexture("baseDiffuseRoughnessSampler", this._baseDiffuseRoughnessTexture); + // Loop through samplers and set textures + for (const key in this._samplersList) { + const sampler = this._samplersList[key]; + if (sampler.value) { + ubo.setTexture(sampler.samplerName, sampler.value); + } } if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { @@ -2277,16 +2344,12 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { public override getAnimatables(): IAnimatable[] { const results = super.getAnimatables(); - if (this._albedoTexture && this._albedoTexture.animations && this._albedoTexture.animations.length > 0) { - results.push(this._albedoTexture); - } - - if (this._baseWeightTexture && this._baseWeightTexture.animations && this._baseWeightTexture.animations.length > 0) { - results.push(this._baseWeightTexture); - } - - if (this._baseDiffuseRoughnessTexture && this._baseDiffuseRoughnessTexture.animations && this._baseDiffuseRoughnessTexture.animations.length > 0) { - results.push(this._baseDiffuseRoughnessTexture); + // Loop through samplers and push animated textures to list. + for (const key in this._samplersList) { + const sampler = this._samplersList[key]; + if (sampler.value && sampler.value.animations && sampler.value.animations.length > 0) { + results.push(sampler.value); + } } if (this._ambientTexture && this._ambientTexture.animations && this._ambientTexture.animations.length > 0) { @@ -2341,16 +2404,12 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { public override getActiveTextures(): BaseTexture[] { const activeTextures = super.getActiveTextures(); - if (this._albedoTexture) { - activeTextures.push(this._albedoTexture); - } - - if (this._baseWeightTexture) { - activeTextures.push(this._baseWeightTexture); - } - - if (this._baseDiffuseRoughnessTexture) { - activeTextures.push(this._baseDiffuseRoughnessTexture); + // Loop through samplers and push active textures + for (const key in this._samplersList) { + const sampler = this._samplersList[key]; + if (sampler.value) { + activeTextures.push(sampler.value); + } } if (this._ambientTexture) { @@ -2410,16 +2469,12 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { return true; } - if (this._albedoTexture === texture) { - return true; - } - - if (this._baseWeightTexture === texture) { - return true; - } - - if (this._baseDiffuseRoughnessTexture === texture) { - return true; + // Loop through samplers and check each texture for equality + for (const key in this._samplersList) { + const sampler = this._samplersList[key]; + if (sampler.value === texture) { + return true; + } } if (this._ambientTexture === texture) { @@ -2491,9 +2546,12 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { this._environmentBRDFTexture.dispose(); } - this._albedoTexture?.dispose(); - this._baseWeightTexture?.dispose(); - this._baseDiffuseRoughnessTexture?.dispose(); + // Loop through samplers and dispose the textures + for (const key in this._samplersList) { + const sampler = this._samplersList[key]; + sampler.value?.dispose(); + } + this._ambientTexture?.dispose(); this._opacityTexture?.dispose(); this._reflectionTexture?.dispose(); @@ -2666,19 +2724,13 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { "vEyePosition", "vLightsType", "vAmbientColor", - "vAlbedoColor", - "baseWeight", - "baseDiffuseRoughness", "vReflectivityColor", "vMetallicReflectanceFactors", - "vEmissiveColor", "visibility", "vFogInfos", "vFogColor", "pointSize", "vAlbedoInfos", - "vBaseWeightInfos", - "vBaseDiffuseRoughnessInfos", "vAmbientInfos", "vOpacityInfos", "vEmissiveInfos", @@ -2690,8 +2742,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { "vLightmapInfos", "mBones", "albedoMatrix", - "baseWeightMatrix", - "baseDiffuseRoughnessMatrix", "ambientMatrix", "opacityMatrix", "emissiveMatrix", @@ -2712,10 +2762,11 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { "cameraInfo", ]; + for (const uniformName in Object.keys(this._uniformsList)) { + uniforms.push(uniformName); + } + const samplers = [ - "albedoSampler", - "baseWeightSampler", - "baseDiffuseRoughnessSampler", "reflectivitySampler", "ambientSampler", "emissiveSampler", @@ -2734,6 +2785,11 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { "areaLightsLTC2Sampler", ]; + for (const key in this._samplersList) { + const sampler = this._samplersList[key]; + samplers.push(sampler.samplerName); + } + PrepareUniformsAndSamplersForIBL(uniforms, samplers, true); const uniformBuffers = ["Material", "Scene", "Mesh"]; @@ -2865,23 +2921,16 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { defines.LODBASEDMICROSFURACE = true; } - if (this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { - PrepareDefinesForMergedUV(this._albedoTexture, defines, "ALBEDO"); - defines.GAMMAALBEDO = this._albedoTexture.gammaSpace; - } else { - defines.ALBEDO = false; - } - - if (this._baseWeightTexture && MaterialFlags.BaseWeightTextureEnabled) { - PrepareDefinesForMergedUV(this._baseWeightTexture, defines, "BASE_WEIGHT"); - } else { - defines.BASE_WEIGHT = false; - } - - if (this._baseDiffuseRoughnessTexture && MaterialFlags.BaseDiffuseRoughnessTextureEnabled) { - PrepareDefinesForMergedUV(this._baseDiffuseRoughnessTexture, defines, "BASE_DIFFUSE_ROUGHNESS"); - } else { - defines.BASE_DIFFUSE_ROUGHNESS = false; + // TODO - loop through samplers and prepare defines for each texture + for (const key in this._samplersList) { + const sampler = this._samplersList[key]; + defines[sampler.textureDefine + "DIRECTUV"] = 0; + if (sampler.value) { + PrepareDefinesForMergedUV(sampler.value, defines, sampler.textureDefine); + defines["GAMMA" + sampler.textureDefine] = sampler.value.gammaSpace; + } else { + defines[sampler.textureDefine] = false; + } } if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { @@ -2975,7 +3024,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { if (engine.getCaps().standardDerivatives && this._bumpTexture && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { PrepareDefinesForMergedUV(this._bumpTexture, defines, "BUMP"); - if (this._useParallax && this._albedoTexture && MaterialFlags.DiffuseTextureEnabled) { + if (this._useParallax && this.baseColorTexture && MaterialFlags.DiffuseTextureEnabled) { defines.PARALLAX = true; defines.PARALLAX_RHS = scene.useRightHandedSystem; defines.PARALLAXOCCLUSION = !!this._useParallaxOcclusion; diff --git a/packages/dev/core/src/Misc/decorators.ts b/packages/dev/core/src/Misc/decorators.ts index 9e07eb69699..3abc2bb90cb 100644 --- a/packages/dev/core/src/Misc/decorators.ts +++ b/packages/dev/core/src/Misc/decorators.ts @@ -158,3 +158,33 @@ nativeOverride.filter = function boolean>(predica return (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<(...params: Parameters) => unknown>) => nativeOverride(target, propertyKey, descriptor, predicate); }; + +export function addAccessorsForMaterialProperty(setCallback: string, targetKey: Nullable = null) { + return (target: any, propertyKey: string) => { + const key = propertyKey; + const newKey = targetKey || ""; + Object.defineProperty(target, newKey, { + get: function (this: any) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return this[key].value; + }, + set: function (this: any, value) { + // does this object (i.e. vector3) has an equals function? use it! + // Note - not using "with epsilon" here, it is expected te behave like the internal cache does. + if (typeof this[key]?.value?.equals === "function") { + if (this[key].value.equals(value)) { + return; + } + } + if (this[key].value === value) { + return; + } + this[key].value = value; + + target[setCallback].apply(this); + }, + enumerable: true, + configurable: true, + }); + }; +} diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx index cddb7c45b7a..f3f6fd2f887 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx @@ -23,9 +23,6 @@ layout(std140, column_major) uniform; // } uniform Material { - vec2 vAlbedoInfos; - vec2 vBaseWeightInfos; - vec2 vBaseDiffuseRoughnessInfos; vec4 vAmbientInfos; vec2 vOpacityInfos; vec2 vEmissiveInfos; @@ -33,9 +30,7 @@ uniform Material { vec3 vReflectivityInfos; vec2 vMicroSurfaceSamplerInfos; vec3 vBumpInfos; - mat4 albedoMatrix; - mat4 baseWeightMatrix; - mat4 baseDiffuseRoughnessMatrix; + mat4 ambientMatrix; mat4 opacityMatrix; mat4 emissiveMatrix; @@ -44,13 +39,9 @@ uniform Material { mat4 microSurfaceSamplerMatrix; mat4 bumpMatrix; vec2 vTangentSpaceParams; - vec4 vAlbedoColor; - float baseWeight; - float baseDiffuseRoughness; vec4 vLightingIntensity; float pointSize; vec4 vReflectivityColor; - vec3 vEmissiveColor; vec3 vAmbientColor; vec2 vDebugMode; @@ -91,7 +82,18 @@ uniform Material { vec3 vSphericalYZ; vec3 vSphericalZX; - #define ADDITIONAL_UBO_DECLARATION + float baseWeight; + vec4 vBaseColor; + float baseDiffuseRoughness; + vec3 vEmissiveColor; + + vec2 baseWeightInfos; + mat4 baseWeightMatrix; + vec2 baseColorInfos; + mat4 baseColorMatrix; + vec2 baseDiffuseRoughnessInfos; + mat4 baseDiffuseRoughnessMatrix; +#define ADDITIONAL_UBO_DECLARATION }; #include diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx new file mode 100644 index 00000000000..84d657669e4 --- /dev/null +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx @@ -0,0 +1,254 @@ +uniform vec4 vEyePosition; + +uniform vec3 vReflectionColor; +uniform vec4 vBaseColor; +uniform float baseWeight; +uniform float baseDiffuseRoughness; + +// CUSTOM CONTROLS +uniform vec4 vLightingIntensity; + +uniform vec4 vReflectivityColor; +uniform vec4 vMetallicReflectanceFactors; +uniform vec3 vEmissiveColor; + +uniform float visibility; + +uniform vec3 vAmbientColor; + +// Samplers +#ifdef ALBEDO +uniform vec2 baseColorInfos; +#endif + +#ifdef BASE_WEIGHT +uniform vec2 baseWeightInfos; +#endif + +#ifdef BASE_DIFFUSE_ROUGHNESS +uniform vec2 baseDiffuseRoughnessInfos; +#endif + +#ifdef AMBIENT +uniform vec4 vAmbientInfos; +#endif + +#ifdef BUMP +uniform vec3 vBumpInfos; +uniform vec2 vTangentSpaceParams; +#endif + +#ifdef OPACITY +uniform vec2 vOpacityInfos; +#endif + +#ifdef EMISSIVE +uniform vec2 vEmissiveInfos; +#endif + +#ifdef LIGHTMAP +uniform vec2 vLightmapInfos; +#endif + +#ifdef REFLECTIVITY +uniform vec3 vReflectivityInfos; +#endif + +#ifdef MICROSURFACEMAP +uniform vec2 vMicroSurfaceSamplerInfos; +#endif + +// Refraction Reflection +#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(SS_REFRACTION) || defined(PREPASS) +uniform mat4 view; +#endif + +// Reflection +#ifdef REFLECTION + uniform vec2 vReflectionInfos; + + #ifdef REALTIME_FILTERING + uniform vec2 vReflectionFilteringInfo; + #endif + uniform mat4 reflectionMatrix; + uniform vec3 vReflectionMicrosurfaceInfos; + #if defined(USEIRRADIANCEMAP) && defined(USE_IRRADIANCE_DOMINANT_DIRECTION) + uniform vec3 vReflectionDominantDirection; + #endif + + #if defined(USE_LOCAL_REFLECTIONMAP_CUBIC) && defined(REFLECTIONMAP_CUBIC) + uniform vec3 vReflectionPosition; + uniform vec3 vReflectionSize; + #endif +#endif + +// Refraction +#if defined(SS_REFRACTION) && defined(SS_USE_LOCAL_REFRACTIONMAP_CUBIC) + uniform vec3 vRefractionPosition; + uniform vec3 vRefractionSize; +#endif + +// Clear Coat +#ifdef CLEARCOAT + uniform vec2 vClearCoatParams; + uniform vec4 vClearCoatRefractionParams; + + #if defined(CLEARCOAT_TEXTURE) || defined(CLEARCOAT_TEXTURE_ROUGHNESS) + uniform vec4 vClearCoatInfos; + #endif + + #ifdef CLEARCOAT_TEXTURE + uniform mat4 clearCoatMatrix; + #endif + + #ifdef CLEARCOAT_TEXTURE_ROUGHNESS + uniform mat4 clearCoatRoughnessMatrix; + #endif + + #ifdef CLEARCOAT_BUMP + uniform vec2 vClearCoatBumpInfos; + uniform vec2 vClearCoatTangentSpaceParams; + uniform mat4 clearCoatBumpMatrix; + #endif + + #ifdef CLEARCOAT_TINT + uniform vec4 vClearCoatTintParams; + uniform float clearCoatColorAtDistance; + + #ifdef CLEARCOAT_TINT_TEXTURE + uniform vec2 vClearCoatTintInfos; + uniform mat4 clearCoatTintMatrix; + #endif + #endif +#endif + +// Iridescence +#ifdef IRIDESCENCE + uniform vec4 vIridescenceParams; + + #if defined(IRIDESCENCE_TEXTURE) || defined(IRIDESCENCE_THICKNESS_TEXTURE) + uniform vec4 vIridescenceInfos; + #endif + + #ifdef IRIDESCENCE_TEXTURE + uniform mat4 iridescenceMatrix; + #endif + + #ifdef IRIDESCENCE_THICKNESS_TEXTURE + uniform mat4 iridescenceThicknessMatrix; + #endif +#endif + +// Anisotropy +#ifdef ANISOTROPIC + uniform vec3 vAnisotropy; + + #ifdef ANISOTROPIC_TEXTURE + uniform vec2 vAnisotropyInfos; + uniform mat4 anisotropyMatrix; + #endif +#endif + +// Sheen +#ifdef SHEEN + uniform vec4 vSheenColor; + #ifdef SHEEN_ROUGHNESS + uniform float vSheenRoughness; + #endif + + #if defined(SHEEN_TEXTURE) || defined(SHEEN_TEXTURE_ROUGHNESS) + uniform vec4 vSheenInfos; + #endif + + #ifdef SHEEN_TEXTURE + uniform mat4 sheenMatrix; + #endif + + #ifdef SHEEN_TEXTURE_ROUGHNESS + uniform mat4 sheenRoughnessMatrix; + #endif +#endif + +// SubSurface +#ifdef SUBSURFACE + #ifdef SS_REFRACTION + uniform vec4 vRefractionMicrosurfaceInfos; + uniform vec4 vRefractionInfos; + uniform mat4 refractionMatrix; + #ifdef REALTIME_FILTERING + uniform vec2 vRefractionFilteringInfo; + #endif + #ifdef SS_DISPERSION + uniform float dispersion; + #endif + #endif + + #ifdef SS_THICKNESSANDMASK_TEXTURE + uniform vec2 vThicknessInfos; + uniform mat4 thicknessMatrix; + #endif + + #ifdef SS_REFRACTIONINTENSITY_TEXTURE + uniform vec2 vRefractionIntensityInfos; + uniform mat4 refractionIntensityMatrix; + #endif + + #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE + uniform vec2 vTranslucencyIntensityInfos; + uniform mat4 translucencyIntensityMatrix; + #endif + + uniform vec2 vThicknessParam; + uniform vec3 vDiffusionDistance; + uniform vec4 vTintColor; + uniform vec3 vSubSurfaceIntensity; + + uniform vec4 vTranslucencyColor; + + #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE + uniform vec2 vTranslucencyColorInfos; + uniform mat4 translucencyColorMatrix; + #endif +#endif + +#ifdef PREPASS + #ifdef SS_SCATTERING + uniform float scatteringDiffusionProfile; + #endif +#endif + +#if DEBUGMODE > 0 + uniform vec2 vDebugMode; +#endif + +#ifdef DETAIL + uniform vec4 vDetailInfos; +#endif + +#include + +#ifdef USESPHERICALFROMREFLECTIONMAP + #ifdef SPHERICAL_HARMONICS + uniform vec3 vSphericalL00; + uniform vec3 vSphericalL1_1; + uniform vec3 vSphericalL10; + uniform vec3 vSphericalL11; + uniform vec3 vSphericalL2_2; + uniform vec3 vSphericalL2_1; + uniform vec3 vSphericalL20; + uniform vec3 vSphericalL21; + uniform vec3 vSphericalL22; + #else + uniform vec3 vSphericalX; + uniform vec3 vSphericalY; + uniform vec3 vSphericalZ; + uniform vec3 vSphericalXX_ZZ; + uniform vec3 vSphericalYY_ZZ; + uniform vec3 vSphericalZZ; + uniform vec3 vSphericalXY; + uniform vec3 vSphericalYZ; + uniform vec3 vSphericalZX; + #endif +#endif + +#define ADDITIONAL_FRAGMENT_DECLARATION diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx new file mode 100644 index 00000000000..7b767c79805 --- /dev/null +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx @@ -0,0 +1,124 @@ +#include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,BaseColor,_SAMPLERNAME_,baseColor) +#include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_SAMPLERNAME_,baseWeight) +#include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_SAMPLERNAME_,baseDiffuseRoughness) +#include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_SAMPLERNAME_,ambient) +#include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_SAMPLERNAME_,opacity) +#include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_SAMPLERNAME_,emissive) +#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_SAMPLERNAME_,lightmap) +#include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity,_SAMPLERNAME_,reflectivity) +#include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler,_SAMPLERNAME_,microSurface) +#include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance,_SAMPLERNAME_,metallicReflectance) +#include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance,_SAMPLERNAME_,reflectance) +#include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_SAMPLERNAME_,decal) + +#ifdef CLEARCOAT + #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat,_SAMPLERNAME_,clearCoat) + #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness) + #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) + uniform sampler2D clearCoatRoughnessSampler; + #endif + #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump,_SAMPLERNAME_,clearCoatBump) + #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint,_SAMPLERNAME_,clearCoatTint) +#endif + +#ifdef IRIDESCENCE + #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence,_SAMPLERNAME_,iridescence) + #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness,_SAMPLERNAME_,iridescenceThickness) +#endif + +#ifdef SHEEN + #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen,_SAMPLERNAME_,sheen) + #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness) + #if defined(SHEEN_ROUGHNESS) && defined(SHEEN_TEXTURE_ROUGHNESS) + uniform sampler2D sheenRoughnessSampler; + #endif +#endif + +#ifdef ANISOTROPIC + #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy,_SAMPLERNAME_,anisotropy) +#endif + +// Reflection +#ifdef REFLECTION + #ifdef REFLECTIONMAP_3D + #define sampleReflection(s, c) textureCube(s, c) + + uniform samplerCube reflectionSampler; + + #ifdef LODBASEDMICROSFURACE + #define sampleReflectionLod(s, c, l) textureCubeLodEXT(s, c, l) + #else + uniform samplerCube reflectionSamplerLow; + uniform samplerCube reflectionSamplerHigh; + #endif + + #ifdef USEIRRADIANCEMAP + uniform samplerCube irradianceSampler; + #endif + #else + #define sampleReflection(s, c) texture2D(s, c) + + uniform sampler2D reflectionSampler; + + #ifdef LODBASEDMICROSFURACE + #define sampleReflectionLod(s, c, l) texture2DLodEXT(s, c, l) + #else + uniform sampler2D reflectionSamplerLow; + uniform sampler2D reflectionSamplerHigh; + #endif + + #ifdef USEIRRADIANCEMAP + uniform sampler2D irradianceSampler; + #endif + #endif + + #ifdef REFLECTIONMAP_SKYBOX + varying vec3 vPositionUVW; + #else + #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED) + varying vec3 vDirectionW; + #endif + #endif +#endif + +#ifdef ENVIRONMENTBRDF + uniform sampler2D environmentBrdfSampler; +#endif + +// SUBSURFACE +#ifdef SUBSURFACE + #ifdef SS_REFRACTION + #ifdef SS_REFRACTIONMAP_3D + #define sampleRefraction(s, c) textureCube(s, c) + + uniform samplerCube refractionSampler; + + #ifdef LODBASEDMICROSFURACE + #define sampleRefractionLod(s, c, l) textureCubeLodEXT(s, c, l) + #else + uniform samplerCube refractionSamplerLow; + uniform samplerCube refractionSamplerHigh; + #endif + #else + #define sampleRefraction(s, c) texture2D(s, c) + + uniform sampler2D refractionSampler; + + #ifdef LODBASEDMICROSFURACE + #define sampleRefractionLod(s, c, l) texture2DLodEXT(s, c, l) + #else + uniform sampler2D refractionSamplerLow; + uniform sampler2D refractionSamplerHigh; + #endif + #endif + #endif + + #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness,_SAMPLERNAME_,thickness) + #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity,_SAMPLERNAME_,refractionIntensity) + #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity,_SAMPLERNAME_,translucencyIntensity) + #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor,_SAMPLERNAME_,translucencyColor) +#endif + +#ifdef IBL_CDF_FILTERING + uniform sampler2D icdfSampler; +#endif \ No newline at end of file diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx new file mode 100644 index 00000000000..b452496e757 --- /dev/null +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx @@ -0,0 +1,206 @@ +uniform mat4 view; +uniform mat4 viewProjection; +uniform vec4 vEyePosition; +#ifdef MULTIVIEW + mat4 viewProjectionR; +#endif + +#ifdef ALBEDO +uniform vec2 baseColorInfos; +uniform mat4 baseColorMatrix; +#endif + +#ifdef BASE_WEIGHT +uniform mat4 baseWeightMatrix; +uniform vec2 baseWeightInfos; +#endif + +uniform float baseDiffuseRoughness; +#ifdef BASE_DIFFUSE_ROUGHNESS +uniform mat4 baseDiffuseRoughnessMatrix; +uniform vec2 baseDiffuseRoughnessInfos; +#endif + +#ifdef AMBIENT +uniform mat4 ambientMatrix; +uniform vec4 vAmbientInfos; +#endif + +#ifdef OPACITY +uniform mat4 opacityMatrix; +uniform vec2 vOpacityInfos; +#endif + +#ifdef EMISSIVE +uniform vec2 vEmissiveInfos; +uniform mat4 emissiveMatrix; +#endif + +#ifdef LIGHTMAP +uniform vec2 vLightmapInfos; +uniform mat4 lightmapMatrix; +#endif + +#ifdef REFLECTIVITY +uniform vec3 vReflectivityInfos; +uniform mat4 reflectivityMatrix; +#endif + +#ifdef METALLIC_REFLECTANCE + uniform vec2 vMetallicReflectanceInfos; + uniform mat4 metallicReflectanceMatrix; +#endif +#ifdef REFLECTANCE + uniform vec2 vReflectanceInfos; + uniform mat4 reflectanceMatrix; +#endif + +#ifdef MICROSURFACEMAP +uniform vec2 vMicroSurfaceSamplerInfos; +uniform mat4 microSurfaceSamplerMatrix; +#endif + +#ifdef BUMP +uniform vec3 vBumpInfos; +uniform mat4 bumpMatrix; +#endif + +#ifdef POINTSIZE +uniform float pointSize; +#endif + +uniform vec4 cameraInfo; + +// Reflection +#ifdef REFLECTION + uniform vec2 vReflectionInfos; + uniform mat4 reflectionMatrix; +#endif + +// Clear Coat +#ifdef CLEARCOAT + #if defined(CLEARCOAT_TEXTURE) || defined(CLEARCOAT_TEXTURE_ROUGHNESS) + uniform vec4 vClearCoatInfos; + #endif + + #ifdef CLEARCOAT_TEXTURE + uniform mat4 clearCoatMatrix; + #endif + + #ifdef CLEARCOAT_TEXTURE_ROUGHNESS + uniform mat4 clearCoatRoughnessMatrix; + #endif + + #ifdef CLEARCOAT_BUMP + uniform vec2 vClearCoatBumpInfos; + uniform mat4 clearCoatBumpMatrix; + #endif + + #ifdef CLEARCOAT_TINT_TEXTURE + uniform vec2 vClearCoatTintInfos; + uniform mat4 clearCoatTintMatrix; + #endif +#endif + +// Iridescence +#ifdef IRIDESCENCE + #if defined(IRIDESCENCE_TEXTURE) || defined(IRIDESCENCE_THICKNESS_TEXTURE) + uniform vec4 vIridescenceInfos; + #endif + + #ifdef IRIDESCENCE_TEXTURE + uniform mat4 iridescenceMatrix; + #endif + + #ifdef IRIDESCENCE_THICKNESS_TEXTURE + uniform mat4 iridescenceThicknessMatrix; + #endif +#endif + +// Anisotropy +#ifdef ANISOTROPIC + #ifdef ANISOTROPIC_TEXTURE + uniform vec2 vAnisotropyInfos; + uniform mat4 anisotropyMatrix; + #endif +#endif + +// Sheen +#ifdef SHEEN + #if defined(SHEEN_TEXTURE) || defined(SHEEN_TEXTURE_ROUGHNESS) + uniform vec4 vSheenInfos; + #endif + + #ifdef SHEEN_TEXTURE + uniform mat4 sheenMatrix; + #endif + + #ifdef SHEEN_TEXTURE_ROUGHNESS + uniform mat4 sheenRoughnessMatrix; + #endif +#endif + +// Sub Surface +#ifdef SUBSURFACE + #ifdef SS_REFRACTION + uniform vec4 vRefractionInfos; + uniform mat4 refractionMatrix; + #endif + + #ifdef SS_THICKNESSANDMASK_TEXTURE + uniform vec2 vThicknessInfos; + uniform mat4 thicknessMatrix; + #endif + + #ifdef SS_REFRACTIONINTENSITY_TEXTURE + uniform vec2 vRefractionIntensityInfos; + uniform mat4 refractionIntensityMatrix; + #endif + + #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE + uniform vec2 vTranslucencyIntensityInfos; + uniform mat4 translucencyIntensityMatrix; + #endif + + #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE + uniform vec2 vTranslucencyColorInfos; + uniform mat4 translucencyColorMatrix; + #endif +#endif + +#ifdef NORMAL + #if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX) + #ifdef USESPHERICALFROMREFLECTIONMAP + #ifdef SPHERICAL_HARMONICS + uniform vec3 vSphericalL00; + uniform vec3 vSphericalL1_1; + uniform vec3 vSphericalL10; + uniform vec3 vSphericalL11; + uniform vec3 vSphericalL2_2; + uniform vec3 vSphericalL2_1; + uniform vec3 vSphericalL20; + uniform vec3 vSphericalL21; + uniform vec3 vSphericalL22; + #else + uniform vec3 vSphericalX; + uniform vec3 vSphericalY; + uniform vec3 vSphericalZ; + uniform vec3 vSphericalXX_ZZ; + uniform vec3 vSphericalYY_ZZ; + uniform vec3 vSphericalZZ; + uniform vec3 vSphericalXY; + uniform vec3 vSphericalYZ; + uniform vec3 vSphericalZX; + #endif + #endif + #endif +#endif + +#ifdef DETAIL +uniform vec4 vDetailInfos; +uniform mat4 detailMatrix; +#endif + +#include + +#define ADDITIONAL_VERTEX_DECLARATION diff --git a/packages/dev/core/src/Shaders/ShadersInclude/pbrBRDFFunctions.fx b/packages/dev/core/src/Shaders/ShadersInclude/pbrBRDFFunctions.fx index db6a8130573..a6a53279de4 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/pbrBRDFFunctions.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/pbrBRDFFunctions.fx @@ -9,7 +9,7 @@ #define CONDUCTOR_SPECULAR_MODEL_GLTF 0 #define CONDUCTOR_SPECULAR_MODEL_OPENPBR 1 -#ifndef PBR_VERTEX_SHADER +#if !defined(PBR_VERTEX_SHADER) && !defined(OPENPBR_VERTEX_SHADER) // ______________________________________________________________________ // diff --git a/packages/dev/core/src/Shaders/openpbr.fragment.fx b/packages/dev/core/src/Shaders/openpbr.fragment.fx index ac621aa07b2..8e901dee728 100644 --- a/packages/dev/core/src/Shaders/openpbr.fragment.fx +++ b/packages/dev/core/src/Shaders/openpbr.fragment.fx @@ -1,4 +1,4 @@ -#define PBR_FRAGMENT_SHADER +#define OPENPBR_FRAGMENT_SHADER #define CUSTOM_FRAGMENT_EXTENSION @@ -27,11 +27,11 @@ precision highp float; #endif // Declaration -#include<__decl__pbrFragment> +#include<__decl__openpbrFragment> #include #include<__decl__lightFragment>[0..maxSimultaneousLights] -#include +#include #include #include #include @@ -89,11 +89,11 @@ void main(void) { albedoOpacityOutParams albedoOpacityOut; #ifdef ALBEDO - vec4 albedoTexture = texture2D(albedoSampler, vAlbedoUV + uvOffset); + vec4 baseColorFromTexture = texture2D(baseColorSampler, vBaseColorUV + uvOffset); #endif #ifdef BASE_WEIGHT - vec4 baseWeightTexture = texture2D(baseWeightSampler, vBaseWeightUV + uvOffset); + vec4 baseWeightFromTexture = texture2D(baseWeightSampler, vBaseWeightUV + uvOffset); #endif #ifdef OPACITY @@ -105,15 +105,15 @@ void main(void) { #endif albedoOpacityOut = albedoOpacityBlock( - vAlbedoColor + vBaseColor #ifdef ALBEDO - , albedoTexture - , vAlbedoInfos + , baseColorFromTexture + , baseColorInfos #endif , baseWeight #ifdef BASE_WEIGHT - , baseWeightTexture - , vBaseWeightInfos + , baseWeightFromTexture + , baseWeightInfos #endif #ifdef OPACITY , opacityMap @@ -202,7 +202,7 @@ void main(void) { #endif #ifdef BASE_DIFFUSE_ROUGHNESS - float baseDiffuseRoughnessTexture = texture2D(baseDiffuseRoughnessSampler, vBaseDiffuseRoughnessUV + uvOffset).r; + float baseDiffuseRoughnessFromTexture = texture2D(baseDiffuseRoughnessSampler, vBaseDiffuseRoughnessUV + uvOffset).r; #endif reflectivityOut = reflectivityBlock( @@ -213,8 +213,8 @@ void main(void) { #endif , baseDiffuseRoughness #ifdef BASE_DIFFUSE_ROUGHNESS - , baseDiffuseRoughnessTexture - , vBaseDiffuseRoughnessInfos + , baseDiffuseRoughnessFromTexture + , baseDiffuseRoughnessInfos #endif #ifdef REFLECTIVITY , vReflectivityInfos diff --git a/packages/dev/core/src/Shaders/openpbr.vertex.fx b/packages/dev/core/src/Shaders/openpbr.vertex.fx index 46a3f34338c..3b4710c6c82 100644 --- a/packages/dev/core/src/Shaders/openpbr.vertex.fx +++ b/packages/dev/core/src/Shaders/openpbr.vertex.fx @@ -1,10 +1,10 @@ -#define PBR_VERTEX_SHADER +#define OPENPBR_VERTEX_SHADER #define CUSTOM_VERTEX_EXTENSION precision highp float; -#include<__decl__pbrVertex> +#include<__decl__openpbrVertex> #define CUSTOM_VERTEX_BEGIN diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx index 6eacae512da..6ae5c2455a1 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx @@ -1,6 +1,3 @@ -uniform vAlbedoInfos: vec2f; -uniform vBaseWeightInfos: vec2f; -uniform vBaseDiffuseRoughnessInfos: vec2f; uniform vAmbientInfos: vec4f; uniform vOpacityInfos: vec2f; uniform vEmissiveInfos: vec2f; @@ -8,9 +5,7 @@ uniform vLightmapInfos: vec2f; uniform vReflectivityInfos: vec3f; uniform vMicroSurfaceSamplerInfos: vec2f; uniform vBumpInfos: vec3f; -uniform albedoMatrix: mat4x4f; -uniform baseWeightMatrix: mat4x4f; -uniform baseDiffuseRoughnessMatrix: mat4x4f; + uniform ambientMatrix: mat4x4f; uniform opacityMatrix: mat4x4f; uniform emissiveMatrix: mat4x4f; @@ -19,13 +14,9 @@ uniform reflectivityMatrix: mat4x4f; uniform microSurfaceSamplerMatrix: mat4x4f; uniform bumpMatrix: mat4x4f; uniform vTangentSpaceParams: vec2f; -uniform vAlbedoColor: vec4f; -uniform baseWeight: f32; -uniform baseDiffuseRoughness: f32; uniform vLightingIntensity: vec4f; uniform pointSize: f32; uniform vReflectivityColor: vec4f; -uniform vEmissiveColor: vec3f; uniform vAmbientColor: vec3f; uniform vDebugMode: vec2f; @@ -66,6 +57,18 @@ uniform vSphericalXY: vec3f; uniform vSphericalYZ: vec3f; uniform vSphericalZX: vec3f; +uniform baseWeight: f32; +uniform vBaseColor: vec4f; +uniform baseDiffuseRoughness: f32; +uniform vEmissiveColor: vec3f; + +uniform baseWeightInfos: vec2f; +uniform baseWeightMatrix: mat4x4f; +uniform baseColorInfos: vec2f; +uniform baseColorMatrix: mat4x4f; +uniform baseDiffuseRoughnessInfos: vec2f; +uniform baseDiffuseRoughnessMatrix: mat4x4f; + #define ADDITIONAL_UBO_DECLARATION diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx new file mode 100644 index 00000000000..363fde264fe --- /dev/null +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx @@ -0,0 +1,134 @@ +#include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,BaseColor,_SAMPLERNAME_,baseColor) +#include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_SAMPLERNAME_,baseWeight) +#include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_SAMPLERNAME_,baseDiffuseRoughness) +#include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_SAMPLERNAME_,ambient) +#include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_SAMPLERNAME_,opacity) +#include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_SAMPLERNAME_,emissive) +#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_SAMPLERNAME_,lightmap) +#include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity,_SAMPLERNAME_,reflectivity) +#include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler,_SAMPLERNAME_,microSurface) +#include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance,_SAMPLERNAME_,metallicReflectance) +#include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance,_SAMPLERNAME_,reflectance) +#include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_SAMPLERNAME_,decal) + +#ifdef CLEARCOAT + #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat,_SAMPLERNAME_,clearCoat) + #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness) + #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) + var clearCoatRoughnessSamplerSampler: sampler; + var clearCoatRoughnessSampler: texture_2d; + #endif + #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump,_SAMPLERNAME_,clearCoatBump) + #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint,_SAMPLERNAME_,clearCoatTint) +#endif + +#ifdef IRIDESCENCE + #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence,_SAMPLERNAME_,iridescence) + #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness,_SAMPLERNAME_,iridescenceThickness) +#endif + +#ifdef SHEEN + #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen,_SAMPLERNAME_,sheen) + #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness) + #if defined(SHEEN_ROUGHNESS) && defined(SHEEN_TEXTURE_ROUGHNESS) + var sheenRoughnessSamplerSampler: sampler; + var sheenRoughnessSampler: texture_2d; + #endif +#endif + +#ifdef ANISOTROPIC + #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy,_SAMPLERNAME_,anisotropy) +#endif + +// Reflection +#ifdef REFLECTION + #ifdef REFLECTIONMAP_3D + var reflectionSamplerSampler: sampler; + var reflectionSampler: texture_cube; + + #ifdef LODBASEDMICROSFURACE + #else + var reflectionLowSamplerSampler: sampler; + var reflectionLowSampler: texture_cube; + var reflectionHighSamplerSampler: sampler; + var reflectionHighSampler: texture_cube; + #endif + + #ifdef USEIRRADIANCEMAP + var irradianceSamplerSampler: sampler; + var irradianceSampler: texture_cube; + #endif + #else + + var reflectionSamplerSampler: sampler; + var reflectionSampler: texture_2d; + + #ifdef LODBASEDMICROSFURACE + #else + var reflectionLowSamplerSampler: sampler; + var reflectionLowSampler: texture_2d; + var reflectionHighSamplerSampler: sampler; + var reflectionHighSampler: texture_2d; + #endif + + #ifdef USEIRRADIANCEMAP + var irradianceSamplerSampler: sampler; + var irradianceSampler: texture_2d; + #endif + #endif + + #ifdef REFLECTIONMAP_SKYBOX + varying vPositionUVW: vec3f; + #else + #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED) + varying vDirectionW: vec3f; + #endif + #endif +#endif + +#ifdef ENVIRONMENTBRDF + var environmentBrdfSamplerSampler: sampler; + var environmentBrdfSampler: texture_2d; +#endif + + +// SUBSURFACE +#ifdef SUBSURFACE + #ifdef SS_REFRACTION + #ifdef SS_REFRACTIONMAP_3D + + var refractionSamplerSampler: sampler; + var refractionSampler: texture_cube; + + #ifdef LODBASEDMICROSFURACE + #else + var refractionLowSamplerSampler: sampler; + var refractionLowSampler: texture_cube; + var refractionHighSamplerSampler: sampler; + var refractionHighSampler: texture_cube; + #endif + #else + + var refractionSamplerSampler: sampler; + var refractionSampler: texture_2d; + + #ifdef LODBASEDMICROSFURACE + #else + var refractionLowSamplerSampler: sampler; + var refractionLowSampler: texture_2d; + var refractionHighSamplerSampler: sampler; + var refractionHighSampler: texture_2d; + #endif + #endif + #endif + + #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness,_SAMPLERNAME_,thickness) + #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity,_SAMPLERNAME_,refractionIntensity) + #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity,_SAMPLERNAME_,translucencyIntensity) + #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor,_SAMPLERNAME_,translucencyColor) +#endif + +#ifdef IBL_CDF_FILTERING + var icdfSamplerSampler: sampler; + var icdfSampler: texture_2d; +#endif \ No newline at end of file diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrBRDFFunctions.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrBRDFFunctions.fx index 58f5fc763e1..e993e06e80e 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrBRDFFunctions.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/pbrBRDFFunctions.fx @@ -9,7 +9,7 @@ #define CONDUCTOR_SPECULAR_MODEL_GLTF 0 #define CONDUCTOR_SPECULAR_MODEL_OPENPBR 1 -#ifndef PBR_VERTEX_SHADER +#if !defined(PBR_VERTEX_SHADER) && !defined(OPENPBR_VERTEX_SHADER) // ______________________________________________________________________ // diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx index 83f4b634711..f7e3de2798a 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx @@ -1,4 +1,4 @@ -#define PBR_FRAGMENT_SHADER +#define OPENPBR_FRAGMENT_SHADER #define CUSTOM_FRAGMENT_BEGIN @@ -11,11 +11,11 @@ #endif // Declaration -#include +#include #include #include[0..maxSimultaneousLights] -#include +#include #include #include #include @@ -74,11 +74,11 @@ fn main(input: FragmentInputs) -> FragmentOutputs { var albedoOpacityOut: albedoOpacityOutParams; #ifdef ALBEDO - var albedoTexture: vec4f = textureSample(albedoSampler, albedoSamplerSampler, fragmentInputs.vAlbedoUV + uvOffset); + var baseColorFromTexture: vec4f = textureSample(baseColorSampler, baseColorSamplerSampler, fragmentInputs.vBaseColorUV + uvOffset); #endif #ifdef BASE_WEIGHT - var baseWeightTexture: vec4f = textureSample(baseWeightSampler, baseWeightSamplerSampler, fragmentInputs.vBaseWeightUV + uvOffset); + var baseWeightFromTexture: vec4f = textureSample(baseWeightSampler, baseWeightSamplerSampler, fragmentInputs.vBaseWeightUV + uvOffset); #endif #ifdef OPACITY @@ -90,15 +90,15 @@ fn main(input: FragmentInputs) -> FragmentOutputs { #endif albedoOpacityOut = albedoOpacityBlock( - uniforms.vAlbedoColor + uniforms.vBaseColor #ifdef ALBEDO - , albedoTexture - , uniforms.vAlbedoInfos + , baseColorFromTexture + , uniforms.baseColorInfos #endif , uniforms.baseWeight #ifdef BASE_WEIGHT - , baseWeightTexture - , uniforms.vBaseWeightInfos + , baseWeightFromTexture + , uniforms.baseWeightInfos #endif #ifdef OPACITY , opacityMap @@ -164,7 +164,7 @@ fn main(input: FragmentInputs) -> FragmentOutputs { #endif #ifdef BASE_DIFFUSE_ROUGHNESS - var baseDiffuseRoughnessTexture: f32 = textureSample(baseDiffuseRoughnessSampler, baseDiffuseRoughnessSamplerSampler, fragmentInputs.vBaseDiffuseRoughnessUV + uvOffset).x; + var baseDiffuseRoughnessFromTexture: f32 = textureSample(baseDiffuseRoughnessSampler, baseDiffuseRoughnessSamplerSampler, fragmentInputs.vBaseDiffuseRoughnessUV + uvOffset).x; #endif #ifdef METALLICWORKFLOW @@ -198,8 +198,8 @@ fn main(input: FragmentInputs) -> FragmentOutputs { #endif , uniforms.baseDiffuseRoughness #ifdef BASE_DIFFUSE_ROUGHNESS - , baseDiffuseRoughnessTexture - , uniforms.vBaseDiffuseRoughnessInfos + , baseDiffuseRoughnessFromTexture + , uniforms.baseDiffuseRoughnessInfos #endif #ifdef REFLECTIVITY , uniforms.vReflectivityInfos diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx index 11eea0f2e3d..493232d3fa5 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx @@ -1,6 +1,6 @@ -#define PBR_VERTEX_SHADER +#define OPENPBR_VERTEX_SHADER -#include +#include #define CUSTOM_VERTEX_BEGIN @@ -228,7 +228,7 @@ fn main(input : VertexInputs) -> FragmentInputs { #include[3..7] - #include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,Albedo,_MATRIXNAME_,albedo,_INFONAME_,AlbedoInfos.x) + #include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,BaseColor,_MATRIXNAME_,baseColor,_INFONAME_,baseColorInfos.x) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_MATRIXNAME_,baseWeight,_INFONAME_,BaseWeightInfos.x) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_MATRIXNAME_,baseDiffuseRoughness,_INFONAME_,BaseDiffuseRoughnessInfos.x) #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) diff --git a/packages/dev/inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx b/packages/dev/inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx index 0d2dd7ca61a..4e3e537d2f2 100644 --- a/packages/dev/inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx +++ b/packages/dev/inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx @@ -117,7 +117,7 @@ import { Tags } from "core/Misc/tags"; import { LineContainerComponent } from "shared-ui-components/lines/lineContainerComponent"; import type { RectAreaLight } from "core/Lights/rectAreaLight"; import { FluentToolWrapper } from "shared-ui-components/fluent/hoc/fluentToolWrapper"; -import { OpenPBRMaterial } from "core/Materials"; +import type { OpenPBRMaterial } from "core/Materials"; export class PropertyGridTabComponent extends PaneComponent { private _timerIntervalId: number; 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 457913824eb..7eb0ceafa45 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 @@ -47,14 +47,16 @@ export class PBRMaterialPropertyGridComponent extends React.Component - + {material instanceof PBRMaterial && ( + + )} { texture.name = `${babylonMaterial.name} (Diffuse)`; - babylonMaterial.albedoTexture = texture; + if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.baseColorTexture = texture; + } else { + babylonMaterial.albedoTexture = texture; + } }) ); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts index cae66552046..aa64856fe9e 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts @@ -79,17 +79,30 @@ export class KHR_materials_unlit implements IGLTFLoaderExtension { const properties = material.pbrMetallicRoughness; if (properties) { if (properties.baseColorFactor) { - babylonMaterial.albedoColor = Color3.FromArray(properties.baseColorFactor); + if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.baseColor = Color3.FromArray(properties.baseColorFactor); + } else { + babylonMaterial.albedoColor = Color3.FromArray(properties.baseColorFactor); + } + babylonMaterial.alpha = properties.baseColorFactor[3]; } else { - babylonMaterial.albedoColor = Color3.White(); + if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.baseColor = Color3.White(); + } else { + babylonMaterial.albedoColor = Color3.White(); + } } if (properties.baseColorTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Base Color)`; - babylonMaterial.albedoTexture = texture; + if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.baseColorTexture = texture; + } else { + babylonMaterial.albedoTexture = texture; + } }) ); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index aaff3b5b7ec..5e16205e167 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -55,8 +55,14 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { const promise = this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial); const useExactSrgbConversions = babylonMaterial.getScene().getEngine().useExactSrgbConversions; - if (!babylonMaterial.albedoTexture) { - babylonMaterial.albedoColor.toLinearSpaceToRef(babylonMaterial.albedoColor, useExactSrgbConversions); + if (babylonMaterial instanceof OpenPBRMaterial) { + if (!babylonMaterial.baseColorTexture) { + babylonMaterial.baseColor.toLinearSpaceToRef(babylonMaterial.baseColor, useExactSrgbConversions); + } + } else { + if (!babylonMaterial.albedoTexture) { + babylonMaterial.albedoColor.toLinearSpaceToRef(babylonMaterial.albedoColor, useExactSrgbConversions); + } } if (!babylonMaterial.reflectivityTexture) { diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index a772397e428..16e5f3a8509 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -2135,11 +2135,20 @@ export class GLTFLoader implements IGLTFLoader { const promises = new Array>(); if (properties) { - if (properties.baseColorFactor) { - babylonMaterial.albedoColor = Color3.FromArray(properties.baseColorFactor); - babylonMaterial.alpha = properties.baseColorFactor[3]; + if (babylonMaterial instanceof OpenPBRMaterial) { + if (properties.baseColorFactor) { + babylonMaterial.baseColor = Color3.FromArray(properties.baseColorFactor); + babylonMaterial.geometryOpacity = properties.baseColorFactor[3]; + } else { + babylonMaterial.baseColor = Color3.White(); + } } else { - babylonMaterial.albedoColor = Color3.White(); + if (properties.baseColorFactor) { + babylonMaterial.albedoColor = Color3.FromArray(properties.baseColorFactor); + babylonMaterial.alpha = properties.baseColorFactor[3]; + } else { + babylonMaterial.albedoColor = Color3.White(); + } } babylonMaterial.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; @@ -2149,7 +2158,11 @@ export class GLTFLoader implements IGLTFLoader { promises.push( this.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Base Color)`; - babylonMaterial.albedoTexture = texture; + if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.baseColorTexture = texture; + } else { + babylonMaterial.albedoTexture = texture; + } }) ); } @@ -2307,7 +2320,11 @@ export class GLTFLoader implements IGLTFLoader { const promises = new Array>(); - babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); + if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.emissionColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); + } else { + babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); + } if (material.doubleSided) { babylonMaterial.backFaceCulling = false; babylonMaterial.twoSidedLighting = true; @@ -2370,6 +2387,8 @@ export class GLTFLoader implements IGLTFLoader { throw new Error(`${context}: Material type not supported`); } + const baseColorTexture = babylonMaterial instanceof OpenPBRMaterial ? babylonMaterial.baseColorTexture : babylonMaterial.albedoTexture; + const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE; switch (alphaMode) { case MaterialAlphaMode.OPAQUE: { @@ -2380,15 +2399,15 @@ export class GLTFLoader implements IGLTFLoader { case MaterialAlphaMode.MASK: { babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHATEST; babylonMaterial.alphaCutOff = material.alphaCutoff == undefined ? 0.5 : material.alphaCutoff; - if (babylonMaterial.albedoTexture) { - babylonMaterial.albedoTexture.hasAlpha = true; + if (baseColorTexture) { + baseColorTexture.hasAlpha = true; } break; } case MaterialAlphaMode.BLEND: { babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHABLEND; - if (babylonMaterial.albedoTexture) { - babylonMaterial.albedoTexture.hasAlpha = true; + if (baseColorTexture) { + baseColorTexture.hasAlpha = true; babylonMaterial.useAlphaFromAlbedoTexture = true; } break; From 5bb9c22af37d2f47b2fa3d4b7bf35e262ced7918 Mon Sep 17 00:00:00 2001 From: sebavan Date: Thu, 10 Jul 2025 19:52:11 +0200 Subject: [PATCH 13/23] fix build --- packages/dev/buildTools/src/addJSToCompiledFiles.ts | 2 ++ packages/dev/buildTools/src/generateDeclaration.ts | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/dev/buildTools/src/addJSToCompiledFiles.ts b/packages/dev/buildTools/src/addJSToCompiledFiles.ts index 6e55dbb546a..686a7ef5383 100644 --- a/packages/dev/buildTools/src/addJSToCompiledFiles.ts +++ b/packages/dev/buildTools/src/addJSToCompiledFiles.ts @@ -8,6 +8,8 @@ function ProcessSource(sourceCode: string, forceMJS: boolean) { const extension = forceMJS ? ".mjs" : ".js"; return ( sourceCode + // replace imports from directories with index.js (mixins are generating them) + .replace(/import\("([./]+)"\)/g, `import("$1/index${extension}")`) // replace imports and exports with js extensions .replace(/((import|export).*["'](@babylonjs\/.*\/|\.{1,2}\/)((?!\.scss|\.svg|\.png|\.jpg).)*?)("|');/g, `$1${extension}$5;`) .replace(/((import|export)\(["']((@babylonjs\/.*\/|\.{1,2}\/)((?!\.scss|\.svg|\.png|\.jpg).)*?))(["'])\)/g, `$1${extension}$6)`) diff --git a/packages/dev/buildTools/src/generateDeclaration.ts b/packages/dev/buildTools/src/generateDeclaration.ts index 4d17d0a3849..162e73a9374 100644 --- a/packages/dev/buildTools/src/generateDeclaration.ts +++ b/packages/dev/buildTools/src/generateDeclaration.ts @@ -76,6 +76,9 @@ function GetModuleDeclaration( line = line.startsWith(" ") ? " //" + line.substring(3) : "// " + line; } + // replace type imports from directories with index (mixins are generating them) + line = line.replace(/import\("([./]+)"\)/g, `import("$1/index")`); + [ // Declaration /declare module ['"](.*)['"]/, @@ -85,7 +88,7 @@ function GetModuleDeclaration( / {4}module ['"](.*)['"]/, /^module ['"](\..*)['"]/, // Inlined Import - /import\(['"](.*)['"]/, + /import\(['"]([^'"]*)['"]/, // Side Effect Import /import ['"](.*)['"]/, ].forEach((regex) => { @@ -93,7 +96,9 @@ function GetModuleDeclaration( if (match) { if (match[1][0] === ".") { const newLocation = path.join(sourceDir, match[1]).replace(/\\/g, "/"); - line = line.replace(match[1], newLocation); + // replaceAll only avaialable by modifying the typescript lib + // which we prefered to not change for now + line = (line as any).replaceAll(match[1], newLocation); } else { let found = false; Object.keys(mapping).forEach((devPackageName) => { @@ -319,8 +324,8 @@ function GetPackageDeclaration( while (i < lines.length) { let line = lines[i]; - if (/import\("\.(.*)\)./g.test(line) && !/^declare type (.*) import/g.test(line)) { - line = line.replace(/import\((.*)\)./, ""); + if (/import\("\.([^)]*)\)./g.test(line) && !/^declare type (.*) import/g.test(line)) { + line = line.replace(/import\(([^)]*)\)./g, ""); } if (!line.includes("const enum") && !line.includes("=")) { From 00d18b18d6aea13545e1afb599fe3a070ee5dd0a Mon Sep 17 00:00:00 2001 From: Michael Bond Date: Thu, 10 Jul 2025 12:34:52 -0700 Subject: [PATCH 14/23] WIP glTFLoader dynamic material load --- .../Extensions/KHR_materials_anisotropy.ts | 24 ++++-- .../2.0/Extensions/KHR_materials_clearcoat.ts | 70 +++++++++++----- .../KHR_materials_diffuse_transmission.ts | 77 +++++++++++------- .../Extensions/KHR_materials_dispersion.ts | 40 ++++++--- .../KHR_materials_emissive_strength.ts | 17 +++- .../glTF/2.0/Extensions/KHR_materials_ior.ts | 29 +++++-- .../Extensions/KHR_materials_iridescence.ts | 54 +++++++++---- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 81 ++++++++++--------- 8 files changed, 265 insertions(+), 127 deletions(-) diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts index c425c295da5..a9d2cb7e2eb 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -21,6 +22,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_anisotropy) */ @@ -60,8 +63,15 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial)); @@ -70,23 +80,23 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { } private async _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsAnisotropy, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); - babylonMaterial.anisotropy.isEnabled = true; + (babylonMaterial as PBRMaterial).anisotropy.isEnabled = true; - babylonMaterial.anisotropy.intensity = properties.anisotropyStrength ?? 0; - babylonMaterial.anisotropy.angle = properties.anisotropyRotation ?? 0; + (babylonMaterial as PBRMaterial).anisotropy.intensity = properties.anisotropyStrength ?? 0; + (babylonMaterial as PBRMaterial).anisotropy.angle = properties.anisotropyRotation ?? 0; if (properties.anisotropyTexture) { (properties.anisotropyTexture as ITextureInfo).nonColorData = true; promises.push( this._loader.loadTextureInfoAsync(`${context}/anisotropyTexture`, properties.anisotropyTexture, (texture) => { texture.name = `${babylonMaterial.name} (Anisotropy Intensity)`; - babylonMaterial.anisotropy.texture = texture; + (babylonMaterial as PBRMaterial).anisotropy.texture = texture; }) ); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts index bc394cd1040..034c3b49f8b 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts @@ -1,6 +1,8 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; +import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +23,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md) * [Playground Sample](https://www.babylonjs-playground.com/frame.html#7F7PN6#8) @@ -61,46 +65,58 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } + if (!(babylonMaterial instanceof PBRMaterialClass)) { + throw new Error(`${context}: Material type not supported`); + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadClearCoatPropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadClearCoatPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); await Promise.all(promises); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); - - babylonMaterial.clearCoat.isEnabled = true; - babylonMaterial.clearCoat.useRoughnessFromMainTexture = false; - babylonMaterial.clearCoat.remapF0OnInterfaceChange = false; + let coatRoughness = 0; + let coatWeight = 0; + let coatWeightTexture: Nullable = null; + let coatRoughnessTexture: Nullable = null; + let coatNormalTexture: Nullable = null; + let coatNormalTextureScale = 1; if (properties.clearcoatFactor != undefined) { - babylonMaterial.clearCoat.intensity = properties.clearcoatFactor; + coatWeight = properties.clearcoatFactor; } else { - babylonMaterial.clearCoat.intensity = 0; + coatWeight = 0; } if (properties.clearcoatTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/clearcoatTexture`, properties.clearcoatTexture, (texture) => { texture.name = `${babylonMaterial.name} (ClearCoat)`; - babylonMaterial.clearCoat.texture = texture; + coatWeightTexture = texture; }) ); } if (properties.clearcoatRoughnessFactor != undefined) { - babylonMaterial.clearCoat.roughness = properties.clearcoatRoughnessFactor; + coatRoughness = properties.clearcoatRoughnessFactor; } else { - babylonMaterial.clearCoat.roughness = 0; + coatRoughness = 0; } if (properties.clearcoatRoughnessTexture) { @@ -108,7 +124,7 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/clearcoatRoughnessTexture`, properties.clearcoatRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (ClearCoat Roughness)`; - babylonMaterial.clearCoat.textureRoughness = texture; + coatRoughnessTexture = texture; }) ); } @@ -118,19 +134,37 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/clearcoatNormalTexture`, properties.clearcoatNormalTexture, (texture) => { texture.name = `${babylonMaterial.name} (ClearCoat Normal)`; - babylonMaterial.clearCoat.bumpTexture = texture; + coatNormalTexture = texture; }) ); babylonMaterial.invertNormalMapX = !babylonMaterial.getScene().useRightHandedSystem; babylonMaterial.invertNormalMapY = babylonMaterial.getScene().useRightHandedSystem; if (properties.clearcoatNormalTexture.scale != undefined) { - babylonMaterial.clearCoat.bumpTexture!.level = properties.clearcoatNormalTexture.scale; + coatNormalTextureScale = properties.clearcoatNormalTexture.scale; } } // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => {}); + return Promise.all(promises).then(() => { + if (useOpenPBR) { + // eslint-disable-next-line github/no-then + return; + } + const material = babylonMaterial as PBRMaterial; + material.clearCoat.isEnabled = true; + material.clearCoat.useRoughnessFromMainTexture = false; + material.clearCoat.remapF0OnInterfaceChange = false; + material.clearCoat.intensity = coatWeight; + material.clearCoat.texture = coatWeightTexture; + material.clearCoat.roughness = coatRoughness; + material.clearCoat.textureRoughness = coatRoughnessTexture; + + material.clearCoat.bumpTexture = coatNormalTexture; + if (coatNormalTexture) { + material.clearCoat.bumpTexture!.level = coatNormalTextureScale; + } + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts index 5507ebfb1ab..91930aef943 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts @@ -1,6 +1,7 @@ /* eslint-disable github/no-then */ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -23,6 +24,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825) * !!! Experimental Extension Subject to Changes !!! @@ -66,8 +69,15 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadTranslucentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); @@ -77,62 +87,71 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async private _loadTranslucentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDiffuseTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const pbrMaterial = babylonMaterial; - - // Enables "translucency" texture which represents diffusely-transmitted light. - pbrMaterial.subSurface.isTranslucencyEnabled = true; - - // Since this extension models thin-surface transmission only, we must make the - // internal IOR == 1.0 and set the thickness to 0. - pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; - pbrMaterial.subSurface.minimumThickness = 0.0; - pbrMaterial.subSurface.maximumThickness = 0.0; - - // Tint color will be used for transmission. - pbrMaterial.subSurface.useAlbedoToTintTranslucency = false; + let translucencyWeight = 0.0; + let translucencyWeightTexture: Nullable; + let translucencyColor = Color3.White(); + let translucencyColorTexture: Nullable; if (extension.diffuseTransmissionFactor !== undefined) { - pbrMaterial.subSurface.translucencyIntensity = extension.diffuseTransmissionFactor; - } else { - pbrMaterial.subSurface.translucencyIntensity = 0.0; - pbrMaterial.subSurface.isTranslucencyEnabled = false; - return Promise.resolve(); + translucencyWeight = extension.diffuseTransmissionFactor; } const promises = new Array>(); - pbrMaterial.subSurface.useGltfStyleTextures = true; - if (extension.diffuseTransmissionTexture) { (extension.diffuseTransmissionTexture as ITextureInfo).nonColorData = true; promises.push( this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionTexture`, extension.diffuseTransmissionTexture).then((texture: BaseTexture) => { texture.name = `${babylonMaterial.name} (Diffuse Transmission)`; - pbrMaterial.subSurface.translucencyIntensityTexture = texture; + translucencyWeightTexture = texture; }) ); } if (extension.diffuseTransmissionColorFactor !== undefined) { - pbrMaterial.subSurface.translucencyColor = Color3.FromArray(extension.diffuseTransmissionColorFactor); - } else { - pbrMaterial.subSurface.translucencyColor = Color3.White(); + translucencyColor = Color3.FromArray(extension.diffuseTransmissionColorFactor); } if (extension.diffuseTransmissionColorTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionColorTexture`, extension.diffuseTransmissionColorTexture).then((texture: BaseTexture) => { texture.name = `${babylonMaterial.name} (Diffuse Transmission Color)`; - pbrMaterial.subSurface.translucencyColorTexture = texture; + translucencyColorTexture = texture; }) ); } - return Promise.all(promises).then(() => {}); + return Promise.all(promises).then(() => { + const pbrMaterial = babylonMaterial as PBRMaterial; + + // Enables "translucency" texture which represents diffusely-transmitted light. + pbrMaterial.subSurface.isTranslucencyEnabled = true; + + // Since this extension models thin-surface transmission only, we must make the + // internal IOR == 1.0 and set the thickness to 0. + pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; + pbrMaterial.subSurface.minimumThickness = 0.0; + pbrMaterial.subSurface.maximumThickness = 0.0; + + // Tint color will be used for transmission. + pbrMaterial.subSurface.useAlbedoToTintTranslucency = false; + + pbrMaterial.subSurface.translucencyIntensity = translucencyWeight; + if (translucencyWeight === 0.0) { + pbrMaterial.subSurface.isTranslucencyEnabled = false; + return; + } + + pbrMaterial.subSurface.useGltfStyleTextures = true; + pbrMaterial.subSurface.translucencyIntensityTexture = translucencyWeightTexture; + + pbrMaterial.subSurface.translucencyColor = translucencyColor; + pbrMaterial.subSurface.translucencyColorTexture = translucencyColorTexture; + }); } } 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 1a99485b358..31bbbf7b404 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 @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +22,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/87bd64a7f5e23c84b6aef2e6082069583ed0ddb4/extensions/2.0/Khronos/KHR_materials_dispersion/README.md) * @experimental @@ -61,29 +64,44 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadDispersionPropertiesAsync(extensionContext, material, babylonMaterial, extension)); + promises.push(this._loadDispersionPropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadDispersionPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDispersion): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadDispersionPropertiesAsync( + context: string, + material: IMaterial, + babylonMaterial: Material, + extension: IKHRMaterialsDispersion, + useOpenPBR: boolean = false + ): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { 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_diffuse_transmission extensions. - if (!babylonMaterial.subSurface.isRefractionEnabled || !extension.dispersion) { - return Promise.resolve(); + if (!useOpenPBR) { + // If transparency isn't enabled already, this extension shouldn't do anything. + // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions. + if (!(babylonMaterial as PBRMaterial).subSurface.isRefractionEnabled || !extension.dispersion) { + return Promise.resolve(); + } + (babylonMaterial as PBRMaterial).subSurface.isDispersionEnabled = true; + (babylonMaterial as PBRMaterial).subSurface.dispersion = extension.dispersion; } - babylonMaterial.subSurface.isDispersionEnabled = true; - babylonMaterial.subSurface.dispersion = extension.dispersion; return Promise.resolve(); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts index 47785510fe7..0b334915f2c 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -22,6 +22,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md) */ @@ -61,8 +63,15 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } // eslint-disable-next-line github/no-then return await this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial).then(() => { this._loadEmissiveProperties(extensionContext, extension, babylonMaterial); @@ -71,7 +80,7 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { } private _loadEmissiveProperties(context: string, properties: IKHRMaterialsEmissiveStrength, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts index ad70f99ba58..6c3479fa586 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -21,6 +22,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_ior/README.md) */ @@ -65,26 +68,38 @@ export class KHR_materials_ior implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadIorPropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadIorPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } + let indexOfRefraction = 1.5; if (properties.ior !== undefined) { - babylonMaterial.indexOfRefraction = properties.ior; + indexOfRefraction = properties.ior; } else { - babylonMaterial.indexOfRefraction = KHR_materials_ior._DEFAULT_IOR; + indexOfRefraction = KHR_materials_ior._DEFAULT_IOR; + } + + if (!useOpenPBR) { + (babylonMaterial as PBRMaterial).indexOfRefraction = indexOfRefraction; } return Promise.resolve(); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts index 11168af02da..22271fa7961 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts @@ -1,6 +1,8 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; +import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +23,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_iridescence/README.md) */ @@ -60,36 +64,48 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const promises = new Array>(); + let iridescenceWeight = 0.0; + let iridescenceWeightTexture: Nullable = null; + let iridescenceIor = 1.3; + let iridescenceThicknessMinimum = 100; + let iridescenceThicknessMaximum = 400; + let iridescenceThicknessTexture: Nullable = null; - babylonMaterial.iridescence.isEnabled = true; + const promises = new Array>(); - babylonMaterial.iridescence.intensity = properties.iridescenceFactor ?? 0; - babylonMaterial.iridescence.indexOfRefraction = properties.iridescenceIor ?? (properties as any).iridescenceIOR ?? 1.3; - babylonMaterial.iridescence.minimumThickness = properties.iridescenceThicknessMinimum ?? 100; - babylonMaterial.iridescence.maximumThickness = properties.iridescenceThicknessMaximum ?? 400; + iridescenceWeight = properties.iridescenceFactor ?? 0; + iridescenceIor = properties.iridescenceIor ?? (properties as any).iridescenceIOR ?? 1.3; + iridescenceThicknessMinimum = properties.iridescenceThicknessMinimum ?? 100; + iridescenceThicknessMaximum = properties.iridescenceThicknessMaximum ?? 400; if (properties.iridescenceTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/iridescenceTexture`, properties.iridescenceTexture, (texture) => { texture.name = `${babylonMaterial.name} (Iridescence)`; - babylonMaterial.iridescence.texture = texture; + iridescenceWeightTexture = texture; }) ); } @@ -98,13 +114,23 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/iridescenceThicknessTexture`, properties.iridescenceThicknessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Iridescence Thickness)`; - babylonMaterial.iridescence.thicknessTexture = texture; + iridescenceThicknessTexture = texture; }) ); } // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => {}); + return Promise.all(promises).then(() => { + const pbrMaterial = babylonMaterial as PBRMaterial; + pbrMaterial.iridescence.isEnabled = true; + + pbrMaterial.iridescence.intensity = iridescenceWeight; + pbrMaterial.iridescence.indexOfRefraction = iridescenceIor; + pbrMaterial.iridescence.minimumThickness = iridescenceThicknessMinimum; + pbrMaterial.iridescence.maximumThickness = iridescenceThicknessMaximum; + pbrMaterial.iridescence.texture = iridescenceWeightTexture; + pbrMaterial.iridescence.thicknessTexture = iridescenceThicknessTexture; + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index 16e5f3a8509..562a3b820eb 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -16,8 +16,8 @@ import type { AnimationGroup } from "core/Animations/animationGroup"; import { Bone } from "core/Bones/bone"; import { Skeleton } from "core/Bones/skeleton"; import { Material } from "core/Materials/material"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { ITextureCreationOptions } from "core/Materials/Textures/texture"; import { Texture } from "core/Materials/Textures/texture"; @@ -87,6 +87,8 @@ import { GetTypedArrayConstructor } from "core/Buffers/bufferUtils"; export { GLTFFileLoader }; +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + interface ILoaderProperty extends IProperty { _activeLoaderExtensionFunctions: { [id: string]: boolean; @@ -400,6 +402,14 @@ export class GLTFLoader implements IGLTFLoader { await this._loadExtensionsAsync(); + if (this.parent.useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } + const loadingToReadyCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.READY]}`; const loadingToCompleteCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.COMPLETE]}`; @@ -2128,40 +2138,42 @@ export class GLTFLoader implements IGLTFLoader { } private _loadMaterialMetallicRoughnessPropertiesAsync(context: string, properties: IMaterialPbrMetallicRoughness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); if (properties) { - if (babylonMaterial instanceof OpenPBRMaterial) { + if (this.parent.useOpenPBR) { + const mat = babylonMaterial as OpenPBRMaterial; if (properties.baseColorFactor) { - babylonMaterial.baseColor = Color3.FromArray(properties.baseColorFactor); - babylonMaterial.geometryOpacity = properties.baseColorFactor[3]; + mat.baseColor = Color3.FromArray(properties.baseColorFactor); + mat.geometryOpacity = properties.baseColorFactor[3]; } else { - babylonMaterial.baseColor = Color3.White(); + mat.baseColor = Color3.White(); } } else { + const mat = babylonMaterial as PBRMaterial; if (properties.baseColorFactor) { - babylonMaterial.albedoColor = Color3.FromArray(properties.baseColorFactor); - babylonMaterial.alpha = properties.baseColorFactor[3]; + mat.albedoColor = Color3.FromArray(properties.baseColorFactor); + mat.alpha = properties.baseColorFactor[3]; } else { - babylonMaterial.albedoColor = Color3.White(); + mat.albedoColor = Color3.White(); } + mat.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; + mat.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; + babylonMaterial = mat; } - babylonMaterial.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; - babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; - if (properties.baseColorTexture) { promises.push( this.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Base Color)`; - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseColorTexture = texture; + if (this.parent.useOpenPBR) { + (babylonMaterial as OpenPBRMaterial).baseColorTexture = texture; } else { - babylonMaterial.albedoTexture = texture; + (babylonMaterial as PBRMaterial).albedoTexture = texture; } }) ); @@ -2172,13 +2184,13 @@ export class GLTFLoader implements IGLTFLoader { promises.push( this.loadTextureInfoAsync(`${context}/metallicRoughnessTexture`, properties.metallicRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Metallic Roughness)`; - babylonMaterial.metallicTexture = texture; + (babylonMaterial as PBRMaterial).metallicTexture = texture; }) ); - babylonMaterial.useMetallnessFromMetallicTextureBlue = true; - babylonMaterial.useRoughnessFromMetallicTextureGreen = true; - babylonMaterial.useRoughnessFromMetallicTextureAlpha = false; + (babylonMaterial as PBRMaterial).useMetallnessFromMetallicTextureBlue = true; + (babylonMaterial as PBRMaterial).useRoughnessFromMetallicTextureGreen = true; + (babylonMaterial as PBRMaterial).useRoughnessFromMetallicTextureAlpha = false; } } @@ -2241,12 +2253,7 @@ export class GLTFLoader implements IGLTFLoader { private _createDefaultMaterial(name: string, babylonDrawMode: number): Material { this._babylonScene._blockEntityCollection = !!this._assetContainer; - let babylonMaterial; - if (this.parent.useOpenPBR) { - babylonMaterial = new OpenPBRMaterial(name, this._babylonScene); - } else { - babylonMaterial = new PBRMaterial(name, this._babylonScene); - } + const babylonMaterial = new PBRMaterialClass(name, this._babylonScene); babylonMaterial._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; // Moved to mesh so user can change materials on gltf meshes: babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation; @@ -2254,7 +2261,7 @@ export class GLTFLoader implements IGLTFLoader { babylonMaterial.enableSpecularAntiAliasing = true; babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage; babylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage; - babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE; + babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_OPAQUE; babylonMaterial.metallic = 1; babylonMaterial.roughness = 1; @@ -2314,16 +2321,16 @@ export class GLTFLoader implements IGLTFLoader { * @returns A promise that resolves when the load is complete */ public loadMaterialBasePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.emissionColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); + if (this.parent.useOpenPBR) { + (babylonMaterial as OpenPBRMaterial).emissionColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); } else { - babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); + (babylonMaterial as PBRMaterial).emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); } if (material.doubleSided) { babylonMaterial.backFaceCulling = false; @@ -2383,21 +2390,21 @@ export class GLTFLoader implements IGLTFLoader { * @param babylonMaterial The Babylon material */ public loadMaterialAlphaProperties(context: string, material: IMaterial, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const baseColorTexture = babylonMaterial instanceof OpenPBRMaterial ? babylonMaterial.baseColorTexture : babylonMaterial.albedoTexture; + const baseColorTexture = this.parent.useOpenPBR ? (babylonMaterial as OpenPBRMaterial).baseColorTexture : (babylonMaterial as PBRMaterial).albedoTexture; const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE; switch (alphaMode) { case MaterialAlphaMode.OPAQUE: { - babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE; + babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_OPAQUE; babylonMaterial.alpha = 1.0; // Force alpha to 1.0 for opaque mode. break; } case MaterialAlphaMode.MASK: { - babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHATEST; + babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_ALPHATEST; babylonMaterial.alphaCutOff = material.alphaCutoff == undefined ? 0.5 : material.alphaCutoff; if (baseColorTexture) { baseColorTexture.hasAlpha = true; @@ -2405,7 +2412,7 @@ export class GLTFLoader implements IGLTFLoader { break; } case MaterialAlphaMode.BLEND: { - babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHABLEND; + babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_ALPHABLEND; if (baseColorTexture) { baseColorTexture.hasAlpha = true; babylonMaterial.useAlphaFromAlbedoTexture = true; @@ -2926,7 +2933,7 @@ export class GLTFLoader implements IGLTFLoader { return this._applyExtensions( material, "loadMaterialProperties", - (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial) + (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial, this.parent.useOpenPBR) ); } From c1c7c59d745dd061af842a005998f50bce588fa7 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Fri, 11 Jul 2025 08:42:43 -0700 Subject: [PATCH 15/23] Finish glTFLoader dynamic material load --- .../2.0/Extensions/KHR_materials_sheen.ts | 59 ++++++---- .../2.0/Extensions/KHR_materials_specular.ts | 27 +++-- .../Extensions/KHR_materials_transmission.ts | 104 +++++++++++------- .../2.0/Extensions/KHR_materials_volume.ts | 81 ++++++++++---- .../glTF/2.0/Extensions/MSFT_minecraftMesh.ts | 17 ++- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 27 +++-- .../src/glTF/2.0/glTFLoaderExtension.ts | 3 +- 7 files changed, 217 insertions(+), 101 deletions(-) diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts index 4816792a5e3..2a2a734fa02 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts @@ -1,6 +1,8 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; +import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -22,6 +24,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_sheen/README.md) * [Playground Sample](https://www.babylonjs-playground.com/frame.html#BNIZX6#4) @@ -62,46 +66,51 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadSheenPropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadSheenPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material, useOpenPBR: boolean): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const promises = new Array>(); + let sheenColor = Color3.Black(); + let sheenColorTexture: Nullable = null; + let sheenRoughness = 0.0; + let sheenRoughnessTexture: Nullable = null; - babylonMaterial.sheen.isEnabled = true; - babylonMaterial.sheen.intensity = 1; + const promises = new Array>(); if (properties.sheenColorFactor != undefined) { - babylonMaterial.sheen.color = Color3.FromArray(properties.sheenColorFactor); - } else { - babylonMaterial.sheen.color = Color3.Black(); + sheenColor = Color3.FromArray(properties.sheenColorFactor); } if (properties.sheenColorTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/sheenColorTexture`, properties.sheenColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Sheen Color)`; - babylonMaterial.sheen.texture = texture; + sheenColorTexture = texture; }) ); } if (properties.sheenRoughnessFactor !== undefined) { - babylonMaterial.sheen.roughness = properties.sheenRoughnessFactor; - } else { - babylonMaterial.sheen.roughness = 0; + sheenRoughness = properties.sheenRoughnessFactor; } if (properties.sheenRoughnessTexture) { @@ -109,16 +118,26 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/sheenRoughnessTexture`, properties.sheenRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Sheen Roughness)`; - babylonMaterial.sheen.textureRoughness = texture; + sheenRoughnessTexture = texture; }) ); } - babylonMaterial.sheen.albedoScaling = true; - babylonMaterial.sheen.useRoughnessFromMainTexture = false; - // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => {}); + return Promise.all(promises).then(() => { + if (useOpenPBR) { + return; + } + const pbrMaterial = babylonMaterial as PBRMaterial; + pbrMaterial.sheen.isEnabled = true; + pbrMaterial.sheen.intensity = 1; + pbrMaterial.sheen.color = sheenColor; + pbrMaterial.sheen.texture = sheenColorTexture; + pbrMaterial.sheen.roughness = sheenRoughness; + pbrMaterial.sheen.textureRoughness = sheenRoughnessTexture; + pbrMaterial.sheen.albedoScaling = true; + pbrMaterial.sheen.useRoughnessFromMainTexture = false; + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts index a55f058dca1..2e18726a4a9 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -24,6 +24,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_specular/README.md) */ @@ -63,18 +65,25 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadSpecularPropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadSpecularPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // Handle the EXT_materials_specular_edge_color sub-extension // https://github.com/KhronosGroup/glTF/blob/2a1111b88f052cbd3e2d82abb9faee56e7494904/extensions/2.0/Vendor/EXT_materials_specular_edge_color/README.md - if (extension.extensions && extension.extensions.EXT_materials_specular_edge_color && babylonMaterial instanceof PBRMaterial) { + if (!useOpenPBR && extension.extensions && extension.extensions.EXT_materials_specular_edge_color) { const specularEdgeColorExtension = extension.extensions.EXT_materials_specular_edge_color as IEXTMaterialsSpecularEdgeColor; if (specularEdgeColorExtension.specularEdgeColorEnabled) { - babylonMaterial.brdf.dielectricSpecularModel = Constants.MATERIAL_DIELECTRIC_SPECULAR_MODEL_OPENPBR; - babylonMaterial.brdf.conductorSpecularModel = Constants.MATERIAL_CONDUCTOR_SPECULAR_MODEL_OPENPBR; + (babylonMaterial as PBRMaterial).brdf.dielectricSpecularModel = Constants.MATERIAL_DIELECTRIC_SPECULAR_MODEL_OPENPBR; + (babylonMaterial as PBRMaterial).brdf.conductorSpecularModel = Constants.MATERIAL_CONDUCTOR_SPECULAR_MODEL_OPENPBR; } } // eslint-disable-next-line github/no-then @@ -83,8 +92,8 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material, useOpenPBR: boolean): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts index 5f91a41d555..b404b2d822f 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -62,6 +63,8 @@ interface ITransmissionHelperOptions { clearColor?: Color4; } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * A class to handle setting up the rendering of opaque objects to be shown through transmissive objects. */ @@ -166,7 +169,7 @@ class TransmissionHelper { if (!material) { return false; } - if (material instanceof PBRMaterial && material.subSurface.isRefractionEnabled) { + if (material instanceof PBRMaterialClass && (material as any).subSurface.isRefractionEnabled) { return true; } return false; @@ -220,8 +223,8 @@ class TransmissionHelper { // If the material is transparent, make sure that it's added to the transparent list and removed from the opaque list const useTransmission = this._shouldRenderAsTransmission(mesh.material); if (useTransmission) { - if (mesh.material instanceof PBRMaterial) { - mesh.material.subSurface.refractionTexture = this._opaqueRenderTarget; + if (mesh.material instanceof PBRMaterialClass) { + (mesh.material as any).subSurface.refractionTexture = this._opaqueRenderTarget; } if (opaqueIdx !== -1) { this._opaqueMeshesCache.splice(opaqueIdx, 1); @@ -366,60 +369,87 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); + promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async - private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadTransparentPropertiesAsync( + context: string, + material: IMaterial, + babylonMaterial: Material, + extension: IKHRMaterialsTransmission, + useOpenPBR: boolean + ): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const pbrMaterial = babylonMaterial; - - // Enables "refraction" texture which represents transmitted light. - pbrMaterial.subSurface.isRefractionEnabled = true; - - // Since this extension models thin-surface transmission only, we must make IOR = 1.0 - pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; - // Albedo colour will tint transmission. - pbrMaterial.subSurface.useAlbedoToTintRefraction = true; + let transmissionWeight = 0.0; + let transmissionWeightTexture: Nullable = null; + const promises = new Array>(); if (extension.transmissionFactor !== undefined) { - pbrMaterial.subSurface.refractionIntensity = extension.transmissionFactor; - const scene = pbrMaterial.getScene() as unknown as ITransmissionHelperHolder; - if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper) { - new TransmissionHelper({}, pbrMaterial.getScene()); - } else if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper?._isRenderTargetValid()) { - // If the render target is not valid, recreate it. - scene._transmissionHelper?._setupRenderTargets(); - } + transmissionWeight = extension.transmissionFactor; } else { - pbrMaterial.subSurface.refractionIntensity = 0.0; - pbrMaterial.subSurface.isRefractionEnabled = false; return Promise.resolve(); } - - pbrMaterial.subSurface.minimumThickness = 0.0; - pbrMaterial.subSurface.maximumThickness = 0.0; if (extension.transmissionTexture) { (extension.transmissionTexture as ITextureInfo).nonColorData = true; // eslint-disable-next-line github/no-then - return this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, undefined).then((texture: BaseTexture) => { - texture.name = `${babylonMaterial.name} (Transmission)`; - pbrMaterial.subSurface.refractionIntensityTexture = texture; - pbrMaterial.subSurface.useGltfStyleTextures = true; - }); - } else { - return Promise.resolve(); + promises.push( + this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, (texture: BaseTexture) => { + texture.name = `${babylonMaterial.name} (Transmission)`; + transmissionWeightTexture = texture; + }) + ); } + + // eslint-disable-next-line github/no-then + return Promise.all(promises).then(() => { + if (useOpenPBR) { + return; + } + const pbrMaterial = babylonMaterial as PBRMaterial; + + // Enables "refraction" texture which represents transmitted light. + pbrMaterial.subSurface.isRefractionEnabled = transmissionWeight !== 0; + + // Since this extension models thin-surface transmission only, we must make IOR = 1.0 + pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; + + // Albedo colour will tint transmission. + pbrMaterial.subSurface.useAlbedoToTintRefraction = true; + + pbrMaterial.subSurface.refractionIntensity = transmissionWeight; + + if (transmissionWeight) { + const scene = pbrMaterial.getScene() as unknown as ITransmissionHelperHolder; + if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper) { + new TransmissionHelper({}, pbrMaterial.getScene()); + } else if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper?._isRenderTargetValid()) { + // If the render target is not valid, recreate it. + scene._transmissionHelper?._setupRenderTargets(); + } + } + pbrMaterial.subSurface.minimumThickness = 0.0; + pbrMaterial.subSurface.maximumThickness = 0.0; + pbrMaterial.subSurface.refractionIntensityTexture = transmissionWeightTexture; + pbrMaterial.subSurface.useGltfStyleTextures = true; + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts index 349cbd67c10..6b70b2453bf 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts @@ -1,7 +1,9 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; +import { Color3 } from "core/Maths/math.color"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -22,6 +24,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_volume/README.md) * @since 5.0.0 @@ -69,50 +73,85 @@ export class KHR_materials_volume implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension)); + promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume, useOpenPBR: boolean): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } + if (useOpenPBR) { + return Promise.resolve(); + } // If transparency isn't enabled already, this extension shouldn't do anything. // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions. - if ((!babylonMaterial.subSurface.isRefractionEnabled && !babylonMaterial.subSurface.isTranslucencyEnabled) || !extension.thicknessFactor) { + if ( + (!(babylonMaterial as PBRMaterial).subSurface.isRefractionEnabled && !(babylonMaterial as PBRMaterial).subSurface.isTranslucencyEnabled) || + !extension.thicknessFactor + ) { return Promise.resolve(); } - // IOR in this extension only affects interior. - babylonMaterial.subSurface.volumeIndexOfRefraction = babylonMaterial.indexOfRefraction; - const attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE; - babylonMaterial.subSurface.tintColorAtDistance = attenuationDistance; + let attenuationDistance = Number.MAX_VALUE; + const attenuationColor: Color3 = Color3.White(); + let thicknessTexture: Nullable = null; + let thicknessFactor = 0.0; + + const promises = new Array>(); + + attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE; if (extension.attenuationColor !== undefined && extension.attenuationColor.length == 3) { - babylonMaterial.subSurface.tintColor.copyFromFloats(extension.attenuationColor[0], extension.attenuationColor[1], extension.attenuationColor[2]); + attenuationColor.copyFromFloats(extension.attenuationColor[0], extension.attenuationColor[1], extension.attenuationColor[2]); } - babylonMaterial.subSurface.minimumThickness = 0.0; - babylonMaterial.subSurface.maximumThickness = extension.thicknessFactor; - babylonMaterial.subSurface.useThicknessAsDepth = true; + thicknessFactor = extension.thicknessFactor; if (extension.thicknessTexture) { (extension.thicknessTexture as ITextureInfo).nonColorData = true; // eslint-disable-next-line github/no-then - return this._loader.loadTextureInfoAsync(`${context}/thicknessTexture`, extension.thicknessTexture).then((texture: BaseTexture) => { - texture.name = `${babylonMaterial.name} (Thickness)`; - babylonMaterial.subSurface.thicknessTexture = texture; - babylonMaterial.subSurface.useGltfStyleTextures = true; - }); - } else { - return Promise.resolve(); + promises.push( + this._loader.loadTextureInfoAsync(`${context}/thicknessTexture`, extension.thicknessTexture, (texture: BaseTexture) => { + texture.name = `${babylonMaterial.name} (Thickness)`; + thicknessTexture = texture; + }) + ); } + + // eslint-disable-next-line github/no-then + return Promise.all(promises).then(() => { + if (useOpenPBR) { + return; + } + + const pbrMaterial = babylonMaterial as PBRMaterial; + // IOR in this extension only affects interior. + pbrMaterial.subSurface.volumeIndexOfRefraction = pbrMaterial.indexOfRefraction; + pbrMaterial.subSurface.tintColorAtDistance = attenuationDistance; + pbrMaterial.subSurface.tintColor = attenuationColor; + + pbrMaterial.subSurface.minimumThickness = 0.0; + pbrMaterial.subSurface.maximumThickness = thicknessFactor; + pbrMaterial.subSurface.useThicknessAsDepth = true; + if (thicknessTexture) { + pbrMaterial.subSurface.thicknessTexture = thicknessTexture; + pbrMaterial.subSurface.useGltfStyleTextures = true; + } + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts index f52207f3e74..ecb866e40c5 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +21,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** @internal */ // eslint-disable-next-line @typescript-eslint/naming-convention export class MSFT_minecraftMesh implements IGLTFLoaderExtension { @@ -45,10 +47,17 @@ export class MSFT_minecraftMesh implements IGLTFLoaderExtension { /** @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } if (extra) { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${extraContext}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index 5e16205e167..f99204093bb 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +21,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** @internal */ // eslint-disable-next-line @typescript-eslint/naming-convention export class MSFT_sRGBFactors implements IGLTFLoaderExtension { @@ -45,23 +47,30 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { /** @internal*/ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } if (extra) { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${extraContext}: Material type not supported`); } const promise = this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial); const useExactSrgbConversions = babylonMaterial.getScene().getEngine().useExactSrgbConversions; - if (babylonMaterial instanceof OpenPBRMaterial) { - if (!babylonMaterial.baseColorTexture) { - babylonMaterial.baseColor.toLinearSpaceToRef(babylonMaterial.baseColor, useExactSrgbConversions); + if (useOpenPBR) { + if (!(babylonMaterial as OpenPBRMaterial).baseColorTexture) { + (babylonMaterial as OpenPBRMaterial).baseColor.toLinearSpaceToRef((babylonMaterial as OpenPBRMaterial).baseColor, useExactSrgbConversions); } } else { - if (!babylonMaterial.albedoTexture) { - babylonMaterial.albedoColor.toLinearSpaceToRef(babylonMaterial.albedoColor, useExactSrgbConversions); + if (!(babylonMaterial as PBRMaterial).albedoTexture) { + (babylonMaterial as PBRMaterial).albedoColor.toLinearSpaceToRef((babylonMaterial as PBRMaterial).albedoColor, useExactSrgbConversions); } } diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts index 72ae55dce23..15930ba12e6 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts @@ -127,9 +127,10 @@ export interface IGLTFLoaderExtension extends IGLTFBaseLoaderExtension, IDisposa * @param context The context when loading the asset * @param material The glTF material property * @param babylonMaterial The Babylon material + * @param useOpenPBR Load materials as OpenPBR materials instead of glTF PBR materials. * @returns A promise that resolves when the load is complete or null if not handled */ - loadMaterialPropertiesAsync?(context: string, material: IMaterial, babylonMaterial: Material): Nullable>; + loadMaterialPropertiesAsync?(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean): Nullable>; /** * Define this method to modify the default behavior when loading texture infos. From 34dfcec05be787c50880a345132ac7f1c13f6fd4 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Tue, 15 Jul 2025 09:00:10 -0700 Subject: [PATCH 16/23] Revert "Finish glTFLoader dynamic material load" This reverts commit c1c7c59d745dd061af842a005998f50bce588fa7. --- .../2.0/Extensions/KHR_materials_sheen.ts | 59 ++++------ .../2.0/Extensions/KHR_materials_specular.ts | 27 ++--- .../Extensions/KHR_materials_transmission.ts | 104 +++++++----------- .../2.0/Extensions/KHR_materials_volume.ts | 81 ++++---------- .../glTF/2.0/Extensions/MSFT_minecraftMesh.ts | 17 +-- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 27 ++--- .../src/glTF/2.0/glTFLoaderExtension.ts | 3 +- 7 files changed, 101 insertions(+), 217 deletions(-) diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts index 2a2a734fa02..4816792a5e3 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts @@ -1,8 +1,6 @@ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import type { Material } from "core/Materials/material"; -import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -24,8 +22,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_sheen/README.md) * [Playground Sample](https://www.babylonjs-playground.com/frame.html#BNIZX6#4) @@ -66,51 +62,46 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadSheenPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); + promises.push(this._loadSheenPropertiesAsync(extensionContext, extension, babylonMaterial)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material, useOpenPBR: boolean): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material): Promise { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } - let sheenColor = Color3.Black(); - let sheenColorTexture: Nullable = null; - let sheenRoughness = 0.0; - let sheenRoughnessTexture: Nullable = null; - const promises = new Array>(); + babylonMaterial.sheen.isEnabled = true; + babylonMaterial.sheen.intensity = 1; + if (properties.sheenColorFactor != undefined) { - sheenColor = Color3.FromArray(properties.sheenColorFactor); + babylonMaterial.sheen.color = Color3.FromArray(properties.sheenColorFactor); + } else { + babylonMaterial.sheen.color = Color3.Black(); } if (properties.sheenColorTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/sheenColorTexture`, properties.sheenColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Sheen Color)`; - sheenColorTexture = texture; + babylonMaterial.sheen.texture = texture; }) ); } if (properties.sheenRoughnessFactor !== undefined) { - sheenRoughness = properties.sheenRoughnessFactor; + babylonMaterial.sheen.roughness = properties.sheenRoughnessFactor; + } else { + babylonMaterial.sheen.roughness = 0; } if (properties.sheenRoughnessTexture) { @@ -118,26 +109,16 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/sheenRoughnessTexture`, properties.sheenRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Sheen Roughness)`; - sheenRoughnessTexture = texture; + babylonMaterial.sheen.textureRoughness = texture; }) ); } + babylonMaterial.sheen.albedoScaling = true; + babylonMaterial.sheen.useRoughnessFromMainTexture = false; + // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => { - if (useOpenPBR) { - return; - } - const pbrMaterial = babylonMaterial as PBRMaterial; - pbrMaterial.sheen.isEnabled = true; - pbrMaterial.sheen.intensity = 1; - pbrMaterial.sheen.color = sheenColor; - pbrMaterial.sheen.texture = sheenColorTexture; - pbrMaterial.sheen.roughness = sheenRoughness; - pbrMaterial.sheen.textureRoughness = sheenRoughnessTexture; - pbrMaterial.sheen.albedoScaling = true; - pbrMaterial.sheen.useRoughnessFromMainTexture = false; - }); + return Promise.all(promises).then(() => {}); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts index 2e18726a4a9..a55f058dca1 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -24,8 +24,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_specular/README.md) */ @@ -65,25 +63,18 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadSpecularPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); + promises.push(this._loadSpecularPropertiesAsync(extensionContext, extension, babylonMaterial)); // Handle the EXT_materials_specular_edge_color sub-extension // https://github.com/KhronosGroup/glTF/blob/2a1111b88f052cbd3e2d82abb9faee56e7494904/extensions/2.0/Vendor/EXT_materials_specular_edge_color/README.md - if (!useOpenPBR && extension.extensions && extension.extensions.EXT_materials_specular_edge_color) { + if (extension.extensions && extension.extensions.EXT_materials_specular_edge_color && babylonMaterial instanceof PBRMaterial) { const specularEdgeColorExtension = extension.extensions.EXT_materials_specular_edge_color as IEXTMaterialsSpecularEdgeColor; if (specularEdgeColorExtension.specularEdgeColorEnabled) { - (babylonMaterial as PBRMaterial).brdf.dielectricSpecularModel = Constants.MATERIAL_DIELECTRIC_SPECULAR_MODEL_OPENPBR; - (babylonMaterial as PBRMaterial).brdf.conductorSpecularModel = Constants.MATERIAL_CONDUCTOR_SPECULAR_MODEL_OPENPBR; + babylonMaterial.brdf.dielectricSpecularModel = Constants.MATERIAL_DIELECTRIC_SPECULAR_MODEL_OPENPBR; + babylonMaterial.brdf.conductorSpecularModel = Constants.MATERIAL_CONDUCTOR_SPECULAR_MODEL_OPENPBR; } } // eslint-disable-next-line github/no-then @@ -92,8 +83,8 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material, useOpenPBR: boolean): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material): Promise { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts index b404b2d822f..5f91a41d555 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts @@ -1,6 +1,5 @@ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -63,8 +62,6 @@ interface ITransmissionHelperOptions { clearColor?: Color4; } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * A class to handle setting up the rendering of opaque objects to be shown through transmissive objects. */ @@ -169,7 +166,7 @@ class TransmissionHelper { if (!material) { return false; } - if (material instanceof PBRMaterialClass && (material as any).subSurface.isRefractionEnabled) { + if (material instanceof PBRMaterial && material.subSurface.isRefractionEnabled) { return true; } return false; @@ -223,8 +220,8 @@ class TransmissionHelper { // If the material is transparent, make sure that it's added to the transparent list and removed from the opaque list const useTransmission = this._shouldRenderAsTransmission(mesh.material); if (useTransmission) { - if (mesh.material instanceof PBRMaterialClass) { - (mesh.material as any).subSurface.refractionTexture = this._opaqueRenderTarget; + if (mesh.material instanceof PBRMaterial) { + mesh.material.subSurface.refractionTexture = this._opaqueRenderTarget; } if (opaqueIdx !== -1) { this._opaqueMeshesCache.splice(opaqueIdx, 1); @@ -369,87 +366,60 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); + promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async - private _loadTransparentPropertiesAsync( - context: string, - material: IMaterial, - babylonMaterial: Material, - extension: IKHRMaterialsTransmission, - useOpenPBR: boolean - ): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } + const pbrMaterial = babylonMaterial; + + // Enables "refraction" texture which represents transmitted light. + pbrMaterial.subSurface.isRefractionEnabled = true; + + // Since this extension models thin-surface transmission only, we must make IOR = 1.0 + pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; - let transmissionWeight = 0.0; - let transmissionWeightTexture: Nullable = null; + // Albedo colour will tint transmission. + pbrMaterial.subSurface.useAlbedoToTintRefraction = true; - const promises = new Array>(); if (extension.transmissionFactor !== undefined) { - transmissionWeight = extension.transmissionFactor; + pbrMaterial.subSurface.refractionIntensity = extension.transmissionFactor; + const scene = pbrMaterial.getScene() as unknown as ITransmissionHelperHolder; + if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper) { + new TransmissionHelper({}, pbrMaterial.getScene()); + } else if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper?._isRenderTargetValid()) { + // If the render target is not valid, recreate it. + scene._transmissionHelper?._setupRenderTargets(); + } } else { + pbrMaterial.subSurface.refractionIntensity = 0.0; + pbrMaterial.subSurface.isRefractionEnabled = false; return Promise.resolve(); } + + pbrMaterial.subSurface.minimumThickness = 0.0; + pbrMaterial.subSurface.maximumThickness = 0.0; if (extension.transmissionTexture) { (extension.transmissionTexture as ITextureInfo).nonColorData = true; // eslint-disable-next-line github/no-then - promises.push( - this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, (texture: BaseTexture) => { - texture.name = `${babylonMaterial.name} (Transmission)`; - transmissionWeightTexture = texture; - }) - ); + return this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, undefined).then((texture: BaseTexture) => { + texture.name = `${babylonMaterial.name} (Transmission)`; + pbrMaterial.subSurface.refractionIntensityTexture = texture; + pbrMaterial.subSurface.useGltfStyleTextures = true; + }); + } else { + return Promise.resolve(); } - - // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => { - if (useOpenPBR) { - return; - } - const pbrMaterial = babylonMaterial as PBRMaterial; - - // Enables "refraction" texture which represents transmitted light. - pbrMaterial.subSurface.isRefractionEnabled = transmissionWeight !== 0; - - // Since this extension models thin-surface transmission only, we must make IOR = 1.0 - pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; - - // Albedo colour will tint transmission. - pbrMaterial.subSurface.useAlbedoToTintRefraction = true; - - pbrMaterial.subSurface.refractionIntensity = transmissionWeight; - - if (transmissionWeight) { - const scene = pbrMaterial.getScene() as unknown as ITransmissionHelperHolder; - if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper) { - new TransmissionHelper({}, pbrMaterial.getScene()); - } else if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper?._isRenderTargetValid()) { - // If the render target is not valid, recreate it. - scene._transmissionHelper?._setupRenderTargets(); - } - } - pbrMaterial.subSurface.minimumThickness = 0.0; - pbrMaterial.subSurface.maximumThickness = 0.0; - pbrMaterial.subSurface.refractionIntensityTexture = transmissionWeightTexture; - pbrMaterial.subSurface.useGltfStyleTextures = true; - }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts index 6b70b2453bf..349cbd67c10 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts @@ -1,9 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import type { Material } from "core/Materials/material"; -import { Color3 } from "core/Maths/math.color"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -24,8 +22,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_volume/README.md) * @since 5.0.0 @@ -73,85 +69,50 @@ export class KHR_materials_volume implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); + promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume, useOpenPBR: boolean): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume): Promise { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } - if (useOpenPBR) { - return Promise.resolve(); - } // If transparency isn't enabled already, this extension shouldn't do anything. // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions. - if ( - (!(babylonMaterial as PBRMaterial).subSurface.isRefractionEnabled && !(babylonMaterial as PBRMaterial).subSurface.isTranslucencyEnabled) || - !extension.thicknessFactor - ) { + if ((!babylonMaterial.subSurface.isRefractionEnabled && !babylonMaterial.subSurface.isTranslucencyEnabled) || !extension.thicknessFactor) { return Promise.resolve(); } - let attenuationDistance = Number.MAX_VALUE; - const attenuationColor: Color3 = Color3.White(); - let thicknessTexture: Nullable = null; - let thicknessFactor = 0.0; - - const promises = new Array>(); - - attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE; + // IOR in this extension only affects interior. + babylonMaterial.subSurface.volumeIndexOfRefraction = babylonMaterial.indexOfRefraction; + const attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE; + babylonMaterial.subSurface.tintColorAtDistance = attenuationDistance; if (extension.attenuationColor !== undefined && extension.attenuationColor.length == 3) { - attenuationColor.copyFromFloats(extension.attenuationColor[0], extension.attenuationColor[1], extension.attenuationColor[2]); + babylonMaterial.subSurface.tintColor.copyFromFloats(extension.attenuationColor[0], extension.attenuationColor[1], extension.attenuationColor[2]); } - thicknessFactor = extension.thicknessFactor; + babylonMaterial.subSurface.minimumThickness = 0.0; + babylonMaterial.subSurface.maximumThickness = extension.thicknessFactor; + babylonMaterial.subSurface.useThicknessAsDepth = true; if (extension.thicknessTexture) { (extension.thicknessTexture as ITextureInfo).nonColorData = true; // eslint-disable-next-line github/no-then - promises.push( - this._loader.loadTextureInfoAsync(`${context}/thicknessTexture`, extension.thicknessTexture, (texture: BaseTexture) => { - texture.name = `${babylonMaterial.name} (Thickness)`; - thicknessTexture = texture; - }) - ); + return this._loader.loadTextureInfoAsync(`${context}/thicknessTexture`, extension.thicknessTexture).then((texture: BaseTexture) => { + texture.name = `${babylonMaterial.name} (Thickness)`; + babylonMaterial.subSurface.thicknessTexture = texture; + babylonMaterial.subSurface.useGltfStyleTextures = true; + }); + } else { + return Promise.resolve(); } - - // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => { - if (useOpenPBR) { - return; - } - - const pbrMaterial = babylonMaterial as PBRMaterial; - // IOR in this extension only affects interior. - pbrMaterial.subSurface.volumeIndexOfRefraction = pbrMaterial.indexOfRefraction; - pbrMaterial.subSurface.tintColorAtDistance = attenuationDistance; - pbrMaterial.subSurface.tintColor = attenuationColor; - - pbrMaterial.subSurface.minimumThickness = 0.0; - pbrMaterial.subSurface.maximumThickness = thicknessFactor; - pbrMaterial.subSurface.useThicknessAsDepth = true; - if (thicknessTexture) { - pbrMaterial.subSurface.thicknessTexture = thicknessTexture; - pbrMaterial.subSurface.useGltfStyleTextures = true; - } - }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts index ecb866e40c5..f52207f3e74 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,8 +21,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** @internal */ // eslint-disable-next-line @typescript-eslint/naming-convention export class MSFT_minecraftMesh implements IGLTFLoaderExtension { @@ -47,17 +45,10 @@ export class MSFT_minecraftMesh implements IGLTFLoaderExtension { /** @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } if (extra) { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${extraContext}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index f99204093bb..5e16205e167 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,8 +21,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** @internal */ // eslint-disable-next-line @typescript-eslint/naming-convention export class MSFT_sRGBFactors implements IGLTFLoaderExtension { @@ -47,30 +45,23 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { /** @internal*/ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } if (extra) { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${extraContext}: Material type not supported`); } const promise = this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial); const useExactSrgbConversions = babylonMaterial.getScene().getEngine().useExactSrgbConversions; - if (useOpenPBR) { - if (!(babylonMaterial as OpenPBRMaterial).baseColorTexture) { - (babylonMaterial as OpenPBRMaterial).baseColor.toLinearSpaceToRef((babylonMaterial as OpenPBRMaterial).baseColor, useExactSrgbConversions); + if (babylonMaterial instanceof OpenPBRMaterial) { + if (!babylonMaterial.baseColorTexture) { + babylonMaterial.baseColor.toLinearSpaceToRef(babylonMaterial.baseColor, useExactSrgbConversions); } } else { - if (!(babylonMaterial as PBRMaterial).albedoTexture) { - (babylonMaterial as PBRMaterial).albedoColor.toLinearSpaceToRef((babylonMaterial as PBRMaterial).albedoColor, useExactSrgbConversions); + if (!babylonMaterial.albedoTexture) { + babylonMaterial.albedoColor.toLinearSpaceToRef(babylonMaterial.albedoColor, useExactSrgbConversions); } } diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts index 15930ba12e6..72ae55dce23 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts @@ -127,10 +127,9 @@ export interface IGLTFLoaderExtension extends IGLTFBaseLoaderExtension, IDisposa * @param context The context when loading the asset * @param material The glTF material property * @param babylonMaterial The Babylon material - * @param useOpenPBR Load materials as OpenPBR materials instead of glTF PBR materials. * @returns A promise that resolves when the load is complete or null if not handled */ - loadMaterialPropertiesAsync?(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean): Nullable>; + loadMaterialPropertiesAsync?(context: string, material: IMaterial, babylonMaterial: Material): Nullable>; /** * Define this method to modify the default behavior when loading texture infos. From b43f753898d5ea47ddc536be03e2494133647884 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Tue, 15 Jul 2025 09:00:24 -0700 Subject: [PATCH 17/23] Revert "WIP glTFLoader dynamic material load" This reverts commit 00d18b18d6aea13545e1afb599fe3a070ee5dd0a. --- .../Extensions/KHR_materials_anisotropy.ts | 24 ++---- .../2.0/Extensions/KHR_materials_clearcoat.ts | 70 +++++----------- .../KHR_materials_diffuse_transmission.ts | 77 +++++++----------- .../Extensions/KHR_materials_dispersion.ts | 40 +++------ .../KHR_materials_emissive_strength.ts | 17 +--- .../glTF/2.0/Extensions/KHR_materials_ior.ts | 29 ++----- .../Extensions/KHR_materials_iridescence.ts | 54 ++++--------- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 81 +++++++++---------- 8 files changed, 127 insertions(+), 265 deletions(-) diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts index a9d2cb7e2eb..c425c295da5 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts @@ -1,6 +1,5 @@ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -22,8 +21,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Specification](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_anisotropy) */ @@ -63,15 +60,8 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial)); @@ -80,23 +70,23 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { } private async _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsAnisotropy, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); - (babylonMaterial as PBRMaterial).anisotropy.isEnabled = true; + babylonMaterial.anisotropy.isEnabled = true; - (babylonMaterial as PBRMaterial).anisotropy.intensity = properties.anisotropyStrength ?? 0; - (babylonMaterial as PBRMaterial).anisotropy.angle = properties.anisotropyRotation ?? 0; + babylonMaterial.anisotropy.intensity = properties.anisotropyStrength ?? 0; + babylonMaterial.anisotropy.angle = properties.anisotropyRotation ?? 0; if (properties.anisotropyTexture) { (properties.anisotropyTexture as ITextureInfo).nonColorData = true; promises.push( this._loader.loadTextureInfoAsync(`${context}/anisotropyTexture`, properties.anisotropyTexture, (texture) => { texture.name = `${babylonMaterial.name} (Anisotropy Intensity)`; - (babylonMaterial as PBRMaterial).anisotropy.texture = texture; + babylonMaterial.anisotropy.texture = texture; }) ); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts index 034c3b49f8b..bc394cd1040 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts @@ -1,8 +1,6 @@ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import type { Material } from "core/Materials/material"; -import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -23,8 +21,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md) * [Playground Sample](https://www.babylonjs-playground.com/frame.html#7F7PN6#8) @@ -65,58 +61,46 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } - if (!(babylonMaterial instanceof PBRMaterialClass)) { - throw new Error(`${context}: Material type not supported`); - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadClearCoatPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); + promises.push(this._loadClearCoatPropertiesAsync(extensionContext, extension, babylonMaterial)); await Promise.all(promises); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material): Promise { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); - let coatRoughness = 0; - let coatWeight = 0; - let coatWeightTexture: Nullable = null; - let coatRoughnessTexture: Nullable = null; - let coatNormalTexture: Nullable = null; - let coatNormalTextureScale = 1; + + babylonMaterial.clearCoat.isEnabled = true; + babylonMaterial.clearCoat.useRoughnessFromMainTexture = false; + babylonMaterial.clearCoat.remapF0OnInterfaceChange = false; if (properties.clearcoatFactor != undefined) { - coatWeight = properties.clearcoatFactor; + babylonMaterial.clearCoat.intensity = properties.clearcoatFactor; } else { - coatWeight = 0; + babylonMaterial.clearCoat.intensity = 0; } if (properties.clearcoatTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/clearcoatTexture`, properties.clearcoatTexture, (texture) => { texture.name = `${babylonMaterial.name} (ClearCoat)`; - coatWeightTexture = texture; + babylonMaterial.clearCoat.texture = texture; }) ); } if (properties.clearcoatRoughnessFactor != undefined) { - coatRoughness = properties.clearcoatRoughnessFactor; + babylonMaterial.clearCoat.roughness = properties.clearcoatRoughnessFactor; } else { - coatRoughness = 0; + babylonMaterial.clearCoat.roughness = 0; } if (properties.clearcoatRoughnessTexture) { @@ -124,7 +108,7 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/clearcoatRoughnessTexture`, properties.clearcoatRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (ClearCoat Roughness)`; - coatRoughnessTexture = texture; + babylonMaterial.clearCoat.textureRoughness = texture; }) ); } @@ -134,37 +118,19 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/clearcoatNormalTexture`, properties.clearcoatNormalTexture, (texture) => { texture.name = `${babylonMaterial.name} (ClearCoat Normal)`; - coatNormalTexture = texture; + babylonMaterial.clearCoat.bumpTexture = texture; }) ); babylonMaterial.invertNormalMapX = !babylonMaterial.getScene().useRightHandedSystem; babylonMaterial.invertNormalMapY = babylonMaterial.getScene().useRightHandedSystem; if (properties.clearcoatNormalTexture.scale != undefined) { - coatNormalTextureScale = properties.clearcoatNormalTexture.scale; + babylonMaterial.clearCoat.bumpTexture!.level = properties.clearcoatNormalTexture.scale; } } // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => { - if (useOpenPBR) { - // eslint-disable-next-line github/no-then - return; - } - const material = babylonMaterial as PBRMaterial; - material.clearCoat.isEnabled = true; - material.clearCoat.useRoughnessFromMainTexture = false; - material.clearCoat.remapF0OnInterfaceChange = false; - material.clearCoat.intensity = coatWeight; - material.clearCoat.texture = coatWeightTexture; - material.clearCoat.roughness = coatRoughness; - material.clearCoat.textureRoughness = coatRoughnessTexture; - - material.clearCoat.bumpTexture = coatNormalTexture; - if (coatNormalTexture) { - material.clearCoat.bumpTexture!.level = coatNormalTextureScale; - } - }); + return Promise.all(promises).then(() => {}); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts index 91930aef943..5507ebfb1ab 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts @@ -1,7 +1,6 @@ /* eslint-disable github/no-then */ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -24,8 +23,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825) * !!! Experimental Extension Subject to Changes !!! @@ -69,15 +66,8 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadTranslucentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); @@ -87,71 +77,62 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async private _loadTranslucentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDiffuseTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } - let translucencyWeight = 0.0; - let translucencyWeightTexture: Nullable; - let translucencyColor = Color3.White(); - let translucencyColorTexture: Nullable; + const pbrMaterial = babylonMaterial; + + // Enables "translucency" texture which represents diffusely-transmitted light. + pbrMaterial.subSurface.isTranslucencyEnabled = true; + + // Since this extension models thin-surface transmission only, we must make the + // internal IOR == 1.0 and set the thickness to 0. + pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; + pbrMaterial.subSurface.minimumThickness = 0.0; + pbrMaterial.subSurface.maximumThickness = 0.0; + + // Tint color will be used for transmission. + pbrMaterial.subSurface.useAlbedoToTintTranslucency = false; if (extension.diffuseTransmissionFactor !== undefined) { - translucencyWeight = extension.diffuseTransmissionFactor; + pbrMaterial.subSurface.translucencyIntensity = extension.diffuseTransmissionFactor; + } else { + pbrMaterial.subSurface.translucencyIntensity = 0.0; + pbrMaterial.subSurface.isTranslucencyEnabled = false; + return Promise.resolve(); } const promises = new Array>(); + pbrMaterial.subSurface.useGltfStyleTextures = true; + if (extension.diffuseTransmissionTexture) { (extension.diffuseTransmissionTexture as ITextureInfo).nonColorData = true; promises.push( this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionTexture`, extension.diffuseTransmissionTexture).then((texture: BaseTexture) => { texture.name = `${babylonMaterial.name} (Diffuse Transmission)`; - translucencyWeightTexture = texture; + pbrMaterial.subSurface.translucencyIntensityTexture = texture; }) ); } if (extension.diffuseTransmissionColorFactor !== undefined) { - translucencyColor = Color3.FromArray(extension.diffuseTransmissionColorFactor); + pbrMaterial.subSurface.translucencyColor = Color3.FromArray(extension.diffuseTransmissionColorFactor); + } else { + pbrMaterial.subSurface.translucencyColor = Color3.White(); } if (extension.diffuseTransmissionColorTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionColorTexture`, extension.diffuseTransmissionColorTexture).then((texture: BaseTexture) => { texture.name = `${babylonMaterial.name} (Diffuse Transmission Color)`; - translucencyColorTexture = texture; + pbrMaterial.subSurface.translucencyColorTexture = texture; }) ); } - return Promise.all(promises).then(() => { - const pbrMaterial = babylonMaterial as PBRMaterial; - - // Enables "translucency" texture which represents diffusely-transmitted light. - pbrMaterial.subSurface.isTranslucencyEnabled = true; - - // Since this extension models thin-surface transmission only, we must make the - // internal IOR == 1.0 and set the thickness to 0. - pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; - pbrMaterial.subSurface.minimumThickness = 0.0; - pbrMaterial.subSurface.maximumThickness = 0.0; - - // Tint color will be used for transmission. - pbrMaterial.subSurface.useAlbedoToTintTranslucency = false; - - pbrMaterial.subSurface.translucencyIntensity = translucencyWeight; - if (translucencyWeight === 0.0) { - pbrMaterial.subSurface.isTranslucencyEnabled = false; - return; - } - - pbrMaterial.subSurface.useGltfStyleTextures = true; - pbrMaterial.subSurface.translucencyIntensityTexture = translucencyWeightTexture; - - pbrMaterial.subSurface.translucencyColor = translucencyColor; - pbrMaterial.subSurface.translucencyColorTexture = translucencyColorTexture; - }); + return Promise.all(promises).then(() => {}); } } 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 31bbbf7b404..1a99485b358 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 @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -22,8 +21,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Specification](https://github.com/KhronosGroup/glTF/blob/87bd64a7f5e23c84b6aef2e6082069583ed0ddb4/extensions/2.0/Khronos/KHR_materials_dispersion/README.md) * @experimental @@ -64,44 +61,29 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadDispersionPropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); + promises.push(this._loadDispersionPropertiesAsync(extensionContext, material, babylonMaterial, extension)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadDispersionPropertiesAsync( - context: string, - material: IMaterial, - babylonMaterial: Material, - extension: IKHRMaterialsDispersion, - useOpenPBR: boolean = false - ): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + private _loadDispersionPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDispersion): Promise { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } - if (!useOpenPBR) { - // If transparency isn't enabled already, this extension shouldn't do anything. - // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions. - if (!(babylonMaterial as PBRMaterial).subSurface.isRefractionEnabled || !extension.dispersion) { - return Promise.resolve(); - } - (babylonMaterial as PBRMaterial).subSurface.isDispersionEnabled = true; - (babylonMaterial as PBRMaterial).subSurface.dispersion = extension.dispersion; + // If transparency isn't enabled already, this extension shouldn't do anything. + // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions. + 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/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts index 0b334915f2c..47785510fe7 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -22,8 +22,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md) */ @@ -63,15 +61,8 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } // eslint-disable-next-line github/no-then return await this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial).then(() => { this._loadEmissiveProperties(extensionContext, extension, babylonMaterial); @@ -80,7 +71,7 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { } private _loadEmissiveProperties(context: string, properties: IKHRMaterialsEmissiveStrength, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts index 6c3479fa586..ad70f99ba58 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts @@ -1,6 +1,5 @@ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -22,8 +21,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_ior/README.md) */ @@ -68,38 +65,26 @@ export class KHR_materials_ior implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadIorPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); + promises.push(this._loadIorPropertiesAsync(extensionContext, extension, babylonMaterial)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material): Promise { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } - let indexOfRefraction = 1.5; if (properties.ior !== undefined) { - indexOfRefraction = properties.ior; + babylonMaterial.indexOfRefraction = properties.ior; } else { - indexOfRefraction = KHR_materials_ior._DEFAULT_IOR; - } - - if (!useOpenPBR) { - (babylonMaterial as PBRMaterial).indexOfRefraction = indexOfRefraction; + babylonMaterial.indexOfRefraction = KHR_materials_ior._DEFAULT_IOR; } return Promise.resolve(); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts index 22271fa7961..11168af02da 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts @@ -1,8 +1,6 @@ import type { Nullable } from "core/types"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; import type { Material } from "core/Materials/material"; -import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -23,8 +21,6 @@ declare module "../../glTFFileLoader" { } } -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_iridescence/README.md) */ @@ -64,48 +60,36 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { - if (useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); + promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material): Promise { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } - let iridescenceWeight = 0.0; - let iridescenceWeightTexture: Nullable = null; - let iridescenceIor = 1.3; - let iridescenceThicknessMinimum = 100; - let iridescenceThicknessMaximum = 400; - let iridescenceThicknessTexture: Nullable = null; - const promises = new Array>(); - iridescenceWeight = properties.iridescenceFactor ?? 0; - iridescenceIor = properties.iridescenceIor ?? (properties as any).iridescenceIOR ?? 1.3; - iridescenceThicknessMinimum = properties.iridescenceThicknessMinimum ?? 100; - iridescenceThicknessMaximum = properties.iridescenceThicknessMaximum ?? 400; + babylonMaterial.iridescence.isEnabled = true; + + babylonMaterial.iridescence.intensity = properties.iridescenceFactor ?? 0; + babylonMaterial.iridescence.indexOfRefraction = properties.iridescenceIor ?? (properties as any).iridescenceIOR ?? 1.3; + babylonMaterial.iridescence.minimumThickness = properties.iridescenceThicknessMinimum ?? 100; + babylonMaterial.iridescence.maximumThickness = properties.iridescenceThicknessMaximum ?? 400; if (properties.iridescenceTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/iridescenceTexture`, properties.iridescenceTexture, (texture) => { texture.name = `${babylonMaterial.name} (Iridescence)`; - iridescenceWeightTexture = texture; + babylonMaterial.iridescence.texture = texture; }) ); } @@ -114,23 +98,13 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/iridescenceThicknessTexture`, properties.iridescenceThicknessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Iridescence Thickness)`; - iridescenceThicknessTexture = texture; + babylonMaterial.iridescence.thicknessTexture = texture; }) ); } // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => { - const pbrMaterial = babylonMaterial as PBRMaterial; - pbrMaterial.iridescence.isEnabled = true; - - pbrMaterial.iridescence.intensity = iridescenceWeight; - pbrMaterial.iridescence.indexOfRefraction = iridescenceIor; - pbrMaterial.iridescence.minimumThickness = iridescenceThicknessMinimum; - pbrMaterial.iridescence.maximumThickness = iridescenceThicknessMaximum; - pbrMaterial.iridescence.texture = iridescenceWeightTexture; - pbrMaterial.iridescence.thicknessTexture = iridescenceThicknessTexture; - }); + return Promise.all(promises).then(() => {}); } } diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index 562a3b820eb..16e5f3a8509 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -16,8 +16,8 @@ import type { AnimationGroup } from "core/Animations/animationGroup"; import { Bone } from "core/Bones/bone"; import { Skeleton } from "core/Bones/skeleton"; import { Material } from "core/Materials/material"; -import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { ITextureCreationOptions } from "core/Materials/Textures/texture"; import { Texture } from "core/Materials/Textures/texture"; @@ -87,8 +87,6 @@ import { GetTypedArrayConstructor } from "core/Buffers/bufferUtils"; export { GLTFFileLoader }; -let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; - interface ILoaderProperty extends IProperty { _activeLoaderExtensionFunctions: { [id: string]: boolean; @@ -402,14 +400,6 @@ export class GLTFLoader implements IGLTFLoader { await this._loadExtensionsAsync(); - if (this.parent.useOpenPBR) { - const mod = await import("core/Materials/PBR/openPbrMaterial"); - PBRMaterialClass = mod.OpenPBRMaterial; - } else { - const mod = await import("core/Materials/PBR/pbrMaterial"); - PBRMaterialClass = mod.PBRMaterial; - } - const loadingToReadyCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.READY]}`; const loadingToCompleteCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.COMPLETE]}`; @@ -2138,42 +2128,40 @@ export class GLTFLoader implements IGLTFLoader { } private _loadMaterialMetallicRoughnessPropertiesAsync(context: string, properties: IMaterialPbrMetallicRoughness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); if (properties) { - if (this.parent.useOpenPBR) { - const mat = babylonMaterial as OpenPBRMaterial; + if (babylonMaterial instanceof OpenPBRMaterial) { if (properties.baseColorFactor) { - mat.baseColor = Color3.FromArray(properties.baseColorFactor); - mat.geometryOpacity = properties.baseColorFactor[3]; + babylonMaterial.baseColor = Color3.FromArray(properties.baseColorFactor); + babylonMaterial.geometryOpacity = properties.baseColorFactor[3]; } else { - mat.baseColor = Color3.White(); + babylonMaterial.baseColor = Color3.White(); } } else { - const mat = babylonMaterial as PBRMaterial; if (properties.baseColorFactor) { - mat.albedoColor = Color3.FromArray(properties.baseColorFactor); - mat.alpha = properties.baseColorFactor[3]; + babylonMaterial.albedoColor = Color3.FromArray(properties.baseColorFactor); + babylonMaterial.alpha = properties.baseColorFactor[3]; } else { - mat.albedoColor = Color3.White(); + babylonMaterial.albedoColor = Color3.White(); } - mat.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; - mat.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; - babylonMaterial = mat; } + babylonMaterial.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; + babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; + if (properties.baseColorTexture) { promises.push( this.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Base Color)`; - if (this.parent.useOpenPBR) { - (babylonMaterial as OpenPBRMaterial).baseColorTexture = texture; + if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.baseColorTexture = texture; } else { - (babylonMaterial as PBRMaterial).albedoTexture = texture; + babylonMaterial.albedoTexture = texture; } }) ); @@ -2184,13 +2172,13 @@ export class GLTFLoader implements IGLTFLoader { promises.push( this.loadTextureInfoAsync(`${context}/metallicRoughnessTexture`, properties.metallicRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Metallic Roughness)`; - (babylonMaterial as PBRMaterial).metallicTexture = texture; + babylonMaterial.metallicTexture = texture; }) ); - (babylonMaterial as PBRMaterial).useMetallnessFromMetallicTextureBlue = true; - (babylonMaterial as PBRMaterial).useRoughnessFromMetallicTextureGreen = true; - (babylonMaterial as PBRMaterial).useRoughnessFromMetallicTextureAlpha = false; + babylonMaterial.useMetallnessFromMetallicTextureBlue = true; + babylonMaterial.useRoughnessFromMetallicTextureGreen = true; + babylonMaterial.useRoughnessFromMetallicTextureAlpha = false; } } @@ -2253,7 +2241,12 @@ export class GLTFLoader implements IGLTFLoader { private _createDefaultMaterial(name: string, babylonDrawMode: number): Material { this._babylonScene._blockEntityCollection = !!this._assetContainer; - const babylonMaterial = new PBRMaterialClass(name, this._babylonScene); + let babylonMaterial; + if (this.parent.useOpenPBR) { + babylonMaterial = new OpenPBRMaterial(name, this._babylonScene); + } else { + babylonMaterial = new PBRMaterial(name, this._babylonScene); + } babylonMaterial._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; // Moved to mesh so user can change materials on gltf meshes: babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation; @@ -2261,7 +2254,7 @@ export class GLTFLoader implements IGLTFLoader { babylonMaterial.enableSpecularAntiAliasing = true; babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage; babylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage; - babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_OPAQUE; + babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE; babylonMaterial.metallic = 1; babylonMaterial.roughness = 1; @@ -2321,16 +2314,16 @@ export class GLTFLoader implements IGLTFLoader { * @returns A promise that resolves when the load is complete */ public loadMaterialBasePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); - if (this.parent.useOpenPBR) { - (babylonMaterial as OpenPBRMaterial).emissionColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); + if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.emissionColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); } else { - (babylonMaterial as PBRMaterial).emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); + babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); } if (material.doubleSided) { babylonMaterial.backFaceCulling = false; @@ -2390,21 +2383,21 @@ export class GLTFLoader implements IGLTFLoader { * @param babylonMaterial The Babylon material */ public loadMaterialAlphaProperties(context: string, material: IMaterial, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterialClass)) { + if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { throw new Error(`${context}: Material type not supported`); } - const baseColorTexture = this.parent.useOpenPBR ? (babylonMaterial as OpenPBRMaterial).baseColorTexture : (babylonMaterial as PBRMaterial).albedoTexture; + const baseColorTexture = babylonMaterial instanceof OpenPBRMaterial ? babylonMaterial.baseColorTexture : babylonMaterial.albedoTexture; const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE; switch (alphaMode) { case MaterialAlphaMode.OPAQUE: { - babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_OPAQUE; + babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE; babylonMaterial.alpha = 1.0; // Force alpha to 1.0 for opaque mode. break; } case MaterialAlphaMode.MASK: { - babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_ALPHATEST; + babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHATEST; babylonMaterial.alphaCutOff = material.alphaCutoff == undefined ? 0.5 : material.alphaCutoff; if (baseColorTexture) { baseColorTexture.hasAlpha = true; @@ -2412,7 +2405,7 @@ export class GLTFLoader implements IGLTFLoader { break; } case MaterialAlphaMode.BLEND: { - babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_ALPHABLEND; + babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHABLEND; if (baseColorTexture) { baseColorTexture.hasAlpha = true; babylonMaterial.useAlphaFromAlbedoTexture = true; @@ -2933,7 +2926,7 @@ export class GLTFLoader implements IGLTFLoader { return this._applyExtensions( material, "loadMaterialProperties", - (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial, this.parent.useOpenPBR) + (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial) ); } From d9b6df751c234da675dba243d99ffd7ff4422a78 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Wed, 16 Jul 2025 17:26:39 -0700 Subject: [PATCH 18/23] WIP replacing PBR props with OpenPBR props --- .vscode/settings.json | 2 +- .../core/src/Materials/PBR/openPbrMaterial.ts | 585 ++++-------------- .../ShadersInclude/openPbrUboDeclaration.fx | 27 +- .../openpbrBlockFinalColorComposition.fx | 34 + .../openpbrBlockFinalLitComponents.fx | 69 +++ .../ShadersInclude/openpbrBlockReflectance.fx | 36 ++ .../openpbrBlockReflectivity.fx | 135 ++++ .../openpbrFragmentDeclaration.fx | 147 +---- .../openpbrFragmentSamplersDeclaration.fx | 30 +- .../openpbrVertexDeclaration.fx | 19 +- .../dev/core/src/Shaders/openpbr.fragment.fx | 478 +++----------- .../dev/core/src/Shaders/openpbr.vertex.fx | 45 +- .../ShadersInclude/openPbrUboDeclaration.fx | 26 +- .../openpbrBlockFinalColorComposition.fx | 34 + .../openpbrBlockFinalLitComponents.fx | 73 +++ .../ShadersInclude/openpbrBlockReflectance.fx | 36 ++ .../openpbrBlockReflectivity.fx | 137 ++++ .../openpbrFragmentSamplersDeclaration.fx | 73 +-- .../core/src/ShadersWGSL/openpbr.fragment.fx | 459 ++------------ .../core/src/ShadersWGSL/openpbr.vertex.fx | 75 +-- .../pbrMaterialPropertyGridComponent.tsx | 94 +-- .../KHR_materials_pbrSpecularGlossiness.ts | 21 +- .../2.0/Extensions/KHR_materials_specular.ts | 76 ++- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 7 +- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 29 +- 25 files changed, 971 insertions(+), 1776 deletions(-) create mode 100644 packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalColorComposition.fx create mode 100644 packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalLitComponents.fx create mode 100644 packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockReflectance.fx create mode 100644 packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockReflectivity.fx create mode 100644 packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalColorComposition.fx create mode 100644 packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalLitComponents.fx create mode 100644 packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockReflectance.fx create mode 100644 packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockReflectivity.fx diff --git a/.vscode/settings.json b/.vscode/settings.json index 0211eae9519..76978e3d834 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -34,6 +34,6 @@ "[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "editor.formatOnSave": true, + "editor.formatOnSave": false, "jest.runMode": "on-demand" } diff --git a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts index 534ba8992c4..24486482428 100644 --- a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts @@ -3,7 +3,7 @@ import { serialize, serializeAsColor3, expandToProperty, serializeAsTexture, add import { GetEnvironmentBRDFTexture } from "../../Misc/brdfTextureTools"; import type { Nullable } from "../../types"; import { Scene } from "../../scene"; -import { Color3, Color4, TmpColors } from "../../Maths/math.color"; +import { Color3, Color4 } from "../../Maths/math.color"; import { ImageProcessingConfiguration } from "../imageProcessingConfiguration"; import type { BaseTexture } from "../../Materials/Textures/baseTexture"; import { PBRBaseMaterial } from "./pbrBaseMaterial"; @@ -176,7 +176,7 @@ class Sampler { * - openpbr.fragment.fx */ public get samplerInfoName(): string { - return this.samplerPrefix + "Infos"; + return "v" + this.samplerPrefix.charAt(0).toUpperCase() + this.samplerPrefix.slice(1) + "Infos"; } /** * The name of the matrix used for this sampler in the shader. @@ -213,16 +213,8 @@ export class OpenPBRMaterialDefines extends ImageProcessingDefinesMixin(OpenPBRM public REALTIME_FILTERING = false; public IBL_CDF_FILTERING = false; - public ALBEDO = false; - public GAMMAALBEDO = false; - public ALBEDODIRECTUV = 0; public VERTEXCOLOR = false; - public BASE_WEIGHT = false; - public BASE_WEIGHTDIRECTUV = 0; - public BASE_DIFFUSE_ROUGHNESS = false; - public BASE_DIFFUSE_ROUGHNESSDIRECTUV = 0; - public BAKED_VERTEX_ANIMATION_TEXTURE = false; public AMBIENT = false; @@ -238,17 +230,12 @@ export class OpenPBRMaterialDefines extends ImageProcessingDefinesMixin(OpenPBRM public ALPHABLEND = false; public ALPHAFROMALBEDO = false; public ALPHATESTVALUE = "0.5"; - public SPECULAROVERALPHA = false; - public RADIANCEOVERALPHA = false; - public ALPHAFRESNEL = false; - public LINEARALPHAFRESNEL = false; public PREMULTIPLYALPHA = false; public EMISSIVE = false; public EMISSIVEDIRECTUV = 0; public GAMMAEMISSIVE = false; - public REFLECTIVITY = false; public REFLECTIVITY_GAMMA = false; public REFLECTIVITYDIRECTUV = 0; public SPECULARTERM = false; @@ -256,21 +243,13 @@ export class OpenPBRMaterialDefines extends ImageProcessingDefinesMixin(OpenPBRM public MICROSURFACEFROMREFLECTIVITYMAP = false; public MICROSURFACEAUTOMATIC = false; public LODBASEDMICROSFURACE = false; - public MICROSURFACEMAP = false; - public MICROSURFACEMAPDIRECTUV = 0; public METALLICWORKFLOW = true; public ROUGHNESSSTOREINMETALMAPALPHA = false; public ROUGHNESSSTOREINMETALMAPGREEN = false; public METALLNESSSTOREINMETALMAPBLUE = false; public AOSTOREINMETALMAPRED = false; - public METALLIC_REFLECTANCE = false; - public METALLIC_REFLECTANCE_GAMMA = false; - public METALLIC_REFLECTANCEDIRECTUV = 0; - public METALLIC_REFLECTANCE_USE_ALPHA_ONLY = false; - public REFLECTANCE = false; - public REFLECTANCE_GAMMA = false; - public REFLECTANCEDIRECTUV = 0; + public SPECULAR_WEIGHT_USE_ALPHA_ONLY = false; public ENVIRONMENTBRDF = false; public ENVIRONMENTBRDF_RGBD = false; @@ -524,6 +503,78 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { // eslint-disable-next-line @typescript-eslint/no-unused-vars private _baseDiffuseRoughnessTexture: Sampler = new Sampler("base_diffuse_roughness", "baseDiffuseRoughness", "BASE_DIFFUSE_ROUGHNESS"); + /** + * Metalness of the base lobe. + * See OpenPBR's specs for base_metalness + */ + public baseMetalness: number; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "baseMetalness") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _baseMetalness: Property = new Property("base_metalness", 0, "vReflectanceInfo", 4, 0); + + /** + * Weight of the specular lobe. + * See OpenPBR's specs for specular_weight + */ + public specularWeight: number; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "specularWeight") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _specularWeight: Property = new Property("specular_weight", 1, "vReflectanceInfo", 4, 3); + + /** + * Roughness of the diffuse lobe. + * See OpenPBR's specs for base_diffuse_roughness + */ + public specularWeightTexture: BaseTexture; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "specularWeightTexture") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _specularWeightTexture: Sampler = new Sampler("specular_weight", "specularWeight", "SPECULAR_WEIGHT"); + + /** + * Color of the specular lobe. + * See OpenPBR's specs for specular_color + */ + public specularColor: Color3; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "specularColor") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _specularColor: Property = new Property("specular_color", Color3.White(), "vSpecularColor", 4); + + /** + * Specular Color Texture property. + * See OpenPBR's specs for specular_color + */ + public specularColorTexture: BaseTexture; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "specularColorTexture") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _specularColorTexture: Sampler = new Sampler("specular_color", "specularColor", "SPECULAR_COLOR"); + + /** + * Roughness of the specular lobe. + * See OpenPBR's specs for specular_roughness + */ + public specularRoughness: number; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "specularRoughness") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _specularRoughness: Property = new Property("specular_roughness", 0, "vReflectanceInfo", 4, 1); + + /** + * IOR of the specular lobe. + * See OpenPBR's specs for specular_roughness + */ + public specularIor: number; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "specularIor") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _specularIor: Property = new Property("specular_ior", 1.5, "vReflectanceInfo", 4, 2); + + /** + * Metalness and Roughness texture. + * See OpenPBR's specs for base_metalness and specular_roughness + */ + public baseMetalRoughTexture: BaseTexture; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "baseMetalRoughTexture") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _baseMetalRoughTexture: Sampler = new Sampler("base_metalness_specular_roughness", "baseMetalRough", "METALLIC_ROUGHNESS"); + /** * Defines the opacity of the material's geometry. See OpenPBR's specs for geometry_opacity */ @@ -543,6 +594,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { private _propertyList: { [name: string]: Property }; private _uniformsList: { [name: string]: Uniform } = {}; private _samplersList: { [name: string]: Sampler } = {}; + private _samplerDefines: { [name: string]: { type: string; default: any } } = {}; /** * Intensity of the direct lights e.g. the four lights available in your scene. @@ -620,95 +672,11 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { public emissiveTexture: Nullable; /** - * AKA Specular texture in other nomenclature. - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public reflectivityTexture: Nullable; - - /** - * Used to switch from specular/glossiness to metallic/roughness workflow. - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public metallicTexture: Nullable; - - /** - * Specifies the metallic scalar of the metallic/roughness workflow. - * Can also be used to scale the metalness values of the metallic texture. - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public metallic: Nullable; - - /** - * Specifies the roughness scalar of the metallic/roughness workflow. - * Can also be used to scale the roughness values of the metallic texture. + * Specifies that the specular weight is stored in the alpha channel of the specular weight texture. */ @serialize() @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public roughness: Nullable; - - /** - * In metallic workflow, specifies an F0 factor to help configuring the material F0. - * By default the indexOfrefraction is used to compute F0; - * - * This is used as a factor against the default reflectance at normal incidence to tweak it. - * - * F0 = defaultF0 * metallicF0Factor * metallicReflectanceColor; - * F90 = metallicReflectanceColor; - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public metallicF0Factor = 1; - - /** - * In metallic workflow, specifies an F0 color. - * By default the F90 is always 1; - * - * Please note that this factor is also used as a factor against the default reflectance at normal incidence. - * - * F0 = defaultF0_from_IOR * metallicF0Factor * metallicReflectanceColor - * F90 = metallicF0Factor; - */ - @serializeAsColor3() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public metallicReflectanceColor = Color3.White(); - - /** - * Specifies that only the A channel from metallicReflectanceTexture should be used. - * If false, both RGB and A channels will be used - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public useOnlyMetallicFromMetallicReflectanceTexture = false; - - /** - * Defines to store metallicReflectanceColor in RGB and metallicF0Factor in A - * This is multiplied against the scalar values defined in the material. - * If useOnlyMetallicFromMetallicReflectanceTexture is true, don't use the RGB channels, only A - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public metallicReflectanceTexture: Nullable; - - /** - * Defines to store reflectanceColor in RGB - * This is multiplied against the scalar values defined in the material. - * If both reflectanceTexture and metallicReflectanceTexture textures are provided and useOnlyMetallicFromMetallicReflectanceTexture - * is false, metallicReflectanceTexture takes priority and reflectanceTexture is not used - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public reflectanceTexture: Nullable; - - /** - * Used to enable roughness/glossiness fetch from a separate channel depending on the current mode. - * Gray Scale represents roughness in metallic mode and glossiness in specular mode. - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public microSurfaceTexture: Nullable; + public useSpecularWeightFromTextureAlpha = false; /** * Stores surface normal data used to displace a mesh in a texture. @@ -745,13 +713,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public reflectionColor = new Color3(1.0, 1.0, 1.0); - /** - * AKA Glossiness in other nomenclature. - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public microSurface = 1.0; - /** * If true, the light map contains occlusion information instead of lighting info. */ @@ -795,28 +756,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public useMicroSurfaceFromReflectivityMapAlpha = false; - /** - * Specifies if the metallic texture contains the roughness information in its alpha channel. - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public useRoughnessFromMetallicTextureAlpha = true; - - /** - * Specifies if the metallic texture contains the roughness information in its green channel. - * Needs useRoughnessFromMetallicTextureAlpha to be false. - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public useRoughnessFromMetallicTextureGreen = false; - - /** - * Specifies if the metallic texture contains the metallness information in its blue channel. - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public useMetallnessFromMetallicTextureBlue = false; - /** * Specifies if the metallic texture contains the ambient occlusion information in its red channel. */ @@ -1137,85 +1076,12 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { */ public _emissiveTexture: Nullable = null; - /** - * AKA Specular texture in other nomenclature. - * @internal - */ - public _reflectivityTexture: Nullable = null; - - /** - * Used to switch from specular/glossiness to metallic/roughness workflow. - * @internal - */ - public _metallicTexture: Nullable = null; - - /** - * Specifies the metallic scalar of the metallic/roughness workflow. - * Can also be used to scale the metalness values of the metallic texture. - * @internal - */ - public _metallic: Nullable = null; - - /** - * Specifies the roughness scalar of the metallic/roughness workflow. - * Can also be used to scale the roughness values of the metallic texture. - * @internal - */ - public _roughness: Nullable = null; - - /** - * In metallic workflow, specifies an F0 factor to help configuring the material F0. - * By default the indexOfrefraction is used to compute F0; - * - * This is used as a factor against the default reflectance at normal incidence to tweak it. - * - * F0 = defaultF0 * metallicF0Factor * metallicReflectanceColor; - * F90 = metallicReflectanceColor; - * @internal - */ - public _metallicF0Factor = 1; - - /** - * In metallic workflow, specifies an F0 color. - * By default the F90 is always 1; - * - * Please note that this factor is also used as a factor against the default reflectance at normal incidence. - * - * F0 = defaultF0_from_IOR * metallicF0Factor * metallicReflectanceColor - * F90 = metallicF0Factor; - * @internal - */ - public _metallicReflectanceColor = Color3.White(); - /** * Specifies that only the A channel from _metallicReflectanceTexture should be used. * If false, both RGB and A channels will be used * @internal */ - public _useOnlyMetallicFromMetallicReflectanceTexture = false; - - /** - * Defines to store metallicReflectanceColor in RGB and metallicF0Factor in A - * This is multiply against the scalar values defined in the material. - * @internal - */ - public _metallicReflectanceTexture: Nullable = null; - - /** - * Defines to store reflectanceColor in RGB - * This is multiplied against the scalar values defined in the material. - * If both _reflectanceTexture and _metallicReflectanceTexture textures are provided and _useOnlyMetallicFromMetallicReflectanceTexture - * is false, _metallicReflectanceTexture takes precedence and _reflectanceTexture is not used - * @internal - */ - public _reflectanceTexture: Nullable = null; - - /** - * Used to enable roughness/glossiness fetch from a separate channel depending on the current mode. - * Gray Scale represents roughness in metallic mode and glossiness in specular mode. - * @internal - */ - public _microSurfaceTexture: Nullable = null; + public _useSpecularWeightFromTextureAlpha = false; /** * Stores surface normal data used to displace a mesh in a texture. @@ -1247,12 +1113,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { */ public _reflectionColor = new Color3(1, 1, 1); - /** - * AKA Glossiness in other nomenclature. - * @internal - */ - public _microSurface = 0.9; - /** * Specifies that the material will use the light map as a show map. * @internal @@ -1292,24 +1152,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { */ public _useMicroSurfaceFromReflectivityMapAlpha = false; - /** - * Specifies if the metallic texture contains the roughness information in its alpha channel. - * @internal - */ - public _useRoughnessFromMetallicTextureAlpha = true; - - /** - * Specifies if the metallic texture contains the roughness information in its green channel. - * @internal - */ - public _useRoughnessFromMetallicTextureGreen = false; - - /** - * Specifies if the metallic texture contains the metallness information in its blue channel. - * @internal - */ - public _useMetallnessFromMetallicTextureBlue = false; - /** * Specifies if the metallic texture contains the ambient occlusion information in its red channel. * @internal @@ -1597,6 +1439,15 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } + // For each sampler in _samplersList, add defines to be added to OpenPBRMaterialDefines + for (const samplerKey in this._samplersList) { + const sampler = this._samplersList[samplerKey]; + const defineName = sampler.textureDefine; + this._samplerDefines[defineName] = { type: "boolean", default: false }; + this._samplerDefines[defineName + "DIRECTUV"] = { type: "number", default: 0 }; + this._samplerDefines[defineName + "_GAMMA"] = { type: "boolean", default: false }; + } + // Arg. Why do I have to add these references to get rid of the linting errors? this._baseWeight; this._baseWeightTexture; @@ -1604,6 +1455,14 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { this._baseColorTexture; this._baseDiffuseRoughness; this._baseDiffuseRoughnessTexture; + this._baseMetalness; + this._specularWeight; + this._specularWeightTexture; + this._specularColor; + this._specularColorTexture; + this._specularRoughness; + this._specularIor; + this._baseMetalRoughTexture; this._geometryOpacity; this._emissionColor; } @@ -1753,7 +1612,11 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { if (this._breakShaderLoadedCheck) { return; } - const defines = new OpenPBRMaterialDefines(this._eventInfo.defineNames); + + const defines = new OpenPBRMaterialDefines({ + ...(this._eventInfo.defineNames || {}), + ...(this._samplerDefines || {}), + }); const effect = this._prepareEffect(mesh, defines, undefined, undefined, localOptions.useInstances, localOptions.clipPlane, mesh.hasThinInstances)!; if (this._onEffectCreatedObservable) { onCreatedEffectParameters.effect = effect; @@ -1797,7 +1660,10 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { if (!subMesh.materialDefines) { this._callbackPluginEventGeneric(MaterialPluginEvent.GetDefineNames, this._eventInfo); - subMesh.materialDefines = new OpenPBRMaterialDefines(this._eventInfo.defineNames); + subMesh.materialDefines = new OpenPBRMaterialDefines({ + ...(this._eventInfo.defineNames || {}), + ...(this._samplerDefines || {}), + }); } const defines = subMesh.materialDefines; @@ -1835,7 +1701,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - const reflectionTexture = this._getReflectionTexture2(); + const reflectionTexture = this._getReflectionTexture(); if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { if (!reflectionTexture.isReadyOrNotBlocking()) { return false; @@ -1864,36 +1730,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - if (MaterialFlags.SpecularTextureEnabled) { - if (this._metallicTexture) { - if (!this._metallicTexture.isReadyOrNotBlocking()) { - return false; - } - } else if (this._reflectivityTexture) { - if (!this._reflectivityTexture.isReadyOrNotBlocking()) { - return false; - } - } - - if (this._metallicReflectanceTexture) { - if (!this._metallicReflectanceTexture.isReadyOrNotBlocking()) { - return false; - } - } - - if (this._reflectanceTexture) { - if (!this._reflectanceTexture.isReadyOrNotBlocking()) { - return false; - } - } - - if (this._microSurfaceTexture) { - if (!this._microSurfaceTexture.isReadyOrNotBlocking()) { - return false; - } - } - } - if (engine.getCaps().standardDerivatives && this._bumpTexture && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { // Bump texture cannot be not blocking. if (!this._bumpTexture.isReady()) { @@ -1993,32 +1829,21 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { ubo.addUniform("vOpacityInfos", 2); ubo.addUniform("vEmissiveInfos", 2); ubo.addUniform("vLightmapInfos", 2); - ubo.addUniform("vReflectivityInfos", 3); - ubo.addUniform("vMicroSurfaceSamplerInfos", 2); ubo.addUniform("vBumpInfos", 3); ubo.addUniform("ambientMatrix", 16); ubo.addUniform("opacityMatrix", 16); ubo.addUniform("emissiveMatrix", 16); ubo.addUniform("lightmapMatrix", 16); - ubo.addUniform("reflectivityMatrix", 16); - ubo.addUniform("microSurfaceSamplerMatrix", 16); ubo.addUniform("bumpMatrix", 16); ubo.addUniform("vTangentSpaceParams", 2); ubo.addUniform("vLightingIntensity", 4); ubo.addUniform("pointSize", 1); - ubo.addUniform("vReflectivityColor", 4); // ubo.addUniform("vEmissiveColor", 3); ubo.addUniform("vAmbientColor", 3); ubo.addUniform("vDebugMode", 2); - ubo.addUniform("vMetallicReflectanceFactors", 4); - ubo.addUniform("vMetallicReflectanceInfos", 2); - ubo.addUniform("metallicReflectanceMatrix", 16); - ubo.addUniform("vReflectanceInfos", 2); - ubo.addUniform("reflectanceMatrix", 16); - ubo.addUniform("cameraInfo", 4); PrepareUniformLayoutForIBL(ubo, true, true, true, true, true); @@ -2134,31 +1959,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { BindTextureMatrix(this._lightmapTexture, ubo, "lightmap"); } - if (MaterialFlags.SpecularTextureEnabled) { - if (this._metallicTexture) { - ubo.updateFloat3("vReflectivityInfos", this._metallicTexture.coordinatesIndex, this._metallicTexture.level, this._ambientTextureStrength); - BindTextureMatrix(this._metallicTexture, ubo, "reflectivity"); - } else if (this._reflectivityTexture) { - ubo.updateFloat3("vReflectivityInfos", this._reflectivityTexture.coordinatesIndex, this._reflectivityTexture.level, 1.0); - BindTextureMatrix(this._reflectivityTexture, ubo, "reflectivity"); - } - - if (this._metallicReflectanceTexture) { - ubo.updateFloat2("vMetallicReflectanceInfos", this._metallicReflectanceTexture.coordinatesIndex, this._metallicReflectanceTexture.level); - BindTextureMatrix(this._metallicReflectanceTexture, ubo, "metallicReflectance"); - } - - if (this._reflectanceTexture && defines.REFLECTANCE) { - ubo.updateFloat2("vReflectanceInfos", this._reflectanceTexture.coordinatesIndex, this._reflectanceTexture.level); - BindTextureMatrix(this._reflectanceTexture, ubo, "reflectance"); - } - - if (this._microSurfaceTexture) { - ubo.updateFloat2("vMicroSurfaceSamplerInfos", this._microSurfaceTexture.coordinatesIndex, this._microSurfaceTexture.level); - BindTextureMatrix(this._microSurfaceTexture, ubo, "microSurfaceSampler"); - } - } - if (this._bumpTexture && engine.getCaps().standardDerivatives && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { ubo.updateFloat3("vBumpInfos", this._bumpTexture.coordinatesIndex, this._bumpTexture.level, this._parallaxScaleBias); BindTextureMatrix(this._bumpTexture, ubo, "bump"); @@ -2178,22 +1978,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { ubo.updateFloat("pointSize", this.pointSize); } - // Colors - if (defines.METALLICWORKFLOW) { - TmpColors.Color4[0].r = this._metallic === undefined || this._metallic === null ? 1 : this._metallic; - TmpColors.Color4[0].g = this._roughness === undefined || this._roughness === null ? 1 : this._roughness; - const ior = 1.5; - const outsideIOR = 1; // consider air as clear coat and other layers would remap in the shader. - TmpColors.Color4[0].b = ior; - // We are here deriving our default reflectance from a common value for none metallic surface. - // Based of the schlick fresnel approximation model - // for dielectrics. - const f0 = Math.pow((ior - outsideIOR) / (ior + outsideIOR), 2); - TmpColors.Color4[0].a = f0; - ubo.updateDirectColor4("vReflectivityColor", TmpColors.Color4[0]); - ubo.updateColor4("vMetallicReflectanceFactors", this._metallicReflectanceColor, this._metallicF0Factor); - } - // ubo.updateColor3("vEmissiveColor", MaterialFlags.EmissiveTextureEnabled ? this._emissiveColor : Color3.BlackReadOnly); Object.values(this._uniformsList).forEach((uniform) => { @@ -2260,26 +2044,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { ubo.setTexture("lightmapSampler", this._lightmapTexture); } - if (MaterialFlags.SpecularTextureEnabled) { - if (this._metallicTexture) { - ubo.setTexture("reflectivitySampler", this._metallicTexture); - } else if (this._reflectivityTexture) { - ubo.setTexture("reflectivitySampler", this._reflectivityTexture); - } - - if (this._metallicReflectanceTexture) { - ubo.setTexture("metallicReflectanceSampler", this._metallicReflectanceTexture); - } - - if (this._reflectanceTexture && defines.REFLECTANCE) { - ubo.setTexture("reflectanceSampler", this._reflectanceTexture); - } - - if (this._microSurfaceTexture) { - ubo.setTexture("microSurfaceSampler", this._microSurfaceTexture); - } - } - if (this._bumpTexture && engine.getCaps().standardDerivatives && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { ubo.setTexture("bumpSampler", this._bumpTexture); } @@ -2368,12 +2132,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { results.push(this._emissiveTexture); } - if (this._metallicTexture && this._metallicTexture.animations && this._metallicTexture.animations.length > 0) { - results.push(this._metallicTexture); - } else if (this._reflectivityTexture && this._reflectivityTexture.animations && this._reflectivityTexture.animations.length > 0) { - results.push(this._reflectivityTexture); - } - if (this._bumpTexture && this._bumpTexture.animations && this._bumpTexture.animations.length > 0) { results.push(this._bumpTexture); } @@ -2382,18 +2140,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { results.push(this._lightmapTexture); } - if (this._metallicReflectanceTexture && this._metallicReflectanceTexture.animations && this._metallicReflectanceTexture.animations.length > 0) { - results.push(this._metallicReflectanceTexture); - } - - if (this._reflectanceTexture && this._reflectanceTexture.animations && this._reflectanceTexture.animations.length > 0) { - results.push(this._reflectanceTexture); - } - - if (this._microSurfaceTexture && this._microSurfaceTexture.animations && this._microSurfaceTexture.animations.length > 0) { - results.push(this._microSurfaceTexture); - } - return results; } @@ -2428,26 +2174,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { activeTextures.push(this._emissiveTexture); } - if (this._reflectivityTexture) { - activeTextures.push(this._reflectivityTexture); - } - - if (this._metallicTexture) { - activeTextures.push(this._metallicTexture); - } - - if (this._metallicReflectanceTexture) { - activeTextures.push(this._metallicReflectanceTexture); - } - - if (this._reflectanceTexture) { - activeTextures.push(this._reflectanceTexture); - } - - if (this._microSurfaceTexture) { - activeTextures.push(this._microSurfaceTexture); - } - if (this._bumpTexture) { activeTextures.push(this._bumpTexture); } @@ -2493,26 +2219,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { return true; } - if (this._reflectivityTexture === texture) { - return true; - } - - if (this._metallicTexture === texture) { - return true; - } - - if (this._metallicReflectanceTexture === texture) { - return true; - } - - if (this._reflectanceTexture === texture) { - return true; - } - - if (this._microSurfaceTexture === texture) { - return true; - } - if (this._bumpTexture === texture) { return true; } @@ -2556,13 +2262,8 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { this._opacityTexture?.dispose(); this._reflectionTexture?.dispose(); this._emissiveTexture?.dispose(); - this._metallicTexture?.dispose(); - this._reflectivityTexture?.dispose(); this._bumpTexture?.dispose(); this._lightmapTexture?.dispose(); - this._metallicReflectanceTexture?.dispose(); - this._reflectanceTexture?.dispose(); - this._microSurfaceTexture?.dispose(); } this._renderTargets.dispose(); @@ -2724,7 +2425,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { "vEyePosition", "vLightsType", "vAmbientColor", - "vReflectivityColor", "vMetallicReflectanceFactors", "visibility", "vFogInfos", @@ -2734,10 +2434,8 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { "vAmbientInfos", "vOpacityInfos", "vEmissiveInfos", - "vReflectivityInfos", "vMetallicReflectanceInfos", "vReflectanceInfos", - "vMicroSurfaceSamplerInfos", "vBumpInfos", "vLightmapInfos", "mBones", @@ -2745,9 +2443,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { "ambientMatrix", "opacityMatrix", "emissiveMatrix", - "reflectivityMatrix", "normalMatrix", - "microSurfaceSamplerMatrix", "bumpMatrix", "lightmapMatrix", "metallicReflectanceMatrix", @@ -2773,7 +2469,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { "bumpSampler", "lightmapSampler", "opacitySampler", - "microSurfaceSampler", "environmentBrdfSampler", "boneSampler", "metallicReflectanceSampler", @@ -2904,14 +2599,10 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { defines["MAINUV" + i] = false; } if (scene.texturesEnabled) { - defines.ALBEDODIRECTUV = 0; - defines.BASE_WEIGHTDIRECTUV = 0; - defines.BASE_DIFFUSE_ROUGHNESSDIRECTUV = 0; defines.AMBIENTDIRECTUV = 0; defines.OPACITYDIRECTUV = 0; defines.EMISSIVEDIRECTUV = 0; defines.REFLECTIVITYDIRECTUV = 0; - defines.MICROSURFACEMAPDIRECTUV = 0; defines.METALLIC_REFLECTANCEDIRECTUV = 0; defines.REFLECTANCEDIRECTUV = 0; defines.BUMPDIRECTUV = 0; @@ -2924,10 +2615,9 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { // TODO - loop through samplers and prepare defines for each texture for (const key in this._samplersList) { const sampler = this._samplersList[key]; - defines[sampler.textureDefine + "DIRECTUV"] = 0; if (sampler.value) { PrepareDefinesForMergedUV(sampler.value, defines, sampler.textureDefine); - defines["GAMMA" + sampler.textureDefine] = sampler.value.gammaSpace; + defines[sampler.textureDefine + "_GAMMA"] = sampler.value.gammaSpace; } else { defines[sampler.textureDefine] = false; } @@ -2947,7 +2637,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { defines.OPACITY = false; } - const reflectionTexture = this._getReflectionTexture2(); + const reflectionTexture = this._getReflectionTexture(); const useSHInFragment: boolean = this._forceIrradianceInFragment || this.realTimeFiltering || @@ -2973,52 +2663,11 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } if (MaterialFlags.SpecularTextureEnabled) { - if (this._metallicTexture) { - PrepareDefinesForMergedUV(this._metallicTexture, defines, "REFLECTIVITY"); - defines.ROUGHNESSSTOREINMETALMAPALPHA = this._useRoughnessFromMetallicTextureAlpha; - defines.ROUGHNESSSTOREINMETALMAPGREEN = !this._useRoughnessFromMetallicTextureAlpha && this._useRoughnessFromMetallicTextureGreen; - defines.METALLNESSSTOREINMETALMAPBLUE = this._useMetallnessFromMetallicTextureBlue; + if (this._baseMetalRoughTexture) { defines.AOSTOREINMETALMAPRED = this._useAmbientOcclusionFromMetallicTextureRed; - defines.REFLECTIVITY_GAMMA = false; - } else if (this._reflectivityTexture) { - PrepareDefinesForMergedUV(this._reflectivityTexture, defines, "REFLECTIVITY"); - defines.MICROSURFACEFROMREFLECTIVITYMAP = this._useMicroSurfaceFromReflectivityMapAlpha; - defines.MICROSURFACEAUTOMATIC = this._useAutoMicroSurfaceFromReflectivityMap; - defines.REFLECTIVITY_GAMMA = this._reflectivityTexture.gammaSpace; - } else { - defines.REFLECTIVITY = false; - } - - if (this._metallicReflectanceTexture || this._reflectanceTexture) { - defines.METALLIC_REFLECTANCE_USE_ALPHA_ONLY = this._useOnlyMetallicFromMetallicReflectanceTexture; - if (this._metallicReflectanceTexture) { - PrepareDefinesForMergedUV(this._metallicReflectanceTexture, defines, "METALLIC_REFLECTANCE"); - defines.METALLIC_REFLECTANCE_GAMMA = this._metallicReflectanceTexture.gammaSpace; - } else { - defines.METALLIC_REFLECTANCE = false; - } - if ( - this._reflectanceTexture && - (!this._metallicReflectanceTexture || (this._metallicReflectanceTexture && this._useOnlyMetallicFromMetallicReflectanceTexture)) - ) { - PrepareDefinesForMergedUV(this._reflectanceTexture, defines, "REFLECTANCE"); - defines.REFLECTANCE_GAMMA = this._reflectanceTexture.gammaSpace; - } else { - defines.REFLECTANCE = false; - } - } else { - defines.METALLIC_REFLECTANCE = false; - defines.REFLECTANCE = false; } - if (this._microSurfaceTexture) { - PrepareDefinesForMergedUV(this._microSurfaceTexture, defines, "MICROSURFACEMAP"); - } else { - defines.MICROSURFACEMAP = false; - } - } else { - defines.REFLECTIVITY = false; - defines.MICROSURFACEMAP = false; + defines.SPECULAR_WEIGHT_USE_ALPHA_ONLY = this._useSpecularWeightFromTextureAlpha; } if (engine.getCaps().standardDerivatives && this._bumpTexture && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { @@ -3087,8 +2736,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { defines.ALPHATESTVALUE = `${this._alphaCutOff}${this._alphaCutOff % 1 === 0 ? "." : ""}`; defines.PREMULTIPLYALPHA = this.alphaMode === Constants.ALPHA_PREMULTIPLIED || this.alphaMode === Constants.ALPHA_PREMULTIPLIED_PORTERDUFF; defines.ALPHABLEND = this.needAlphaBlendingForMesh(mesh); - defines.ALPHAFRESNEL = this._useAlphaFresnel || this._useLinearAlphaFresnel; - defines.LINEARALPHAFRESNEL = this._useLinearAlphaFresnel; } if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) { @@ -3131,18 +2778,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { // External config this._callbackPluginEventPrepareDefines(this._eventInfo); } - - /** - * Returns the texture used for reflections. - * @returns - Reflection texture if present. Otherwise, returns the environment texture. - */ - private _getReflectionTexture2(): Nullable { - if (this._reflectionTexture) { - return this._reflectionTexture; - } - - return this.getScene().environmentTexture; - } } RegisterClass("BABYLON.OpenPBRMaterial", OpenPBRMaterial); diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx index f3f6fd2f887..1d1cf2e74b2 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx @@ -27,30 +27,20 @@ uniform Material { vec2 vOpacityInfos; vec2 vEmissiveInfos; vec2 vLightmapInfos; - vec3 vReflectivityInfos; - vec2 vMicroSurfaceSamplerInfos; vec3 vBumpInfos; mat4 ambientMatrix; mat4 opacityMatrix; mat4 emissiveMatrix; mat4 lightmapMatrix; - mat4 reflectivityMatrix; - mat4 microSurfaceSamplerMatrix; mat4 bumpMatrix; vec2 vTangentSpaceParams; vec4 vLightingIntensity; float pointSize; - vec4 vReflectivityColor; vec3 vAmbientColor; vec2 vDebugMode; - vec4 vMetallicReflectanceFactors; - vec2 vMetallicReflectanceInfos; - mat4 metallicReflectanceMatrix; - vec2 vReflectanceInfos; - mat4 reflectanceMatrix; vec4 cameraInfo; vec2 vReflectionInfos; @@ -84,15 +74,24 @@ uniform Material { float baseWeight; vec4 vBaseColor; - float baseDiffuseRoughness; + float vBaseDiffuseRoughness; + vec4 vReflectanceInfo; + vec4 vSpecularColor; vec3 vEmissiveColor; - vec2 baseWeightInfos; + vec2 vBaseWeightInfos; mat4 baseWeightMatrix; - vec2 baseColorInfos; + vec2 vBaseColorInfos; mat4 baseColorMatrix; - vec2 baseDiffuseRoughnessInfos; + vec2 vBaseDiffuseRoughnessInfos; mat4 baseDiffuseRoughnessMatrix; + vec2 vBaseMetalRoughInfos; + mat4 baseMetalRoughMatrix; + vec2 vSpecularWeightInfos; + mat4 specularWeightMatrix; + vec2 vSpecularColorInfos; + mat4 specularColorMatrix; + #define ADDITIONAL_UBO_DECLARATION }; diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalColorComposition.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalColorComposition.fx new file mode 100644 index 00000000000..e0a0d3613df --- /dev/null +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalColorComposition.fx @@ -0,0 +1,34 @@ +vec4 finalColor = vec4( +#ifndef UNLIT + #ifdef REFLECTION + finalIrradiance + + #endif + #ifdef SPECULARTERM + finalSpecularScaled + + #endif + #ifdef REFLECTION + finalRadianceScaled + + #endif +#endif + finalAmbient + + finalDiffuse, + alpha); + +// _____________________________ LightMappping _____________________________________ +#ifdef LIGHTMAP + #ifndef LIGHTMAPEXCLUDED + #ifdef USELIGHTMAPASSHADOWMAP + finalColor.rgb *= lightmapColor.rgb; + #else + finalColor.rgb += lightmapColor.rgb; + #endif + #endif +#endif + +// _____________________________ EmissiveLight _____________________________________ +finalColor.rgb += finalEmissive; + +#define CUSTOM_FRAGMENT_BEFORE_FOG + +// _____________________________ Finally ___________________________________________ +finalColor = max(finalColor, 0.0); diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalLitComponents.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalLitComponents.fx new file mode 100644 index 00000000000..8dcb78aa4f0 --- /dev/null +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalLitComponents.fx @@ -0,0 +1,69 @@ +aggShadow = aggShadow / numLights; + +// ______________________________________________________________________________ +// _____________________________ Energy Conservation ___________________________ +// Apply Energy Conservation. +// _____________________________ IBL BRDF + Energy Cons ________________________________ +#if defined(ENVIRONMENTBRDF) + #ifdef MS_BRDF_ENERGY_CONSERVATION + vec3 baseSpecularEnergyConservationFactor = getEnergyConservationFactor(vec3(reflectanceF0), environmentBrdf); + vec3 coloredEnergyConservationFactor = getEnergyConservationFactor(specularEnvironmentR0, environmentBrdf); + #endif +#endif + +// _____________________________ Irradiance ______________________________________ +#ifdef REFLECTION + vec3 finalIrradiance = reflectionOut.environmentIrradiance; + + // Account for energy loss due to specular reflectance + vec3 baseSpecularEnergy = vec3(baseSpecularEnvironmentReflectance); + #if defined(ENVIRONMENTBRDF) + #ifdef MS_BRDF_ENERGY_CONSERVATION + baseSpecularEnergy *= baseSpecularEnergyConservationFactor; + #endif + #endif + finalIrradiance *= clamp(vec3(1.0) - baseSpecularEnergy, 0.0, 1.0); + finalIrradiance *= vLightingIntensity.z; + finalIrradiance *= surfaceAlbedo.rgb; + finalIrradiance *= aoOut.ambientOcclusionColor; +#endif + +// _____________________________ Specular ________________________________________ +#ifdef SPECULARTERM + vec3 finalSpecular = specularBase; + finalSpecular = max(finalSpecular, 0.0); + + vec3 finalSpecularScaled = finalSpecular * vLightingIntensity.x * vLightingIntensity.w; + + #if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION) + finalSpecularScaled *= coloredEnergyConservationFactor; + #endif +#endif + +// _____________________________ Radiance ________________________________________ +#ifdef REFLECTION + vec3 finalRadiance = reflectionOut.environmentRadiance.rgb; + finalRadiance *= colorSpecularEnvironmentReflectance; + + vec3 finalRadianceScaled = finalRadiance * vLightingIntensity.z; + + #if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION) + finalRadianceScaled *= coloredEnergyConservationFactor; + #endif +#endif + +// _____________________________ Highlights on Alpha _____________________________ +#ifdef ALPHABLEND + float luminanceOverAlpha = 0.0; + #if defined(REFLECTION) && defined(RADIANCEOVERALPHA) + luminanceOverAlpha += getLuminance(finalRadianceScaled); + #endif + + #if defined(SPECULARTERM) && defined(SPECULAROVERALPHA) + luminanceOverAlpha += getLuminance(finalSpecularScaled); + #endif + + #if defined(RADIANCEOVERALPHA) || defined(SPECULAROVERALPHA) + alpha = saturate(alpha + luminanceOverAlpha * luminanceOverAlpha); + #endif +#endif diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockReflectance.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockReflectance.fx new file mode 100644 index 00000000000..af4db665973 --- /dev/null +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockReflectance.fx @@ -0,0 +1,36 @@ +#if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX) + // "Base" specular reflectance is the amount of light prevented from penetrating the diffuse surface by the specular lobe. + // For dielectric materials, this is a greyscale value derived from the IOR and the maximum component of the specular colour. + // For metallic materials, this is vec3(1.0). i.e. no light penetrates to the diffuse surface. + vec3 baseSpecularEnvironmentReflectance = getReflectanceFromBRDFLookup(vec3(reflectanceF0), reflectivityOut.reflectanceF90, environmentBrdf); + + #if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR) + // For OpenPBR, we use a different specular lobe for metallic materials and then blend based on metalness. However, + // to do this correctly, we really need reflectivityOut to contain separate F0 and F90 values for purely dielectric + // and purely metal. Instead, the values are already a mix of dielectric and metallic values. + // So, for intermediate metallic values, the result isn't 100% correct but it seems to work well enough in practice. + // Because specular weight in OpenPBR removes the specular lobe entirely for metals, we do need the actual dielectric + // F0 value to pickup the weight from the dielectric lobe. + vec3 metalEnvironmentReflectance = reflectivityOut.specularWeight * getF82Specular(NdotV, reflectivityOut.colorReflectanceF0, reflectivityOut.colorReflectanceF90, reflectivityOut.roughness); + vec3 dielectricEnvironmentReflectance = getReflectanceFromBRDFLookup(reflectivityOut.dielectricColorF0, reflectivityOut.colorReflectanceF90, environmentBrdf); + vec3 colorSpecularEnvironmentReflectance = mix(dielectricEnvironmentReflectance, metalEnvironmentReflectance, reflectivityOut.metallic); + #else + vec3 colorSpecularEnvironmentReflectance = getReflectanceFromBRDFLookup(reflectivityOut.colorReflectanceF0, reflectivityOut.colorReflectanceF90, environmentBrdf); + #endif + + #ifdef RADIANCEOCCLUSION + colorSpecularEnvironmentReflectance *= seo; + #endif + + #ifdef HORIZONOCCLUSION + #ifdef BUMP + #ifdef REFLECTIONMAP_3D + colorSpecularEnvironmentReflectance *= eho; + #endif + #endif + #endif +#else + // Jones implementation of a well balanced fast analytical solution. + vec3 colorSpecularEnvironmentReflectance = getReflectanceFromAnalyticalBRDFLookup_Jones(NdotV, reflectivityOut.colorReflectanceF0, reflectivityOut.colorReflectanceF90, sqrt(microSurface)); + vec3 baseSpecularEnvironmentReflectance = getReflectanceFromAnalyticalBRDFLookup_Jones(NdotV, vec3(reflectanceF0), reflectivityOut.reflectanceF90, sqrt(microSurface)); +#endif \ No newline at end of file diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockReflectivity.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockReflectivity.fx new file mode 100644 index 00000000000..eed66449874 --- /dev/null +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockReflectivity.fx @@ -0,0 +1,135 @@ +struct reflectivityOutParams +{ + float roughness; + float diffuseRoughness; + float reflectanceF0; + vec3 reflectanceF90; + vec3 colorReflectanceF0; + vec3 colorReflectanceF90; + float metallic; + float specularWeight; + vec3 dielectricColorF0; +#if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) + vec3 ambientOcclusionColor; +#endif +#if DEBUGMODE > 0 + #ifdef METALLIC_ROUGHNESS + vec4 surfaceMetallicColorMap; + #endif + vec3 metallicF0; +#endif +}; + +#define pbr_inline +reflectivityOutParams reflectivityBlock( + in vec4 reflectanceInfo + , in vec3 surfaceAlbedo + , in vec4 specularColor + , in float baseDiffuseRoughness +#ifdef BASE_DIFFUSE_ROUGHNESS + , in float baseDiffuseRoughnessTexture + , in vec2 baseDiffuseRoughnessInfos +#endif +#ifdef METALLIC_ROUGHNESS + , in vec3 reflectivityInfos + , in vec4 metallicRoughnessFromTexture +#endif +#if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) + , in vec3 ambientOcclusionColorIn +#endif +#ifdef DETAIL + , in vec4 detailColor + , in vec4 vDetailInfos +#endif +) +{ + reflectivityOutParams outParams; + vec2 metallicRoughness = reflectanceInfo.rg; + float ior = reflectanceInfo.b; + #ifdef METALLIC_ROUGHNESS + #if DEBUGMODE > 0 + outParams.surfaceMetallicColorMap = metallicRoughnessFromTexture; + #endif + + #ifdef AOSTOREINMETALMAPRED + vec3 aoStoreInMetalMap = vec3(metallicRoughnessFromTexture.r, metallicRoughnessFromTexture.r, metallicRoughnessFromTexture.r); + outParams.ambientOcclusionColor = mix(ambientOcclusionColorIn, aoStoreInMetalMap, reflectivityInfos.z); + #endif + + metallicRoughness.r *= metallicRoughnessFromTexture.b; + metallicRoughness.g *= metallicRoughnessFromTexture.g; + #endif + + #ifdef DETAIL + float detailRoughness = mix(0.5, detailColor.b, vDetailInfos.w); + float loLerp = mix(0., metallicRoughness.g, detailRoughness * 2.); + float hiLerp = mix(metallicRoughness.g, 1., (detailRoughness - 0.5) * 2.); + metallicRoughness.g = mix(loLerp, hiLerp, step(detailRoughness, 0.5)); + #endif + + #define CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS + + outParams.metallic = metallicRoughness.r; + outParams.roughness = metallicRoughness.g; + outParams.specularWeight = specularColor.a; + const float outsideIOR = 1.0; + float dielectricF0 = pow((ior - outsideIOR) / (ior + outsideIOR), 2.0) * outParams.specularWeight; + + #if DEBUGMODE > 0 + outParams.metallicF0 = vec3(dielectricF0) * specularColor.rgb; + #endif + + // Compute non-coloured reflectance. + // reflectanceF0 is the non-coloured reflectance used for blending between the diffuse and specular components. + // It represents the total percentage of light reflected by the specular lobe at normal incidence. + // In glTF's material model, the F0 value is multiplied by the maximum component of the specular colour. + + #if DIELECTRIC_SPECULAR_MODEL == DIELECTRIC_SPECULAR_MODEL_GLTF + float maxF0 = max(specularColor.r, max(specularColor.g, specularColor.b)); + outParams.reflectanceF0 = mix(dielectricF0 * maxF0, 1.0, outParams.metallic); + #else + outParams.reflectanceF0 = mix(dielectricF0, 1.0, outParams.metallic); + #endif + + + // Scale the reflectanceF90 by the IOR for values less than 1.5. + // This is an empirical hack to account for the fact that Schlick is tuned for IOR = 1.5 + // and an IOR of 1.0 should result in no visible glancing specular. + float f90Scale = clamp(2.0 * (ior - 1.0), 0.0, 1.0); + outParams.reflectanceF90 = vec3(mix(outParams.specularWeight * f90Scale, 1.0, outParams.metallic)); + + // Compute the coloured F0 reflectance. + // The coloured reflectance is the percentage of light reflected by the specular lobe at normal incidence. + // In glTF and OpenPBR, it is not the same thing as the percentage of light blocked from penetrating + // down to the diffuse lobe. The non-coloured F0 will be used for this (see below). + outParams.dielectricColorF0 = vec3(dielectricF0 * specularColor.rgb); + vec3 metallicColorF0 = surfaceAlbedo.rgb; + outParams.colorReflectanceF0 = mix(outParams.dielectricColorF0, metallicColorF0, outParams.metallic); + + // Now, compute the coloured reflectance at glancing angles based on the specular model. + #if (DIELECTRIC_SPECULAR_MODEL == DIELECTRIC_SPECULAR_MODEL_OPENPBR) + // In OpenPBR, the F90 is coloured using the specular colour for dielectrics. + vec3 dielectricColorF90 = specularColor.rgb * vec3(outParams.specularWeight) * vec3(f90Scale); + #else + // In glTF, the F90 is white for dielectrics. + vec3 dielectricColorF90 = vec3(outParams.specularWeight * f90Scale); + #endif + #if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR) + // In OpenPBR, we use the "F82" model for conductors. + // We'll use the F90 value to hold the F82 tint which will be used in the computation later. + vec3 conductorColorF90 = specularColor.rgb; + #else + // In glTF, the F90 colour for metals is white. + vec3 conductorColorF90 = vec3(1.0); + #endif + outParams.colorReflectanceF90 = mix(dielectricColorF90, conductorColorF90, outParams.metallic); + + float diffuseRoughness = baseDiffuseRoughness; +#ifdef BASE_DIFFUSE_ROUGHNESS + diffuseRoughness *= baseDiffuseRoughnessTexture * baseDiffuseRoughnessInfos.y; +#endif + + outParams.diffuseRoughness = diffuseRoughness; + + return outParams; +} diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx index 84d657669e4..fe2d0db835c 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx @@ -3,13 +3,11 @@ uniform vec4 vEyePosition; uniform vec3 vReflectionColor; uniform vec4 vBaseColor; uniform float baseWeight; -uniform float baseDiffuseRoughness; +uniform float vBaseDiffuseRoughness; // CUSTOM CONTROLS uniform vec4 vLightingIntensity; -uniform vec4 vReflectivityColor; -uniform vec4 vMetallicReflectanceFactors; uniform vec3 vEmissiveColor; uniform float visibility; @@ -18,15 +16,15 @@ uniform vec3 vAmbientColor; // Samplers #ifdef ALBEDO -uniform vec2 baseColorInfos; +uniform vec2 vBaseColorInfos; #endif #ifdef BASE_WEIGHT -uniform vec2 baseWeightInfos; +uniform vec2 vBaseWeightInfos; #endif #ifdef BASE_DIFFUSE_ROUGHNESS -uniform vec2 baseDiffuseRoughnessInfos; +uniform vec2 vBaseDiffuseRoughnessInfos; #endif #ifdef AMBIENT @@ -50,12 +48,8 @@ uniform vec2 vEmissiveInfos; uniform vec2 vLightmapInfos; #endif -#ifdef REFLECTIVITY -uniform vec3 vReflectivityInfos; -#endif - -#ifdef MICROSURFACEMAP -uniform vec2 vMicroSurfaceSamplerInfos; +#ifdef METALLIC_ROUGHNESS +uniform vec2 vBaseMetalRoughInfos; #endif // Refraction Reflection @@ -82,135 +76,6 @@ uniform mat4 view; #endif #endif -// Refraction -#if defined(SS_REFRACTION) && defined(SS_USE_LOCAL_REFRACTIONMAP_CUBIC) - uniform vec3 vRefractionPosition; - uniform vec3 vRefractionSize; -#endif - -// Clear Coat -#ifdef CLEARCOAT - uniform vec2 vClearCoatParams; - uniform vec4 vClearCoatRefractionParams; - - #if defined(CLEARCOAT_TEXTURE) || defined(CLEARCOAT_TEXTURE_ROUGHNESS) - uniform vec4 vClearCoatInfos; - #endif - - #ifdef CLEARCOAT_TEXTURE - uniform mat4 clearCoatMatrix; - #endif - - #ifdef CLEARCOAT_TEXTURE_ROUGHNESS - uniform mat4 clearCoatRoughnessMatrix; - #endif - - #ifdef CLEARCOAT_BUMP - uniform vec2 vClearCoatBumpInfos; - uniform vec2 vClearCoatTangentSpaceParams; - uniform mat4 clearCoatBumpMatrix; - #endif - - #ifdef CLEARCOAT_TINT - uniform vec4 vClearCoatTintParams; - uniform float clearCoatColorAtDistance; - - #ifdef CLEARCOAT_TINT_TEXTURE - uniform vec2 vClearCoatTintInfos; - uniform mat4 clearCoatTintMatrix; - #endif - #endif -#endif - -// Iridescence -#ifdef IRIDESCENCE - uniform vec4 vIridescenceParams; - - #if defined(IRIDESCENCE_TEXTURE) || defined(IRIDESCENCE_THICKNESS_TEXTURE) - uniform vec4 vIridescenceInfos; - #endif - - #ifdef IRIDESCENCE_TEXTURE - uniform mat4 iridescenceMatrix; - #endif - - #ifdef IRIDESCENCE_THICKNESS_TEXTURE - uniform mat4 iridescenceThicknessMatrix; - #endif -#endif - -// Anisotropy -#ifdef ANISOTROPIC - uniform vec3 vAnisotropy; - - #ifdef ANISOTROPIC_TEXTURE - uniform vec2 vAnisotropyInfos; - uniform mat4 anisotropyMatrix; - #endif -#endif - -// Sheen -#ifdef SHEEN - uniform vec4 vSheenColor; - #ifdef SHEEN_ROUGHNESS - uniform float vSheenRoughness; - #endif - - #if defined(SHEEN_TEXTURE) || defined(SHEEN_TEXTURE_ROUGHNESS) - uniform vec4 vSheenInfos; - #endif - - #ifdef SHEEN_TEXTURE - uniform mat4 sheenMatrix; - #endif - - #ifdef SHEEN_TEXTURE_ROUGHNESS - uniform mat4 sheenRoughnessMatrix; - #endif -#endif - -// SubSurface -#ifdef SUBSURFACE - #ifdef SS_REFRACTION - uniform vec4 vRefractionMicrosurfaceInfos; - uniform vec4 vRefractionInfos; - uniform mat4 refractionMatrix; - #ifdef REALTIME_FILTERING - uniform vec2 vRefractionFilteringInfo; - #endif - #ifdef SS_DISPERSION - uniform float dispersion; - #endif - #endif - - #ifdef SS_THICKNESSANDMASK_TEXTURE - uniform vec2 vThicknessInfos; - uniform mat4 thicknessMatrix; - #endif - - #ifdef SS_REFRACTIONINTENSITY_TEXTURE - uniform vec2 vRefractionIntensityInfos; - uniform mat4 refractionIntensityMatrix; - #endif - - #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE - uniform vec2 vTranslucencyIntensityInfos; - uniform mat4 translucencyIntensityMatrix; - #endif - - uniform vec2 vThicknessParam; - uniform vec3 vDiffusionDistance; - uniform vec4 vTintColor; - uniform vec3 vSubSurfaceIntensity; - - uniform vec4 vTranslucencyColor; - - #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE - uniform vec2 vTranslucencyColorInfos; - uniform mat4 translucencyColorMatrix; - #endif -#endif - #ifdef PREPASS #ifdef SS_SCATTERING uniform float scatteringDiffusionProfile; diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx index 7b767c79805..24783ded67f 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx @@ -5,39 +5,11 @@ #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_SAMPLERNAME_,opacity) #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_SAMPLERNAME_,emissive) #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_SAMPLERNAME_,lightmap) -#include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity,_SAMPLERNAME_,reflectivity) -#include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler,_SAMPLERNAME_,microSurface) +#include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough,_SAMPLERNAME_,baseMetalRough) #include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance,_SAMPLERNAME_,metallicReflectance) #include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance,_SAMPLERNAME_,reflectance) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_SAMPLERNAME_,decal) -#ifdef CLEARCOAT - #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat,_SAMPLERNAME_,clearCoat) - #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness) - #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) - uniform sampler2D clearCoatRoughnessSampler; - #endif - #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump,_SAMPLERNAME_,clearCoatBump) - #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint,_SAMPLERNAME_,clearCoatTint) -#endif - -#ifdef IRIDESCENCE - #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence,_SAMPLERNAME_,iridescence) - #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness,_SAMPLERNAME_,iridescenceThickness) -#endif - -#ifdef SHEEN - #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen,_SAMPLERNAME_,sheen) - #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness) - #if defined(SHEEN_ROUGHNESS) && defined(SHEEN_TEXTURE_ROUGHNESS) - uniform sampler2D sheenRoughnessSampler; - #endif -#endif - -#ifdef ANISOTROPIC - #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy,_SAMPLERNAME_,anisotropy) -#endif - // Reflection #ifdef REFLECTION #ifdef REFLECTIONMAP_3D diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx index b452496e757..c304218eb3e 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx @@ -6,19 +6,19 @@ uniform vec4 vEyePosition; #endif #ifdef ALBEDO -uniform vec2 baseColorInfos; +uniform vec2 vBaseColorInfos; uniform mat4 baseColorMatrix; #endif #ifdef BASE_WEIGHT uniform mat4 baseWeightMatrix; -uniform vec2 baseWeightInfos; +uniform vec2 vBaseWeightInfos; #endif -uniform float baseDiffuseRoughness; +uniform float vBaseDiffuseRoughness; #ifdef BASE_DIFFUSE_ROUGHNESS uniform mat4 baseDiffuseRoughnessMatrix; -uniform vec2 baseDiffuseRoughnessInfos; +uniform vec2 vBaseDiffuseRoughnessInfos; #endif #ifdef AMBIENT @@ -41,9 +41,9 @@ uniform vec2 vLightmapInfos; uniform mat4 lightmapMatrix; #endif -#ifdef REFLECTIVITY -uniform vec3 vReflectivityInfos; -uniform mat4 reflectivityMatrix; +#ifdef METALLIC_ROUGHNESS +uniform vec2 vBaseMetalRoughInfos; +uniform mat4 baseMetalRoughMatrix; #endif #ifdef METALLIC_REFLECTANCE @@ -55,11 +55,6 @@ uniform mat4 reflectivityMatrix; uniform mat4 reflectanceMatrix; #endif -#ifdef MICROSURFACEMAP -uniform vec2 vMicroSurfaceSamplerInfos; -uniform mat4 microSurfaceSamplerMatrix; -#endif - #ifdef BUMP uniform vec3 vBumpInfos; uniform mat4 bumpMatrix; diff --git a/packages/dev/core/src/Shaders/openpbr.fragment.fx b/packages/dev/core/src/Shaders/openpbr.fragment.fx index 8e901dee728..18f8c4fd57d 100644 --- a/packages/dev/core/src/Shaders/openpbr.fragment.fx +++ b/packages/dev/core/src/Shaders/openpbr.fragment.fx @@ -2,7 +2,7 @@ #define CUSTOM_FRAGMENT_EXTENSION -#if defined(BUMP) || !defined(NORMAL) || defined(FORCENORMALFORWARD) || defined(SPECULARAA) || defined(CLEARCOAT_BUMP) || defined(ANISOTROPIC) +#if defined(BUMP) || !defined(NORMAL) || defined(FORCENORMALFORWARD) || defined(SPECULARAA) #extension GL_OES_standard_derivatives : enable #endif @@ -61,15 +61,10 @@ precision highp float; #define CUSTOM_FRAGMENT_DEFINITIONS #include -#include +#include #include #include -#include #include -#include -#include -#include -#include // _____________________________ MAIN FUNCTION ____________________________ void main(void) { @@ -108,12 +103,12 @@ void main(void) { vBaseColor #ifdef ALBEDO , baseColorFromTexture - , baseColorInfos + , vBaseColorInfos #endif , baseWeight #ifdef BASE_WEIGHT , baseWeightFromTexture - , baseWeightInfos + , vBaseWeightInfos #endif #ifdef OPACITY , opacityMap @@ -138,6 +133,19 @@ void main(void) { #define CUSTOM_FRAGMENT_BEFORE_LIGHTS + +// MPBR =mix(Sambient-medium,Msurface,α) whereα =geometry_opacity +// Msurface =layer(Mcoated-base,Sfuzz,F) whereF =fuzz_weight +// Mcoated-base =layer(Mbase,Scoat,C) whereC =coat_weight + +// Mbase =mix(Mdielectric-base,Smetal,M) whereM =base_metalness +// Mdielectric-base =mix(Mopaque-base,Stranslucent-base,T) whereT =transmission_weight +// Mopaque-base =mix(Mglossy-diffuse,Ssubsurface,S) whereS =subsurface_weight +// Mglossy-diffuse =layer(Sdiffuse,Sgloss) + + + + // _____________________________ AO _______________________________ ambientOcclusionOutParams aoOut; @@ -158,129 +166,76 @@ void main(void) { vec3 diffuseBase = vec3(1., 1., 1.); #else // !UNLIT - // _____________________________ Reflectivity _______________________________ - vec3 baseColor = surfaceAlbedo; - + // _____________________________ Reflectivity (Rename this to IBL) _______________________________ + reflectivityOutParams reflectivityOut; -#if defined(REFLECTIVITY) - vec4 surfaceMetallicOrReflectivityColorMap = texture2D(reflectivitySampler, vReflectivityUV + uvOffset); - vec4 baseReflectivity = surfaceMetallicOrReflectivityColorMap; - #ifndef METALLICWORKFLOW - #ifdef REFLECTIVITY_GAMMA - surfaceMetallicOrReflectivityColorMap = toLinearSpace(surfaceMetallicOrReflectivityColorMap); - #endif - surfaceMetallicOrReflectivityColorMap.rgb *= vReflectivityInfos.y; - #endif +#ifdef METALLIC_ROUGHNESS + vec4 metallicRoughnessFromTexture = texture2D(baseMetalRoughSampler, vBaseMetalRoughUV + uvOffset); #endif -#if defined(MICROSURFACEMAP) - vec4 microSurfaceTexel = texture2D(microSurfaceSampler, vMicroSurfaceSamplerUV + uvOffset) * vMicroSurfaceSamplerInfos.y; +#ifdef BASE_DIFFUSE_ROUGHNESS + float baseDiffuseRoughnessFromTexture = texture2D(baseDiffuseRoughnessSampler, vBaseDiffuseRoughnessUV + uvOffset).r; #endif -#ifdef METALLICWORKFLOW - vec4 metallicReflectanceFactors = vMetallicReflectanceFactors; - #ifdef REFLECTANCE - vec4 reflectanceFactorsMap = texture2D(reflectanceSampler, vReflectanceUV + uvOffset); - #ifdef REFLECTANCE_GAMMA - reflectanceFactorsMap = toLinearSpace(reflectanceFactorsMap); - #endif - - metallicReflectanceFactors.rgb *= reflectanceFactorsMap.rgb; +vec4 specularColor = vSpecularColor; +#ifdef SPECULAR_COLOR + vec4 specularColorFromTexture = texture2D(specularColorSampler, vSpecularColorUV + uvOffset); + #ifdef SPECULAR_COLOR_GAMMA + specularColorFromTexture = toLinearSpace(specularColorFromTexture); #endif - #ifdef METALLIC_REFLECTANCE - vec4 metallicReflectanceFactorsMap = texture2D(metallicReflectanceSampler, vMetallicReflectanceUV + uvOffset); - #ifdef METALLIC_REFLECTANCE_GAMMA - metallicReflectanceFactorsMap = toLinearSpace(metallicReflectanceFactorsMap); - #endif - #ifndef METALLIC_REFLECTANCE_USE_ALPHA_ONLY - metallicReflectanceFactors.rgb *= metallicReflectanceFactorsMap.rgb; - #endif - metallicReflectanceFactors.a *= metallicReflectanceFactorsMap.a; - #endif + specularColor.rgb *= specularColorFromTexture.rgb; #endif +#ifdef SPECULAR_WEIGHT + vec4 specularWeightFromTexture = texture2D(specularWeightSampler, vSpecularWeightUV + uvOffset); + #ifdef SPECULAR_WEIGHT_GAMMA + specularWeightFromTexture = toLinearSpace(specularWeightFromTexture); + #endif -#ifdef BASE_DIFFUSE_ROUGHNESS - float baseDiffuseRoughnessFromTexture = texture2D(baseDiffuseRoughnessSampler, vBaseDiffuseRoughnessUV + uvOffset).r; + // If loaded from a glTF, the specular_weight is stored in the alpha channel. + // Otherwise, it's expected to just be a greyscale texture. + #ifdef SPECULAR_WEIGHT_USE_ALPHA_ONLY + specularColor.a *= specularWeightFromTexture.a; + #else + specularColor.rgb *= specularWeightFromTexture.rgb; + #endif #endif reflectivityOut = reflectivityBlock( - vReflectivityColor - #ifdef METALLICWORKFLOW + vReflectanceInfo , surfaceAlbedo - , metallicReflectanceFactors - #endif - , baseDiffuseRoughness + , specularColor + , vBaseDiffuseRoughness #ifdef BASE_DIFFUSE_ROUGHNESS , baseDiffuseRoughnessFromTexture - , baseDiffuseRoughnessInfos + , vBaseDiffuseRoughnessInfos #endif - #ifdef REFLECTIVITY - , vReflectivityInfos - , surfaceMetallicOrReflectivityColorMap + #ifdef METALLIC_ROUGHNESS + , vec3(vBaseMetalRoughInfos, 1.0f) + , metallicRoughnessFromTexture #endif - #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED) + #if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) , aoOut.ambientOcclusionColor #endif - #ifdef MICROSURFACEMAP - , microSurfaceTexel - #endif #ifdef DETAIL , detailColor , vDetailInfos #endif ); - float microSurface = reflectivityOut.microSurface; float roughness = reflectivityOut.roughness; float diffuseRoughness = reflectivityOut.diffuseRoughness; - #ifdef METALLICWORKFLOW - surfaceAlbedo = reflectivityOut.surfaceAlbedo; - #endif - #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED) + // surfaceAlbedo = reflectivityOut.surfaceAlbedo; + + #if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) aoOut.ambientOcclusionColor = reflectivityOut.ambientOcclusionColor; #endif - // _____________________________ Alpha Fresnel ___________________________________ - #ifdef ALPHAFRESNEL - #if defined(ALPHATEST) || defined(ALPHABLEND) - alphaFresnelOutParams alphaFresnelOut; - - alphaFresnelOut = alphaFresnelBlock( - normalW, - viewDirectionW, - alpha, - microSurface - ); - - alpha = alphaFresnelOut.alpha; - #endif - #endif - // _____________________________ Compute Geometry info _________________________________ #include - // _____________________________ Anisotropy _______________________________________ - #ifdef ANISOTROPIC - anisotropicOutParams anisotropicOut; - - #ifdef ANISOTROPIC_TEXTURE - vec3 anisotropyMapData = texture2D(anisotropySampler, vAnisotropyUV + uvOffset).rgb * vAnisotropyInfos.y; - #endif - - anisotropicOut = anisotropicBlock( - vAnisotropy, - roughness, - #ifdef ANISOTROPIC_TEXTURE - anisotropyMapData, - #endif - TBN, - normalW, - viewDirectionW - ); - #endif // _____________________________ Reflection Info _______________________________________ #ifdef REFLECTION @@ -328,336 +283,41 @@ void main(void) { #endif , viewDirectionW , diffuseRoughness - , baseColor + , surfaceAlbedo ); #else #define CUSTOM_REFLECTION #endif #endif - // ___________________ Compute Reflectance aka R0 F0 info _________________________ - #include - - // ________________________________ Sheen ______________________________ - #ifdef SHEEN - sheenOutParams sheenOut; - - #ifdef SHEEN_TEXTURE - vec4 sheenMapData = texture2D(sheenSampler, vSheenUV + uvOffset); - #endif - #if defined(SHEEN_ROUGHNESS) && defined(SHEEN_TEXTURE_ROUGHNESS) && !defined(SHEEN_USE_ROUGHNESS_FROM_MAINTEXTURE) - vec4 sheenMapRoughnessData = texture2D(sheenRoughnessSampler, vSheenRoughnessUV + uvOffset) * vSheenInfos.w; - #endif - - sheenOut = sheenBlock( - vSheenColor - #ifdef SHEEN_ROUGHNESS - , vSheenRoughness - #if defined(SHEEN_TEXTURE_ROUGHNESS) && !defined(SHEEN_USE_ROUGHNESS_FROM_MAINTEXTURE) - , sheenMapRoughnessData - #endif - #endif - , roughness - #ifdef SHEEN_TEXTURE - , sheenMapData - , vSheenInfos.y - #endif - , reflectanceF0 - #ifdef SHEEN_LINKWITHALBEDO - , baseColor - , surfaceAlbedo - #endif - #ifdef ENVIRONMENTBRDF - , NdotV - , environmentBrdf - #endif - #if defined(REFLECTION) && defined(ENVIRONMENTBRDF) - , AARoughnessFactors - , vReflectionMicrosurfaceInfos - , vReflectionInfos - , vReflectionColor - , vLightingIntensity - , reflectionSampler - , reflectionOut.reflectionCoords - , NdotVUnclamped - #ifndef LODBASEDMICROSFURACE - , reflectionSamplerLow - , reflectionSamplerHigh - #endif - #ifdef REALTIME_FILTERING - , vReflectionFilteringInfo - #endif - #if !defined(REFLECTIONMAP_SKYBOX) && defined(RADIANCEOCCLUSION) - , seo - #endif - #if !defined(REFLECTIONMAP_SKYBOX) && defined(HORIZONOCCLUSION) && defined(BUMP) && defined(REFLECTIONMAP_3D) - , eho - #endif - #endif - ); - - #ifdef SHEEN_LINKWITHALBEDO - surfaceAlbedo = sheenOut.surfaceAlbedo; - #endif - #endif - - // _____________ Shared Iridescence and Clear Coat data _________________ - #ifdef CLEARCOAT - #ifdef CLEARCOAT_TEXTURE - vec2 clearCoatMapData = texture2D(clearCoatSampler, vClearCoatUV + uvOffset).rg * vClearCoatInfos.y; - #endif - #endif - - // _____________________________ Iridescence ____________________________ - #ifdef IRIDESCENCE - iridescenceOutParams iridescenceOut; - - #ifdef IRIDESCENCE_TEXTURE - vec2 iridescenceMapData = texture2D(iridescenceSampler, vIridescenceUV + uvOffset).rg * vIridescenceInfos.y; - #endif - #ifdef IRIDESCENCE_THICKNESS_TEXTURE - vec2 iridescenceThicknessMapData = texture2D(iridescenceThicknessSampler, vIridescenceThicknessUV + uvOffset).rg * vIridescenceInfos.w; - #endif - - iridescenceOut = iridescenceBlock( - vIridescenceParams - , NdotV - , specularEnvironmentR0 - #ifdef IRIDESCENCE_TEXTURE - , iridescenceMapData - #endif - #ifdef IRIDESCENCE_THICKNESS_TEXTURE - , iridescenceThicknessMapData - #endif - #ifdef CLEARCOAT - , NdotVUnclamped - , vClearCoatParams - #ifdef CLEARCOAT_TEXTURE - , clearCoatMapData - #endif - #endif - ); - - float iridescenceIntensity = iridescenceOut.iridescenceIntensity; - specularEnvironmentR0 = iridescenceOut.specularEnvironmentR0; - #endif - - // _____________________________ Clear Coat ____________________________ - clearcoatOutParams clearcoatOut; - - #ifdef CLEARCOAT - #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) && !defined(CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE) - vec4 clearCoatMapRoughnessData = texture2D(clearCoatRoughnessSampler, vClearCoatRoughnessUV + uvOffset) * vClearCoatInfos.w; - #endif - - #if defined(CLEARCOAT_TINT) && defined(CLEARCOAT_TINT_TEXTURE) - vec4 clearCoatTintMapData = texture2D(clearCoatTintSampler, vClearCoatTintUV + uvOffset); - #endif - - #ifdef CLEARCOAT_BUMP - vec4 clearCoatBumpMapData = texture2D(clearCoatBumpSampler, vClearCoatBumpUV + uvOffset); - #endif - - clearcoatOut = clearcoatBlock( - vPositionW - , geometricNormalW - , viewDirectionW - , vClearCoatParams - #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) && !defined(CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE) - , clearCoatMapRoughnessData - #endif - , specularEnvironmentR0 - #ifdef CLEARCOAT_TEXTURE - , clearCoatMapData - #endif - #ifdef CLEARCOAT_TINT - , vClearCoatTintParams - , clearCoatColorAtDistance - , vClearCoatRefractionParams - #ifdef CLEARCOAT_TINT_TEXTURE - , clearCoatTintMapData - #endif - #endif - #ifdef CLEARCOAT_BUMP - , vClearCoatBumpInfos - , clearCoatBumpMapData - , vClearCoatBumpUV - #if defined(TANGENT) && defined(NORMAL) - , vTBN - #else - , vClearCoatTangentSpaceParams - #endif - #ifdef OBJECTSPACE_NORMALMAP - , normalMatrix - #endif - #endif - #if defined(FORCENORMALFORWARD) && defined(NORMAL) - , faceNormal - #endif - #ifdef REFLECTION - , vReflectionMicrosurfaceInfos - , vReflectionInfos - , vReflectionColor - , vLightingIntensity - , reflectionSampler - #ifndef LODBASEDMICROSFURACE - , reflectionSamplerLow - , reflectionSamplerHigh - #endif - #ifdef REALTIME_FILTERING - , vReflectionFilteringInfo - #endif - #endif - #if defined(CLEARCOAT_BUMP) || defined(TWOSIDEDLIGHTING) - , (gl_FrontFacing ? 1. : -1.) - #endif - ); - #else - clearcoatOut.specularEnvironmentR0 = specularEnvironmentR0; - #endif - // _________________________ Specular Environment Reflectance __________________________ - #include - - // ___________________________________ SubSurface ______________________________________ - subSurfaceOutParams subSurfaceOut; - - #ifdef SUBSURFACE - #ifdef SS_THICKNESSANDMASK_TEXTURE - vec4 thicknessMap = texture2D(thicknessSampler, vThicknessUV + uvOffset); - #endif - - #ifdef SS_REFRACTIONINTENSITY_TEXTURE - vec4 refractionIntensityMap = texture2D(refractionIntensitySampler, vRefractionIntensityUV + uvOffset); - #endif - - #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE - vec4 translucencyIntensityMap = texture2D(translucencyIntensitySampler, vTranslucencyIntensityUV + uvOffset); - #endif - - #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE - vec4 translucencyColorMap = texture2D(translucencyColorSampler, vTranslucencyColorUV + uvOffset); - #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE_GAMMA - translucencyColorMap = toLinearSpace(translucencyColorMap); - #endif - #endif - - #ifdef LEGACY_SPECULAR_ENERGY_CONSERVATION - vec3 vSpecularEnvironmentReflectance = vec3(max(colorSpecularEnvironmentReflectance.r, max(colorSpecularEnvironmentReflectance.g, colorSpecularEnvironmentReflectance.b))); - #endif - - subSurfaceOut = subSurfaceBlock( - vSubSurfaceIntensity - , vThicknessParam - , vTintColor - , normalW - #ifdef LEGACY_SPECULAR_ENERGY_CONSERVATION - , vSpecularEnvironmentReflectance - #else - , baseSpecularEnvironmentReflectance - #endif - #ifdef SS_THICKNESSANDMASK_TEXTURE - , thicknessMap - #endif - #ifdef SS_REFRACTIONINTENSITY_TEXTURE - , refractionIntensityMap - #endif - #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE - , translucencyIntensityMap - #endif - #ifdef REFLECTION - #ifdef SS_TRANSLUCENCY - , reflectionMatrix - #ifdef USESPHERICALFROMREFLECTIONMAP - #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX) - , reflectionOut.irradianceVector - #endif - #if defined(REALTIME_FILTERING) - , reflectionSampler - , vReflectionFilteringInfo - #ifdef IBL_CDF_FILTERING - , icdfSampler - #endif - #endif - #endif - #ifdef USEIRRADIANCEMAP - , irradianceSampler - #endif - #endif - #endif - #if defined(SS_REFRACTION) || defined(SS_TRANSLUCENCY) - , surfaceAlbedo - #endif - #ifdef SS_REFRACTION - , vPositionW - , viewDirectionW - , view - , vRefractionInfos - , refractionMatrix - , vRefractionMicrosurfaceInfos - , vLightingIntensity - #ifdef SS_LINKREFRACTIONTOTRANSPARENCY - , alpha - #endif - #ifdef SS_LODINREFRACTIONALPHA - , NdotVUnclamped - #endif - #ifdef SS_LINEARSPECULARREFRACTION - , roughness - #endif - , alphaG - , refractionSampler - #ifndef LODBASEDMICROSFURACE - , refractionSamplerLow - , refractionSamplerHigh - #endif - #ifdef ANISOTROPIC - , anisotropicOut - #endif - #ifdef REALTIME_FILTERING - , vRefractionFilteringInfo - #endif - #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC - , vRefractionPosition - , vRefractionSize - #endif - #ifdef SS_DISPERSION - , dispersion - #endif - #endif - #ifdef SS_TRANSLUCENCY - , vDiffusionDistance - , vTranslucencyColor - #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE - , translucencyColorMap - #endif - #endif - ); - - #ifdef SS_REFRACTION - surfaceAlbedo = subSurfaceOut.surfaceAlbedo; - #ifdef SS_LINKREFRACTIONTOTRANSPARENCY - alpha = subSurfaceOut.alpha; - #endif - #endif - #else - subSurfaceOut.specularEnvironmentReflectance = colorSpecularEnvironmentReflectance; - #endif - + float reflectanceF0 = reflectivityOut.reflectanceF0; + vec3 specularEnvironmentR0 = reflectivityOut.colorReflectanceF0; + vec3 specularEnvironmentR90 = reflectivityOut.colorReflectanceF90; + #include + // _____________________________ Direct Lighting Info __________________________________ #include - #include[0..maxSimultaneousLights] + // TODO: lightFragment references cloatcoatOut, subsurfaceOut, etc. + // lightFragment shouldn't know what layer it's working on. + // Instead, we should define values for lightFragment to use here, defining + // conditions like F0, F90, etc. + // Or we could convert lightFragment to be a function that returns the diffuse + // or specular contribution, given the reflectance inputs? + // e.g. lighting contributions from clearcoat, subsurface, base layer, etc. need + // to be computed separately. + // #include[0..maxSimultaneousLights] // _____________________________ Compute Final Lit Components ________________________ - #include + #include #endif // !UNLIT #include #define CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION - #include + #include #include #include(color, finalColor) diff --git a/packages/dev/core/src/Shaders/openpbr.vertex.fx b/packages/dev/core/src/Shaders/openpbr.vertex.fx index 3b4710c6c82..3bf844c7304 100644 --- a/packages/dev/core/src/Shaders/openpbr.vertex.fx +++ b/packages/dev/core/src/Shaders/openpbr.vertex.fx @@ -41,10 +41,9 @@ attribute vec4 color; #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity) #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive) #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap) -#include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity) -#include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler) -#include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance) -#include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance) +#include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough) +#include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight) +#include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor) #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal) @@ -165,7 +164,7 @@ void main(void) { #endif float NdotV = max(dot(vNormalW, viewDirectionW), 0.0); - vec3 roughNormal = mix(vNormalW, viewDirectionW, (0.5 * (1.0 - NdotV)) * baseDiffuseRoughness); + vec3 roughNormal = mix(vNormalW, viewDirectionW, (0.5 * (1.0 - NdotV)) * vBaseDiffuseRoughness); vec3 reflectionVector = vec3(reflectionMatrix * vec4(roughNormal, 0)).xyz; #else vec3 reflectionVector = vec3(reflectionMatrix * vec4(vNormalW, 0)).xyz; @@ -221,42 +220,12 @@ void main(void) { #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_MATRIXNAME_,opacity,_INFONAME_,OpacityInfos.x) #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_MATRIXNAME_,emissive,_INFONAME_,EmissiveInfos.x) #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_MATRIXNAME_,lightmap,_INFONAME_,LightmapInfos.x) - #include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity,_MATRIXNAME_,reflectivity,_INFONAME_,ReflectivityInfos.x) - #include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler,_MATRIXNAME_,microSurfaceSampler,_INFONAME_,MicroSurfaceSamplerInfos.x) - #include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance,_MATRIXNAME_,metallicReflectance,_INFONAME_,MetallicReflectanceInfos.x) - #include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance,_MATRIXNAME_,reflectance,_INFONAME_,ReflectanceInfos.x) + #include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough,_MATRIXNAME_,baseMetalRough,_INFONAME_,BaseMetalRoughInfos.x) + #include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight,_MATRIXNAME_,specularWeight,_INFONAME_,SpecularWeightInfos.x) + #include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor,_MATRIXNAME_,specularColor,_INFONAME_,SpecularColorInfos.x) #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump,_MATRIXNAME_,bump,_INFONAME_,BumpInfos.x) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_MATRIXNAME_,decal,_INFONAME_,DecalInfos.x) -#ifdef CLEARCOAT - #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat,_MATRIXNAME_,clearCoat,_INFONAME_,ClearCoatInfos.x) - #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness,_MATRIXNAME_,clearCoatRoughness,_INFONAME_,ClearCoatInfos.z) - #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump,_MATRIXNAME_,clearCoatBump,_INFONAME_,ClearCoatBumpInfos.x) - #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint,_MATRIXNAME_,clearCoatTint,_INFONAME_,ClearCoatTintInfos.x) -#endif - -#ifdef IRIDESCENCE - #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence,_MATRIXNAME_,iridescence,_INFONAME_,IridescenceInfos.x) - #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness,_MATRIXNAME_,iridescenceThickness,_INFONAME_,IridescenceInfos.z) -#endif - -#ifdef SHEEN - #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen,_MATRIXNAME_,sheen,_INFONAME_,SheenInfos.x) - #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness,_MATRIXNAME_,sheenRoughness,_INFONAME_,SheenInfos.z) - -#endif - -#ifdef ANISOTROPIC - #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy,_MATRIXNAME_,anisotropy,_INFONAME_,AnisotropyInfos.x) -#endif - -#ifdef SUBSURFACE - #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness,_MATRIXNAME_,thickness,_INFONAME_,ThicknessInfos.x) - #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity,_MATRIXNAME_,refractionIntensity,_INFONAME_,RefractionIntensityInfos.x) - #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity,_MATRIXNAME_,translucencyIntensity,_INFONAME_,TranslucencyIntensityInfos.x) - #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor,_MATRIXNAME_,translucencyColor,_INFONAME_,TranslucencyColorInfos.x) -#endif - // TBN #include diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx index 6ae5c2455a1..be6feacd61c 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx @@ -2,30 +2,20 @@ uniform vAmbientInfos: vec4f; uniform vOpacityInfos: vec2f; uniform vEmissiveInfos: vec2f; uniform vLightmapInfos: vec2f; -uniform vReflectivityInfos: vec3f; -uniform vMicroSurfaceSamplerInfos: vec2f; uniform vBumpInfos: vec3f; uniform ambientMatrix: mat4x4f; uniform opacityMatrix: mat4x4f; uniform emissiveMatrix: mat4x4f; uniform lightmapMatrix: mat4x4f; -uniform reflectivityMatrix: mat4x4f; -uniform microSurfaceSamplerMatrix: mat4x4f; uniform bumpMatrix: mat4x4f; uniform vTangentSpaceParams: vec2f; uniform vLightingIntensity: vec4f; uniform pointSize: f32; -uniform vReflectivityColor: vec4f; uniform vAmbientColor: vec3f; uniform vDebugMode: vec2f; -uniform vMetallicReflectanceFactors: vec4f; -uniform vMetallicReflectanceInfos: vec2f; -uniform metallicReflectanceMatrix: mat4x4f; -uniform vReflectanceInfos: vec2f; -uniform reflectanceMatrix: mat4x4f; uniform cameraInfo: vec4f; uniform vReflectionInfos: vec2f; @@ -59,15 +49,23 @@ uniform vSphericalZX: vec3f; uniform baseWeight: f32; uniform vBaseColor: vec4f; -uniform baseDiffuseRoughness: f32; +uniform vBaseDiffuseRoughness: f32; +uniform vReflectanceInfo: vec4f; +uniform vSpecularColor: vec4f; uniform vEmissiveColor: vec3f; -uniform baseWeightInfos: vec2f; +uniform vBaseWeightInfos: vec2f; uniform baseWeightMatrix: mat4x4f; -uniform baseColorInfos: vec2f; +uniform vBaseColorInfos: vec2f; uniform baseColorMatrix: mat4x4f; -uniform baseDiffuseRoughnessInfos: vec2f; +uniform vBaseDiffuseRoughnessInfos: vec2f; uniform baseDiffuseRoughnessMatrix: mat4x4f; +uniform vBaseMetalRoughInfos: vec2f; +uniform baseMetalRoughMatrix: mat4x4f; +uniform vSpecularWeightInfos: vec2f; +uniform specularWeightMatrix: mat4x4f; +uniform vSpecularColorInfos: vec2f; +uniform specularColorMatrix: mat4x4f; #define ADDITIONAL_UBO_DECLARATION diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalColorComposition.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalColorComposition.fx new file mode 100644 index 00000000000..a56f7056b55 --- /dev/null +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalColorComposition.fx @@ -0,0 +1,34 @@ +var finalColor: vec4f = vec4f( +#ifndef UNLIT + #ifdef REFLECTION + finalIrradiance + + #endif + #ifdef SPECULARTERM + finalSpecularScaled + + #endif + #ifdef REFLECTION + finalRadianceScaled + + #endif +#endif + finalAmbient + + finalDiffuse, + alpha); + +// _____________________________ LightMappping _____________________________________ +#ifdef LIGHTMAP + #ifndef LIGHTMAPEXCLUDED + #ifdef USELIGHTMAPASSHADOWMAP + finalColor = vec4f(finalColor.rgb * lightmapColor.rgb, finalColor.a); + #else + finalColor = vec4f(finalColor.rgb + lightmapColor.rgb, finalColor.a); + #endif + #endif +#endif + +// _____________________________ EmissiveLight _____________________________________ +finalColor = vec4f(finalColor.rgb + finalEmissive, finalColor.a); + +#define CUSTOM_FRAGMENT_BEFORE_FOG + +// _____________________________ Finally ___________________________________________ +finalColor = max(finalColor, vec4f(0.0)); diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalLitComponents.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalLitComponents.fx new file mode 100644 index 00000000000..e3fc7254aa1 --- /dev/null +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalLitComponents.fx @@ -0,0 +1,73 @@ +aggShadow = aggShadow / numLights; + +// ______________________________________________________________________________ +// _____________________________ Energy Conservation ___________________________ +// Apply Energy Conservation. +// _____________________________ IBL BRDF + Energy Cons ________________________________ +#if defined(ENVIRONMENTBRDF) + #ifdef MS_BRDF_ENERGY_CONSERVATION + var baseSpecularEnergyConservationFactor: vec3f = getEnergyConservationFactor(vec3f(reflectanceF0), environmentBrdf); + var coloredEnergyConservationFactor: vec3f = getEnergyConservationFactor(specularEnvironmentR0, environmentBrdf); + #endif +#endif + +// _____________________________ Irradiance ______________________________________ +#ifdef REFLECTION + var finalIrradiance: vec3f = reflectionOut.environmentIrradiance; + + // Account for energy loss due to specular reflectance + var baseSpecularEnergy: vec3f = vec3f(baseSpecularEnvironmentReflectance); + #if defined(ENVIRONMENTBRDF) + #ifdef MS_BRDF_ENERGY_CONSERVATION + baseSpecularEnergy *= baseSpecularEnergyConservationFactor; + #endif + #endif + finalIrradiance *= clamp(vec3f(1.0) - baseSpecularEnergy, vec3f(0.0), vec3f(1.0)); + finalIrradiance *= uniforms.vLightingIntensity.z; + finalIrradiance *= surfaceAlbedo.rgb; + finalIrradiance *= aoOut.ambientOcclusionColor; +#endif + +// _____________________________ Specular ________________________________________ +#ifdef SPECULARTERM + var finalSpecular: vec3f = specularBase; + finalSpecular = max(finalSpecular, vec3f(0.0)); + + var finalSpecularScaled: vec3f = finalSpecular * uniforms.vLightingIntensity.x * uniforms.vLightingIntensity.w; + + #if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION) + finalSpecularScaled *= coloredEnergyConservationFactor; + #endif +#endif + +// _____________________________ Radiance ________________________________________ +#ifdef REFLECTION + var finalRadiance: vec3f = reflectionOut.environmentRadiance.rgb; + finalRadiance *= colorSpecularEnvironmentReflectance;; + + var finalRadianceScaled: vec3f = finalRadiance * uniforms.vLightingIntensity.z; + + #if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION) + finalRadianceScaled *= coloredEnergyConservationFactor; + #endif + +#endif + +// _____________________________ Highlights on Alpha _____________________________ +#ifdef ALPHABLEND + var luminanceOverAlpha: f32 = 0.0; + #if defined(REFLECTION) && defined(RADIANCEOVERALPHA) + luminanceOverAlpha += getLuminance(finalRadianceScaled); + #if defined(CLEARCOAT) + luminanceOverAlpha += getLuminance(clearcoatOut.finalClearCoatRadianceScaled); + #endif + #endif + + #if defined(SPECULARTERM) && defined(SPECULAROVERALPHA) + luminanceOverAlpha += getLuminance(finalSpecularScaled); + #endif + + #if defined(RADIANCEOVERALPHA) || defined(SPECULAROVERALPHA) || defined(CLEARCOATOVERALPHA) + alpha = saturate(alpha + luminanceOverAlpha * luminanceOverAlpha); + #endif +#endif diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockReflectance.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockReflectance.fx new file mode 100644 index 00000000000..e1463573150 --- /dev/null +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockReflectance.fx @@ -0,0 +1,36 @@ +#if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX) + // "Base" specular reflectance is the amount of light prevented from penetrating the diffuse surface by the specular lobe. + // For dielectric materials, this is a greyscale value derived from the IOR and the maximum component of the specular colour. + // For metallic materials, this is vec3(1.0). i.e. no light penetrates to the diffuse surface. + var baseSpecularEnvironmentReflectance: vec3f = getReflectanceFromBRDFWithEnvLookup(vec3f(reflectanceF0), vec3f(reflectivityOut.reflectanceF90), environmentBrdf); + + #if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR) + // For OpenPBR, we use a different specular lobe for metallic materials and then blend based on metalness. However, + // to do this correctly, we really need reflectivityOut to contain separate F0 and F90 values for purely dielectric + // and purely metal. Instead, the values are already a mix of dielectric and metallic values. + // So, for intermediate metallic values, the result isn't 100% correct but it seems to work well enough in practice. + // Because specular weight in OpenPBR removes the specular lobe entirely for metals, we do need the actual dielectric + // F0 value to pickup the weight from the dielectric lobe. + let metalEnvironmentReflectance: vec3f = vec3f(reflectivityOut.specularWeight) * getF82Specular(NdotV, reflectivityOut.colorReflectanceF0, reflectivityOut.colorReflectanceF90, reflectivityOut.roughness); + let dielectricEnvironmentReflectance = getReflectanceFromBRDFWithEnvLookup(reflectivityOut.dielectricColorF0, reflectivityOut.colorReflectanceF90, environmentBrdf); + var colorSpecularEnvironmentReflectance: vec3f = mix(dielectricEnvironmentReflectance, metalEnvironmentReflectance, reflectivityOut.metallic); + #else + var colorSpecularEnvironmentReflectance = getReflectanceFromBRDFWithEnvLookup(reflectivityOut.colorReflectanceF0, reflectivityOut.colorReflectanceF90, environmentBrdf); + #endif + + #ifdef RADIANCEOCCLUSION + colorSpecularEnvironmentReflectance *= seo; + #endif + + #ifdef HORIZONOCCLUSION + #ifdef BUMP + #ifdef REFLECTIONMAP_3D + colorSpecularEnvironmentReflectance *= eho; + #endif + #endif + #endif +#else + // Jones implementation of a well balanced fast analytical solution. + var colorSpecularEnvironmentReflectance: vec3f = getReflectanceFromAnalyticalBRDFLookup_Jones(NdotV, reflectivityOut.colorReflectanceF0, reflectivityOut.colorReflectanceF90, sqrt(microSurface)); + var baseSpecularEnvironmentReflectance: vec3f = getReflectanceFromAnalyticalBRDFLookup_Jones(NdotV, vec3f(reflectanceF0), vec3f(reflectivityOut.reflectanceF90), sqrt(microSurface)); +#endif diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockReflectivity.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockReflectivity.fx new file mode 100644 index 00000000000..d36f6a3935a --- /dev/null +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockReflectivity.fx @@ -0,0 +1,137 @@ +struct reflectivityOutParams +{ + roughness: f32, + diffuseRoughness: f32, + reflectanceF0: f32, + reflectanceF90: vec3f, + colorReflectanceF0: vec3f, + colorReflectanceF90: vec3f, + metallic: f32, + specularWeight: f32, + dielectricColorF0: vec3f, +#if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) + ambientOcclusionColor: vec3f, +#endif +#if DEBUGMODE > 0 + #ifdef METALLIC_ROUGHNESS + surfaceMetallicColorMap: vec4f, + #endif + metallicF0: vec3f, +#endif +}; + +#define pbr_inline +fn reflectivityBlock( + reflectanceInfo: vec4f + , surfaceAlbedo: vec3f + , specularColor: vec4f + , baseDiffuseRoughness: f32 +#ifdef BASE_DIFFUSE_ROUGHNESS + , baseDiffuseRoughnessTexture: f32 + , baseDiffuseRoughnessInfos: vec2f +#endif +#ifdef METALLIC_ROUGHNESS + , reflectivityInfos: vec3f + , metallicRoughnessFromTexture: vec4f +#endif +#if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) + , ambientOcclusionColorIn: vec3f +#endif +#ifdef DETAIL + , detailColor: vec4f + , vDetailInfos: vec4f +#endif +) -> reflectivityOutParams +{ + var outParams: reflectivityOutParams; + var metallicRoughness: vec2f = reflectanceInfo.rg; + var ior: f32 = reflectanceInfo.b; + #ifdef METALLIC_ROUGHNESS + #if DEBUGMODE > 0 + outParams.surfaceMetallicColorMap = metallicRoughnessFromTexture; + #endif + + #ifdef AOSTOREINMETALMAPRED + var aoStoreInMetalMap: vec3f = vec3f(metallicRoughnessFromTexture.r, metallicRoughnessFromTexture.r, metallicRoughnessFromTexture.r); + outParams.ambientOcclusionColor = mix(ambientOcclusionColorIn, aoStoreInMetalMap, reflectivityInfos.z); + #endif + + metallicRoughness.r *= metallicRoughnessFromTexture.b; + metallicRoughness.g *= metallicRoughnessFromTexture.g; + #endif + + #ifdef DETAIL + var detailRoughness: f32 = mix(0.5, detailColor.b, vDetailInfos.w); + var loLerp: f32 = mix(0., metallicRoughness.g, detailRoughness * 2.); + var hiLerp: f32 = mix(metallicRoughness.g, 1., (detailRoughness - 0.5) * 2.); + metallicRoughness.g = mix(loLerp, hiLerp, step(detailRoughness, 0.5)); + #endif + + #define CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS + + outParams.metallic = metallicRoughness.r; + outParams.roughness = metallicRoughness.g; + outParams.specularWeight = specularColor.a; + const outsideIOR: f32 = 1.0; + let dielectricF0: f32 = pow((ior - outsideIOR) / (ior + outsideIOR), 2.0) * outParams.specularWeight; + + #if DEBUGMODE > 0 + outParams.metallicF0 = dielectricF0 * specularColor.rgb; + #endif + + // Compute non-coloured reflectance. + // reflectanceF0 is the non-coloured reflectance used for blending between the diffuse and specular components. + // It represents the total percentage of light reflected by the specular lobe at normal incidence. + // In glTF's material model, the F0 value is multiplied by the maximum component of the specular colour. + #if DIELECTRIC_SPECULAR_MODEL == DIELECTRIC_SPECULAR_MODEL_GLTF + let maxF0: f32 = max(specularColor.r, max(specularColor.g, specularColor.b)); + outParams.reflectanceF0 = mix(dielectricF0 * maxF0, 1.0f, outParams.metallic); + #else + outParams.reflectanceF0 = mix(dielectricF0, 1.0, outParams.metallic); + #endif + + // Scale the reflectanceF90 by the IOR for values less than 1.5. + // This is an empirical hack to account for the fact that Schlick is tuned for IOR = 1.5 + // and an IOR of 1.0 should result in no visible glancing specular. + var f90Scale: f32 = clamp(2.0 * (ior - 1.0), 0.0, 1.0); + outParams.reflectanceF90 = vec3(mix( + outParams.specularWeight * f90Scale, 1.0, outParams.metallic)); + + // Compute the coloured F0 reflectance. + // The coloured reflectance is the percentage of light reflected by the specular lobe at normal incidence. + // In glTF and OpenPBR, it is not the same thing as the percentage of light blocked from penetrating + // down to the diffuse lobe. The non-coloured F0 will be used for this (see below). + outParams.dielectricColorF0 = vec3f(dielectricF0 * specularColor.rgb); + var metallicColorF0: vec3f = surfaceAlbedo.rgb; + outParams.colorReflectanceF0 = mix(outParams.dielectricColorF0, metallicColorF0, outParams.metallic); + + // Now, compute the coloured reflectance at glancing angles based on the specular model. + #if (DIELECTRIC_SPECULAR_MODEL == DIELECTRIC_SPECULAR_MODEL_OPENPBR) + // In OpenPBR, the F90 is coloured using the specular colour for dielectrics. + let dielectricColorF90 + : vec3f = specularColor.rgb * + vec3f(outParams.specularWeight * f90Scale); + #else + // In glTF, the F90 is white for dielectrics. + let dielectricColorF90 + : vec3f = vec3f(outParams.specularWeight * f90Scale); + #endif + #if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR) + // In OpenPBR, we use the "F82" model for conductors. + // We'll use the F90 value to hold the F82 tint which will be used in the computation later. + let conductorColorF90: vec3f = specularColor.rgb; + #else + // In glTF, the F90 colour for metals is white. + let conductorColorF90: vec3f = vec3f(1.0f); + #endif + outParams.colorReflectanceF90 = mix(dielectricColorF90, conductorColorF90, outParams.metallic); + + var diffuseRoughness: f32 = baseDiffuseRoughness; +#ifdef BASE_DIFFUSE_ROUGHNESS + diffuseRoughness *= baseDiffuseRoughnessTexture * baseDiffuseRoughnessInfos.y; +#endif + + outParams.diffuseRoughness = diffuseRoughness; + + return outParams; +} diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx index 363fde264fe..9fb632b5df8 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx @@ -5,41 +5,11 @@ #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_SAMPLERNAME_,opacity) #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_SAMPLERNAME_,emissive) #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_SAMPLERNAME_,lightmap) -#include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity,_SAMPLERNAME_,reflectivity) -#include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler,_SAMPLERNAME_,microSurface) -#include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance,_SAMPLERNAME_,metallicReflectance) -#include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance,_SAMPLERNAME_,reflectance) +#include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough,_SAMPLERNAME_,baseMetalRough) +#include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight,_SAMPLERNAME_,specularWeight) +#include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor,_SAMPLERNAME_,specularColor) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_SAMPLERNAME_,decal) -#ifdef CLEARCOAT - #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat,_SAMPLERNAME_,clearCoat) - #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness) - #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) - var clearCoatRoughnessSamplerSampler: sampler; - var clearCoatRoughnessSampler: texture_2d; - #endif - #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump,_SAMPLERNAME_,clearCoatBump) - #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint,_SAMPLERNAME_,clearCoatTint) -#endif - -#ifdef IRIDESCENCE - #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence,_SAMPLERNAME_,iridescence) - #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness,_SAMPLERNAME_,iridescenceThickness) -#endif - -#ifdef SHEEN - #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen,_SAMPLERNAME_,sheen) - #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness) - #if defined(SHEEN_ROUGHNESS) && defined(SHEEN_TEXTURE_ROUGHNESS) - var sheenRoughnessSamplerSampler: sampler; - var sheenRoughnessSampler: texture_2d; - #endif -#endif - -#ifdef ANISOTROPIC - #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy,_SAMPLERNAME_,anisotropy) -#endif - // Reflection #ifdef REFLECTION #ifdef REFLECTIONMAP_3D @@ -91,43 +61,6 @@ var environmentBrdfSampler: texture_2d; #endif - -// SUBSURFACE -#ifdef SUBSURFACE - #ifdef SS_REFRACTION - #ifdef SS_REFRACTIONMAP_3D - - var refractionSamplerSampler: sampler; - var refractionSampler: texture_cube; - - #ifdef LODBASEDMICROSFURACE - #else - var refractionLowSamplerSampler: sampler; - var refractionLowSampler: texture_cube; - var refractionHighSamplerSampler: sampler; - var refractionHighSampler: texture_cube; - #endif - #else - - var refractionSamplerSampler: sampler; - var refractionSampler: texture_2d; - - #ifdef LODBASEDMICROSFURACE - #else - var refractionLowSamplerSampler: sampler; - var refractionLowSampler: texture_2d; - var refractionHighSamplerSampler: sampler; - var refractionHighSampler: texture_2d; - #endif - #endif - #endif - - #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness,_SAMPLERNAME_,thickness) - #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity,_SAMPLERNAME_,refractionIntensity) - #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity,_SAMPLERNAME_,translucencyIntensity) - #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor,_SAMPLERNAME_,translucencyColor) -#endif - #ifdef IBL_CDF_FILTERING var icdfSamplerSampler: sampler; var icdfSampler: texture_2d; diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx index f7e3de2798a..c664ab9513c 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx @@ -45,15 +45,10 @@ #define CUSTOM_FRAGMENT_DEFINITIONS #include -#include +#include #include #include -#include #include -#include -#include -#include -#include // _____________________________ MAIN FUNCTION ____________________________ @fragment @@ -93,12 +88,12 @@ fn main(input: FragmentInputs) -> FragmentOutputs { uniforms.vBaseColor #ifdef ALBEDO , baseColorFromTexture - , uniforms.baseColorInfos + , uniforms.vBaseColorInfos #endif , uniforms.baseWeight #ifdef BASE_WEIGHT , baseWeightFromTexture - , uniforms.baseWeightInfos + , uniforms.vBaseWeightInfos #endif #ifdef OPACITY , opacityMap @@ -148,125 +143,70 @@ fn main(input: FragmentInputs) -> FragmentOutputs { var reflectivityOut: reflectivityOutParams; -#if defined(REFLECTIVITY) - var surfaceMetallicOrReflectivityColorMap: vec4f = textureSample(reflectivitySampler, reflectivitySamplerSampler, fragmentInputs.vReflectivityUV + uvOffset); - var baseReflectivity: vec4f = surfaceMetallicOrReflectivityColorMap; - #ifndef METALLICWORKFLOW - #ifdef REFLECTIVITY_GAMMA - surfaceMetallicOrReflectivityColorMap = toLinearSpaceVec4(surfaceMetallicOrReflectivityColorMap); - #endif - surfaceMetallicOrReflectivityColorMap = vec4f(surfaceMetallicOrReflectivityColorMap.rgb * uniforms.vReflectivityInfos.y, surfaceMetallicOrReflectivityColorMap.a); - #endif -#endif - -#if defined(MICROSURFACEMAP) - var microSurfaceTexel: vec4f = textureSample(microSurfaceSampler, microSurfaceSamplerSampler, fragmentInputs.vMicroSurfaceSamplerUV + uvOffset) * uniforms.vMicroSurfaceSamplerInfos.y; +#ifdef METALLIC_ROUGHNESS + var metallicRoughnessFromTexture: vec4f = textureSample(baseMetalRoughSampler, baseMetalRoughSamplerSampler, fragmentInputs.vBaseMetalRoughUV + uvOffset); #endif #ifdef BASE_DIFFUSE_ROUGHNESS var baseDiffuseRoughnessFromTexture: f32 = textureSample(baseDiffuseRoughnessSampler, baseDiffuseRoughnessSamplerSampler, fragmentInputs.vBaseDiffuseRoughnessUV + uvOffset).x; #endif -#ifdef METALLICWORKFLOW - var metallicReflectanceFactors: vec4f = uniforms.vMetallicReflectanceFactors; - #ifdef REFLECTANCE - var reflectanceFactorsMap: vec4f = textureSample(reflectanceSampler, reflectanceSamplerSampler, fragmentInputs.vReflectanceUV + uvOffset); - #ifdef REFLECTANCE_GAMMA - reflectanceFactorsMap = toLinearSpaceVec4(reflectanceFactorsMap); - #endif +var specularColor: vec4f = uniforms.vSpecularColor; +#ifdef SPECULAR_COLOR + var specularColorFromTexture: vec4f = textureSample(specularColorSampler, specularColorSamplerSampler, fragmentInputs.vSpecularColorUV + uvOffset); + #ifdef SPECULAR_COLOR_GAMMA + specularColorFromTexture = toLinearSpaceVec4(specularColorFromTexture); + #endif - metallicReflectanceFactors = vec4f(metallicReflectanceFactors.rgb * reflectanceFactorsMap.rgb, metallicReflectanceFactors.a); + specularColor = vec4f(specularColor.rgb * specularColorFromTexture.rgb, specularColor.a); +#endif +#ifdef SPECULAR_WEIGHT + var specularWeightFromTexture: vec4f = textureSample(specularWeightSampler, specularWeightSamplerSampler, fragmentInputs.vSpecularWeightUV + uvOffset); + #ifdef SPECULAR_WEIGHT_GAMMA + specularWeightFromTexture = toLinearSpaceVec4(specularWeightFromTexture); #endif - #ifdef METALLIC_REFLECTANCE - var metallicReflectanceFactorsMap: vec4f = textureSample(metallicReflectanceSampler, metallicReflectanceSamplerSampler, fragmentInputs.vMetallicReflectanceUV + uvOffset); - #ifdef METALLIC_REFLECTANCE_GAMMA - metallicReflectanceFactorsMap = toLinearSpaceVec4(metallicReflectanceFactorsMap); - #endif - #ifndef METALLIC_REFLECTANCE_USE_ALPHA_ONLY - metallicReflectanceFactors = vec4f(metallicReflectanceFactors.rgb * metallicReflectanceFactorsMap.rgb, metallicReflectanceFactors.a); - #endif - metallicReflectanceFactors.a *= metallicReflectanceFactorsMap.a; + // If loaded from a glTF, the specular_weight is stored in the alpha channel. + // Otherwise, it's expected to just be a greyscale texture. + #ifdef SPECULAR_WEIGHT_USE_ALPHA_ONLY + specularColor.a *= specularWeightFromTexture.a; + #else + specularColor = vec4f(specularColor.rgb * specularWeightFromTexture.rgb, specularColor.a); #endif #endif reflectivityOut = reflectivityBlock( - uniforms.vReflectivityColor - #ifdef METALLICWORKFLOW + uniforms.vReflectanceInfo , surfaceAlbedo - , metallicReflectanceFactors - #endif - , uniforms.baseDiffuseRoughness + , specularColor + , uniforms.vBaseDiffuseRoughness #ifdef BASE_DIFFUSE_ROUGHNESS , baseDiffuseRoughnessFromTexture - , uniforms.baseDiffuseRoughnessInfos + , uniforms.vBaseDiffuseRoughnessInfos #endif - #ifdef REFLECTIVITY - , uniforms.vReflectivityInfos - , surfaceMetallicOrReflectivityColorMap + #ifdef METALLIC_ROUGHNESS + , vec3f(uniforms.vBaseMetalRoughInfos, 1.0f) + , metallicRoughnessFromTexture #endif - #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED) + #if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) , aoOut.ambientOcclusionColor #endif - #ifdef MICROSURFACEMAP - , microSurfaceTexel - #endif #ifdef DETAIL , detailColor , uniforms.vDetailInfos #endif ); - var microSurface: f32 = reflectivityOut.microSurface; var roughness: f32 = reflectivityOut.roughness; var diffuseRoughness: f32 = reflectivityOut.diffuseRoughness; - #ifdef METALLICWORKFLOW - surfaceAlbedo = reflectivityOut.surfaceAlbedo; - #endif - #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED) + #if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) aoOut.ambientOcclusionColor = reflectivityOut.ambientOcclusionColor; #endif - // _____________________________ Alpha Fresnel ___________________________________ - #ifdef ALPHAFRESNEL - #if defined(ALPHATEST) || defined(ALPHABLEND) - var alphaFresnelOut: alphaFresnelOutParams; - - alphaFresnelOut = alphaFresnelBlock( - normalW, - viewDirectionW, - alpha, - microSurface - ); - - alpha = alphaFresnelOut.alpha; - #endif - #endif - // _____________________________ Compute Geometry info _________________________________ #include - // _____________________________ Anisotropy _______________________________________ - #ifdef ANISOTROPIC - var anisotropicOut: anisotropicOutParams; - - #ifdef ANISOTROPIC_TEXTURE - var anisotropyMapData: vec3f = textureSample(anisotropySampler, anisotropySamplerSampler, fragmentInputs.vAnisotropyUV + uvOffset).rgb * uniforms.vAnisotropyInfos.y; - #endif - - anisotropicOut = anisotropicBlock( - uniforms.vAnisotropy, - roughness, - #ifdef ANISOTROPIC_TEXTURE - anisotropyMapData, - #endif - TBN, - normalW, - viewDirectionW - ); - #endif - // _____________________________ Reflection Info _______________________________________ #ifdef REFLECTION var reflectionOut: reflectionOutParams; @@ -284,9 +224,6 @@ fn main(input: FragmentInputs) -> FragmentOutputs { #endif #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX) , NdotVUnclamped - #endif - #ifdef LINEARSPECULARREFLECTION - , roughness #endif , reflectionSampler , reflectionSamplerSampler @@ -326,336 +263,34 @@ fn main(input: FragmentInputs) -> FragmentOutputs { #endif // ___________________ Compute Reflectance aka R0 F0 info _________________________ - #include - - // ________________________________ Sheen ______________________________ - #ifdef SHEEN - var sheenOut: sheenOutParams; - - #ifdef SHEEN_TEXTURE - var sheenMapData: vec4f = textureSample(sheenSampler, sheenSamplerSampler, fragmentInputs.vSheenUV + uvOffset); - #endif - #if defined(SHEEN_ROUGHNESS) && defined(SHEEN_TEXTURE_ROUGHNESS) && !defined(SHEEN_USE_ROUGHNESS_FROM_MAINTEXTURE) - var sheenMapRoughnessData: vec4f = textureSample(sheenRoughnessSampler, sheenRoughnessSamplerSampler, fragmentInputs.vSheenRoughnessUV + uvOffset) * uniforms.vSheenInfos.w; - #endif - - sheenOut = sheenBlock( - uniforms.vSheenColor - #ifdef SHEEN_ROUGHNESS - , uniforms.vSheenRoughness - #if defined(SHEEN_TEXTURE_ROUGHNESS) && !defined(SHEEN_USE_ROUGHNESS_FROM_MAINTEXTURE) - , sheenMapRoughnessData - #endif - #endif - , roughness - #ifdef SHEEN_TEXTURE - , sheenMapData - , uniforms.vSheenInfos.y - #endif - , reflectanceF0 - #ifdef SHEEN_LINKWITHALBEDO - , baseColor - , surfaceAlbedo - #endif - #ifdef ENVIRONMENTBRDF - , NdotV - , environmentBrdf - #endif - #if defined(REFLECTION) && defined(ENVIRONMENTBRDF) - , AARoughnessFactors - , uniforms.vReflectionMicrosurfaceInfos - , uniforms.vReflectionInfos - , uniforms.vReflectionColor - , uniforms.vLightingIntensity - , reflectionSampler - , reflectionSamplerSampler - , reflectionOut.reflectionCoords - , NdotVUnclamped - #ifndef LODBASEDMICROSFURACE - , reflectionLowSampler - , reflectionLowSamplerSampler - , reflectionHighSampler - , reflectionHighSamplerSampler - #endif - #ifdef REALTIME_FILTERING - , uniforms.vReflectionFilteringInfo - #endif - #if !defined(REFLECTIONMAP_SKYBOX) && defined(RADIANCEOCCLUSION) - , seo - #endif - #if !defined(REFLECTIONMAP_SKYBOX) && defined(HORIZONOCCLUSION) && defined(BUMP) && defined(REFLECTIONMAP_3D) - , eho - #endif - #endif - ); - - #ifdef SHEEN_LINKWITHALBEDO - surfaceAlbedo = sheenOut.surfaceAlbedo; - #endif - #endif - - // _____________ Shared Iridescence and Clear Coat data _________________ - #ifdef CLEARCOAT - #ifdef CLEARCOAT_TEXTURE - var clearCoatMapData: vec2f = textureSample(clearCoatSampler, clearCoatSamplerSampler, fragmentInputs.vClearCoatUV + uvOffset).rg * uniforms.vClearCoatInfos.y; - #endif - #endif - - // _____________________________ Iridescence ____________________________ - #ifdef IRIDESCENCE - var iridescenceOut: iridescenceOutParams; - - #ifdef IRIDESCENCE_TEXTURE - var iridescenceMapData: vec2f = textureSample(iridescenceSampler, iridescenceSamplerSampler, fragmentInputs.vIridescenceUV + uvOffset).rg * uniforms.vIridescenceInfos.y; - #endif - #ifdef IRIDESCENCE_THICKNESS_TEXTURE - var iridescenceThicknessMapData: vec2f = textureSample(iridescenceThicknessSampler, iridescenceThicknessSamplerSampler, fragmentInputs.vIridescenceThicknessUV + uvOffset).rg * uniforms.vIridescenceInfos.w; - #endif - - iridescenceOut = iridescenceBlock( - uniforms.vIridescenceParams - , NdotV - , specularEnvironmentR0 - #ifdef IRIDESCENCE_TEXTURE - , iridescenceMapData - #endif - #ifdef IRIDESCENCE_THICKNESS_TEXTURE - , iridescenceThicknessMapData - #endif - #ifdef CLEARCOAT - , NdotVUnclamped - , uniforms.vClearCoatParams - #ifdef CLEARCOAT_TEXTURE - , clearCoatMapData - #endif - #endif - ); - - var iridescenceIntensity: f32 = iridescenceOut.iridescenceIntensity; - specularEnvironmentR0 = iridescenceOut.specularEnvironmentR0; - #endif - - // _____________________________ Clear Coat ____________________________ - var clearcoatOut: clearcoatOutParams; - - #ifdef CLEARCOAT - #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) && !defined(CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE) - var clearCoatMapRoughnessData: vec4f = textureSample(clearCoatRoughnessSampler, clearCoatRoughnessSamplerSampler, fragmentInputs.vClearCoatRoughnessUV + uvOffset) * uniforms.vClearCoatInfos.w; - #endif - - #if defined(CLEARCOAT_TINT) && defined(CLEARCOAT_TINT_TEXTURE) - var clearCoatTintMapData: vec4f = textureSample(clearCoatTintSampler, clearCoatTintSamplerSampler, fragmentInputs.vClearCoatTintUV + uvOffset); - #endif - - #ifdef CLEARCOAT_BUMP - var clearCoatBumpMapData: vec4f = textureSample(clearCoatBumpSampler, clearCoatBumpSamplerSampler, fragmentInputs.vClearCoatBumpUV + uvOffset); - #endif - - clearcoatOut = clearcoatBlock( - fragmentInputs.vPositionW - , geometricNormalW - , viewDirectionW - , uniforms.vClearCoatParams - #if defined(CLEARCOAT_TEXTURE_ROUGHNESS) && !defined(CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE) - , clearCoatMapRoughnessData - #endif - , specularEnvironmentR0 - #ifdef CLEARCOAT_TEXTURE - , clearCoatMapData - #endif - #ifdef CLEARCOAT_TINT - , uniforms.vClearCoatTintParams - , uniforms.clearCoatColorAtDistance - , uniforms.vClearCoatRefractionParams - #ifdef CLEARCOAT_TINT_TEXTURE - , clearCoatTintMapData - #endif - #endif - #ifdef CLEARCOAT_BUMP - , uniforms.vClearCoatBumpInfos - , clearCoatBumpMapData - , fragmentInputs.vClearCoatBumpUV - #if defined(TANGENT) && defined(NORMAL) - , mat3x3(input.vTBN0, input.vTBN1, input.vTBN2) - #else - , uniforms.vClearCoatTangentSpaceParams - #endif - #ifdef OBJECTSPACE_NORMALMAP - , uniforms.normalMatrix - #endif - #endif - #if defined(FORCENORMALFORWARD) && defined(NORMAL) - , faceNormal - #endif - #ifdef REFLECTION - , uniforms.vReflectionMicrosurfaceInfos - , uniforms.vReflectionInfos - , uniforms.vReflectionColor - , uniforms.vLightingIntensity - , reflectionSampler - , reflectionSamplerSampler - #ifndef LODBASEDMICROSFURACE - , reflectionLowSampler - , reflectionLowSamplerSampler - , reflectionHighSampler - , reflectionHighSamplerSampler - #endif - #ifdef REALTIME_FILTERING - , uniforms.vReflectionFilteringInfo - #endif - #endif - #if defined(CLEARCOAT_BUMP) || defined(TWOSIDEDLIGHTING) - , select(-1., 1., fragmentInputs.frontFacing) - #endif - ); - #else - clearcoatOut.specularEnvironmentR0 = specularEnvironmentR0; - #endif + var reflectanceF0: f32 = reflectivityOut.reflectanceF0; + var specularEnvironmentR0: vec3f = reflectivityOut.colorReflectanceF0; + var specularEnvironmentR90: vec3f = reflectivityOut.colorReflectanceF90; // _________________________ Specular Environment Reflectance __________________________ - #include - - // ___________________________________ SubSurface ______________________________________ - var subSurfaceOut: subSurfaceOutParams; - - #ifdef SUBSURFACE - #ifdef SS_THICKNESSANDMASK_TEXTURE - var thicknessMap: vec4f = textureSample(thicknessSampler, thicknessSamplerSampler, fragmentInputs.vThicknessUV + uvOffset); - #endif - - #ifdef SS_REFRACTIONINTENSITY_TEXTURE - var refractionIntensityMap: vec4f = textureSample(refractionIntensitySampler, refractionIntensitySamplerSampler, fragmentInputs.vRefractionIntensityUV + uvOffset); - #endif - - #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE - var translucencyIntensityMap: vec4f = textureSample(translucencyIntensitySampler, translucencyIntensitySamplerSampler, fragmentInputs.vTranslucencyIntensityUV + uvOffset); - #endif - - #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE - var translucencyColorMap: vec4f = textureSample(translucencyColorSampler, translucencyColorSamplerSampler, fragmentInputs.vTranslucencyColorUV + uvOffset); - #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE_GAMMA - translucencyColorMap = toLinearSpaceVec4(translucencyColorMap); - #endif - #endif - - subSurfaceOut = subSurfaceBlock( - uniforms.vSubSurfaceIntensity - , uniforms.vThicknessParam - , uniforms.vTintColor - , normalW - #ifdef LEGACY_SPECULAR_ENERGY_CONSERVATION - , vec3f(max(colorSpecularEnvironmentReflectance.r, max(colorSpecularEnvironmentReflectance.g, colorSpecularEnvironmentReflectance.b))) - #else - , baseSpecularEnvironmentReflectance - #endif - #ifdef SS_THICKNESSANDMASK_TEXTURE - , thicknessMap - #endif - #ifdef SS_REFRACTIONINTENSITY_TEXTURE - , refractionIntensityMap - #endif - #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE - , translucencyIntensityMap - #endif - #ifdef REFLECTION - #ifdef SS_TRANSLUCENCY - , uniforms.reflectionMatrix - #ifdef USESPHERICALFROMREFLECTIONMAP - #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX) - , reflectionOut.irradianceVector - #endif - #if defined(REALTIME_FILTERING) - , reflectionSampler - , reflectionSamplerSampler - , uniforms.vReflectionFilteringInfo - #ifdef IBL_CDF_FILTERING - , icdfSampler - , icdfSamplerSampler - #endif - #endif - #endif - #ifdef USEIRRADIANCEMAP - , irradianceSampler - , irradianceSamplerSampler - #endif - #endif - #endif - #if defined(SS_REFRACTION) || defined(SS_TRANSLUCENCY) - , surfaceAlbedo - #endif - #ifdef SS_REFRACTION - , fragmentInputs.vPositionW - , viewDirectionW - , scene.view - , uniforms.vRefractionInfos - , uniforms.refractionMatrix - , uniforms.vRefractionMicrosurfaceInfos - , uniforms.vLightingIntensity - #ifdef SS_LINKREFRACTIONTOTRANSPARENCY - , alpha - #endif - #ifdef SS_LODINREFRACTIONALPHA - , NdotVUnclamped - #endif - #ifdef SS_LINEARSPECULARREFRACTION - , roughness - #endif - , alphaG - , refractionSampler - , refractionSamplerSampler - #ifndef LODBASEDMICROSFURACE - , refractionLowSampler - , refractionLowSamplerSampler - , refractionHighSampler - , refractionHighSamplerSampler - #endif - #ifdef ANISOTROPIC - , anisotropicOut - #endif - #ifdef REALTIME_FILTERING - , uniforms.vRefractionFilteringInfo - #endif - #ifdef SS_USE_LOCAL_REFRACTIONMAP_CUBIC - , uniforms.vRefractionPosition - , uniforms.vRefractionSize - #endif - #ifdef SS_DISPERSION - , dispersion - #endif - #endif - #ifdef SS_TRANSLUCENCY - , uniforms.vDiffusionDistance - , uniforms.vTranslucencyColor - #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE - , translucencyColorMap - #endif - #endif - ); - - #ifdef SS_REFRACTION - surfaceAlbedo = subSurfaceOut.surfaceAlbedo; - #ifdef SS_LINKREFRACTIONTOTRANSPARENCY - alpha = subSurfaceOut.alpha; - #endif - #endif - #else - subSurfaceOut.specularEnvironmentReflectance = colorSpecularEnvironmentReflectance; - #endif + #include // _____________________________ Direct Lighting Info __________________________________ #include - - #include[0..maxSimultaneousLights] + // TODO: lightFragment references cloatcoatOut, subsurfaceOut, etc. + // lightFragment shouldn't know what layer it's working on. + // Instead, we should define values for lightFragment to use here, defining + // conditions like F0, F90, etc. + // Or we could convert lightFragment to be a function that returns the diffuse + // or specular contribution, given the reflectance inputs? + // e.g. lighting contributions from clearcoat, subsurface, base layer, etc. need + // to be computed separately. + // #include[0..maxSimultaneousLights] // _____________________________ Compute Final Lit Components ________________________ - #include + #include #endif // UNLIT #include #define CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION - #include + #include #include #include(color, finalColor) diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx index 493232d3fa5..87435b5a65a 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx @@ -37,41 +37,12 @@ attribute color: vec4f; #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity) #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive) #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap) -#include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity) -#include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler) -#include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance) -#include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance) +#include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough) +#include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight) +#include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor) #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal) -#ifdef CLEARCOAT - #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat) - #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness) - #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump) - #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint) -#endif - -#ifdef IRIDESCENCE - #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence) - #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness) -#endif - -#ifdef SHEEN - #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen) - #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness) -#endif - -#ifdef ANISOTROPIC - #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy) -#endif - -#ifdef SUBSURFACE - #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness) - #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity) - #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity) - #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor) -#endif - // Output varying vPositionW: vec3f; #if DEBUGMODE > 0 @@ -179,7 +150,7 @@ fn main(input : VertexInputs) -> FragmentInputs { // Bend the normal towards the viewer based on the diffuse roughness var viewDirectionW: vec3f = normalize(scene.vEyePosition.xyz - vertexOutputs.vPositionW); var NdotV: f32 = max(dot(vertexOutputs.vNormalW, viewDirectionW), 0.0); - var roughNormal: vec3f = mix(vertexOutputs.vNormalW, viewDirectionW, (0.5 * (1.0 - NdotV)) * uniforms.baseDiffuseRoughness); + var roughNormal: vec3f = mix(vertexOutputs.vNormalW, viewDirectionW, (0.5 * (1.0 - NdotV)) * uniforms.vBaseDiffuseRoughness); var reflectionVector: vec3f = (uniforms.reflectionMatrix * vec4f(roughNormal, 0)).xyz; #else var reflectionVector: vec3f = (uniforms.reflectionMatrix * vec4f(vertexOutputs.vNormalW, 0)).xyz; @@ -228,7 +199,7 @@ fn main(input : VertexInputs) -> FragmentInputs { #include[3..7] - #include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,BaseColor,_MATRIXNAME_,baseColor,_INFONAME_,baseColorInfos.x) + #include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,BaseColor,_MATRIXNAME_,baseColor,_INFONAME_,BaseColorInfos.x) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_MATRIXNAME_,baseWeight,_INFONAME_,BaseWeightInfos.x) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_MATRIXNAME_,baseDiffuseRoughness,_INFONAME_,BaseDiffuseRoughnessInfos.x) #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) @@ -236,42 +207,12 @@ fn main(input : VertexInputs) -> FragmentInputs { #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_MATRIXNAME_,opacity,_INFONAME_,OpacityInfos.x) #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_MATRIXNAME_,emissive,_INFONAME_,EmissiveInfos.x) #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_MATRIXNAME_,lightmap,_INFONAME_,LightmapInfos.x) - #include(_DEFINENAME_,REFLECTIVITY,_VARYINGNAME_,Reflectivity,_MATRIXNAME_,reflectivity,_INFONAME_,ReflectivityInfos.x) - #include(_DEFINENAME_,MICROSURFACEMAP,_VARYINGNAME_,MicroSurfaceSampler,_MATRIXNAME_,microSurfaceSampler,_INFONAME_,MicroSurfaceSamplerInfos.x) - #include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance,_MATRIXNAME_,metallicReflectance,_INFONAME_,MetallicReflectanceInfos.x) - #include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance,_MATRIXNAME_,reflectance,_INFONAME_,ReflectanceInfos.x) + #include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough,_MATRIXNAME_,baseMetalRough,_INFONAME_,BaseMetalRoughInfos.x) + #include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight,_MATRIXNAME_,specularWeight,_INFONAME_,SpecularWeightInfos.x) + #include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor,_MATRIXNAME_,specularColor,_INFONAME_,SpecularColorInfos.x) #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump,_MATRIXNAME_,bump,_INFONAME_,BumpInfos.x) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_MATRIXNAME_,decal,_INFONAME_,DecalInfos.x) -#ifdef CLEARCOAT - #include(_DEFINENAME_,CLEARCOAT_TEXTURE,_VARYINGNAME_,ClearCoat,_MATRIXNAME_,clearCoat,_INFONAME_,ClearCoatInfos.x) - #include(_DEFINENAME_,CLEARCOAT_TEXTURE_ROUGHNESS,_VARYINGNAME_,ClearCoatRoughness,_MATRIXNAME_,clearCoatRoughness,_INFONAME_,ClearCoatInfos.z) - #include(_DEFINENAME_,CLEARCOAT_BUMP,_VARYINGNAME_,ClearCoatBump,_MATRIXNAME_,clearCoatBump,_INFONAME_,ClearCoatBumpInfos.x) - #include(_DEFINENAME_,CLEARCOAT_TINT_TEXTURE,_VARYINGNAME_,ClearCoatTint,_MATRIXNAME_,clearCoatTint,_INFONAME_,ClearCoatTintInfos.x) -#endif - -#ifdef IRIDESCENCE - #include(_DEFINENAME_,IRIDESCENCE_TEXTURE,_VARYINGNAME_,Iridescence,_MATRIXNAME_,iridescence,_INFONAME_,IridescenceInfos.x) - #include(_DEFINENAME_,IRIDESCENCE_THICKNESS_TEXTURE,_VARYINGNAME_,IridescenceThickness,_MATRIXNAME_,iridescenceThickness,_INFONAME_,IridescenceInfos.z) -#endif - -#ifdef SHEEN - #include(_DEFINENAME_,SHEEN_TEXTURE,_VARYINGNAME_,Sheen,_MATRIXNAME_,sheen,_INFONAME_,SheenInfos.x) - #include(_DEFINENAME_,SHEEN_TEXTURE_ROUGHNESS,_VARYINGNAME_,SheenRoughness,_MATRIXNAME_,sheenRoughness,_INFONAME_,SheenInfos.z) - -#endif - -#ifdef ANISOTROPIC - #include(_DEFINENAME_,ANISOTROPIC_TEXTURE,_VARYINGNAME_,Anisotropy,_MATRIXNAME_,anisotropy,_INFONAME_,AnisotropyInfos.x) -#endif - -#ifdef SUBSURFACE - #include(_DEFINENAME_,SS_THICKNESSANDMASK_TEXTURE,_VARYINGNAME_,Thickness,_MATRIXNAME_,thickness,_INFONAME_,ThicknessInfos.x) - #include(_DEFINENAME_,SS_REFRACTIONINTENSITY_TEXTURE,_VARYINGNAME_,RefractionIntensity,_MATRIXNAME_,refractionIntensity,_INFONAME_,RefractionIntensityInfos.x) - #include(_DEFINENAME_,SS_TRANSLUCENCYINTENSITY_TEXTURE,_VARYINGNAME_,TranslucencyIntensity,_MATRIXNAME_,translucencyIntensity,_INFONAME_,TranslucencyIntensityInfos.x) - #include(_DEFINENAME_,SS_TRANSLUCENCYCOLOR_TEXTURE,_VARYINGNAME_,TranslucencyColor,_MATRIXNAME_,translucencyColor,_INFONAME_,TranslucencyColorInfos.x) -#endif - // TBN #include 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 7eb0ceafa45..b28df370c69 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 @@ -73,14 +73,16 @@ export class PBRMaterialPropertyGridComponent extends React.Component - + {material instanceof PBRMaterial && ( + + )} )} - - + {material instanceof PBRMaterial && ( + + )} + {material instanceof PBRMaterial && ( + + )} - (material.metallicReflectanceTexture = texture)} - onTextureRemoved={() => (material.metallicReflectanceTexture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> - (material.reflectanceTexture = texture)} - onTextureRemoved={() => (material.reflectanceTexture = null)} - material={material} - onSelectionChangedObservable={this.props.onSelectionChangedObservable} - onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} - /> + {material instanceof PBRMaterial && ( + (material.metallicReflectanceTexture = texture)} + onTextureRemoved={() => (material.metallicReflectanceTexture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + )} + {material instanceof PBRMaterial && ( + (material.reflectanceTexture = texture)} + onTextureRemoved={() => (material.reflectanceTexture = null)} + material={material} + onSelectionChangedObservable={this.props.onSelectionChangedObservable} + onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} + /> + )} {material instanceof PBRMaterial && ( <> diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts index 1d35b075425..4f228ad3d07 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts @@ -1,7 +1,6 @@ import type { Nullable } from "core/types"; import { Color3 } from "core/Maths/math.color"; import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -75,7 +74,7 @@ export class KHR_materials_pbrSpecularGlossiness implements IGLTFLoaderExtension // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax private _loadSpecularGlossinessPropertiesAsync(context: string, properties: IKHRMaterialsPbrSpecularGlossiness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterial)) { throw new Error(`${context}: Material type not supported`); } @@ -85,18 +84,10 @@ export class KHR_materials_pbrSpecularGlossiness implements IGLTFLoaderExtension babylonMaterial.roughness = null; if (properties.diffuseFactor) { - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseColor = Color3.FromArray(properties.diffuseFactor); - } else { - babylonMaterial.albedoColor = Color3.FromArray(properties.diffuseFactor); - } + babylonMaterial.albedoColor = Color3.FromArray(properties.diffuseFactor); babylonMaterial.alpha = properties.diffuseFactor[3]; } else { - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseColor = Color3.White(); - } else { - babylonMaterial.albedoColor = Color3.White(); - } + babylonMaterial.albedoColor = Color3.White(); } babylonMaterial.reflectivityColor = properties.specularFactor ? Color3.FromArray(properties.specularFactor) : Color3.White(); @@ -106,11 +97,7 @@ export class KHR_materials_pbrSpecularGlossiness implements IGLTFLoaderExtension promises.push( this._loader.loadTextureInfoAsync(`${context}/diffuseTexture`, properties.diffuseTexture, (texture) => { texture.name = `${babylonMaterial.name} (Diffuse)`; - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseColorTexture = texture; - } else { - babylonMaterial.albedoTexture = texture; - } + babylonMaterial.albedoTexture = texture; }) ); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts index a55f058dca1..ae0db035daf 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts @@ -90,32 +90,62 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { const promises = new Array>(); - if (properties.specularFactor !== undefined) { - babylonMaterial.metallicF0Factor = properties.specularFactor; - } + if (babylonMaterial instanceof OpenPBRMaterial) { + if (properties.specularFactor !== undefined) { + babylonMaterial.specularWeight = properties.specularFactor; + } - if (properties.specularColorFactor !== undefined) { - babylonMaterial.metallicReflectanceColor = Color3.FromArray(properties.specularColorFactor); - } + if (properties.specularColorFactor !== undefined) { + babylonMaterial.specularColor = Color3.FromArray(properties.specularColorFactor); + } - if (properties.specularTexture) { - (properties.specularTexture as ITextureInfo).nonColorData = true; - promises.push( - this._loader.loadTextureInfoAsync(`${context}/specularTexture`, properties.specularTexture, (texture) => { - texture.name = `${babylonMaterial.name} (Specular)`; - babylonMaterial.metallicReflectanceTexture = texture; - babylonMaterial.useOnlyMetallicFromMetallicReflectanceTexture = true; - }) - ); - } + if (properties.specularTexture) { + (properties.specularTexture as ITextureInfo).nonColorData = true; + promises.push( + this._loader.loadTextureInfoAsync(`${context}/specularTexture`, properties.specularTexture, (texture) => { + texture.name = `${babylonMaterial.name} (Specular)`; + babylonMaterial.specularWeightTexture = texture; + babylonMaterial.useSpecularWeightFromTextureAlpha = true; + }) + ); + } + + if (properties.specularColorTexture) { + promises.push( + this._loader.loadTextureInfoAsync(`${context}/specularColorTexture`, properties.specularColorTexture, (texture) => { + texture.name = `${babylonMaterial.name} (Specular Color)`; + babylonMaterial.specularColorTexture = texture; + }) + ); + } + } else { + if (properties.specularFactor !== undefined) { + babylonMaterial.metallicF0Factor = properties.specularFactor; + } + + if (properties.specularColorFactor !== undefined) { + babylonMaterial.metallicReflectanceColor = Color3.FromArray(properties.specularColorFactor); + } - if (properties.specularColorTexture) { - promises.push( - this._loader.loadTextureInfoAsync(`${context}/specularColorTexture`, properties.specularColorTexture, (texture) => { - texture.name = `${babylonMaterial.name} (Specular Color)`; - babylonMaterial.reflectanceTexture = texture; - }) - ); + if (properties.specularTexture) { + (properties.specularTexture as ITextureInfo).nonColorData = true; + promises.push( + this._loader.loadTextureInfoAsync(`${context}/specularTexture`, properties.specularTexture, (texture) => { + texture.name = `${babylonMaterial.name} (Specular)`; + babylonMaterial.metallicReflectanceTexture = texture; + babylonMaterial.useOnlyMetallicFromMetallicReflectanceTexture = true; + }) + ); + } + + if (properties.specularColorTexture) { + promises.push( + this._loader.loadTextureInfoAsync(`${context}/specularColorTexture`, properties.specularColorTexture, (texture) => { + texture.name = `${babylonMaterial.name} (Specular Color)`; + babylonMaterial.reflectanceTexture = texture; + }) + ); + } } // eslint-disable-next-line github/no-then diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index 5e16205e167..76f6932f2b3 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -63,10 +63,9 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { if (!babylonMaterial.albedoTexture) { babylonMaterial.albedoColor.toLinearSpaceToRef(babylonMaterial.albedoColor, useExactSrgbConversions); } - } - - if (!babylonMaterial.reflectivityTexture) { - babylonMaterial.reflectivityColor.toLinearSpaceToRef(babylonMaterial.reflectivityColor, useExactSrgbConversions); + if (!babylonMaterial.reflectivityTexture) { + babylonMaterial.reflectivityColor.toLinearSpaceToRef(babylonMaterial.reflectivityColor, useExactSrgbConversions); + } } return await promise; diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index 16e5f3a8509..5a12ad340d3 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -2151,8 +2151,13 @@ export class GLTFLoader implements IGLTFLoader { } } - babylonMaterial.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; - babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; + if (babylonMaterial instanceof PBRMaterial) { + babylonMaterial.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; + babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; + } else if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.baseMetalness = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; + babylonMaterial.specularRoughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; + } if (properties.baseColorTexture) { promises.push( @@ -2172,13 +2177,19 @@ export class GLTFLoader implements IGLTFLoader { promises.push( this.loadTextureInfoAsync(`${context}/metallicRoughnessTexture`, properties.metallicRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Metallic Roughness)`; - babylonMaterial.metallicTexture = texture; + if (babylonMaterial instanceof OpenPBRMaterial) { + babylonMaterial.baseMetalRoughTexture = texture; + } else { + babylonMaterial.metallicTexture = texture; + } }) ); - babylonMaterial.useMetallnessFromMetallicTextureBlue = true; - babylonMaterial.useRoughnessFromMetallicTextureGreen = true; - babylonMaterial.useRoughnessFromMetallicTextureAlpha = false; + if (babylonMaterial instanceof PBRMaterial) { + babylonMaterial.useMetallnessFromMetallicTextureBlue = true; + babylonMaterial.useRoughnessFromMetallicTextureGreen = true; + babylonMaterial.useRoughnessFromMetallicTextureAlpha = false; + } } } @@ -2255,8 +2266,10 @@ export class GLTFLoader implements IGLTFLoader { babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage; babylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage; babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE; - babylonMaterial.metallic = 1; - babylonMaterial.roughness = 1; + if (babylonMaterial instanceof PBRMaterial) { + babylonMaterial.metallic = 1; + babylonMaterial.roughness = 1; + } return babylonMaterial; } From 2022b170813f1cb233e1f6813211bacf1e13d806 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Thu, 17 Jul 2025 13:57:17 -0700 Subject: [PATCH 19/23] Change albedo to base color --- .../core/src/Materials/PBR/openPbrMaterial.ts | 2 +- .../openpbrBlockAlbedoOpacity.fx | 115 +++++++++++++++++ .../openpbrFragmentDeclaration.fx | 2 +- .../openpbrFragmentSamplersDeclaration.fx | 2 +- .../dev/core/src/Shaders/openpbr.fragment.fx | 7 +- .../dev/core/src/Shaders/openpbr.vertex.fx | 4 +- .../openpbrBlockAlbedoOpacity.fx | 116 ++++++++++++++++++ .../openpbrFragmentSamplersDeclaration.fx | 2 +- .../core/src/ShadersWGSL/openpbr.fragment.fx | 6 +- .../core/src/ShadersWGSL/openpbr.vertex.fx | 4 +- 10 files changed, 245 insertions(+), 15 deletions(-) create mode 100644 packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockAlbedoOpacity.fx create mode 100644 packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockAlbedoOpacity.fx diff --git a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts index 24486482428..a6f43d0eef8 100644 --- a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts @@ -483,7 +483,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { public baseColorTexture: BaseTexture; @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "baseColorTexture") // eslint-disable-next-line @typescript-eslint/no-unused-vars - private _baseColorTexture: Sampler = new Sampler("base_color", "baseColor", "ALBEDO"); + private _baseColorTexture: Sampler = new Sampler("base_color", "baseColor", "BASE_COLOR"); /** * Roughness of the diffuse lobe. diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockAlbedoOpacity.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockAlbedoOpacity.fx new file mode 100644 index 00000000000..1053198bdf4 --- /dev/null +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockAlbedoOpacity.fx @@ -0,0 +1,115 @@ +struct albedoOpacityOutParams +{ + vec3 surfaceAlbedo; + float alpha; +}; + +#define pbr_inline +albedoOpacityOutParams albedoOpacityBlock( + in vec4 vAlbedoColor +#ifdef BASE_COLOR + ,in vec4 albedoTexture + ,in vec2 albedoInfos +#endif + , in float baseWeight +#ifdef BASE_WEIGHT + , in vec4 baseWeightTexture + , in vec2 vBaseWeightInfos +#endif +#ifdef OPACITY + ,in vec4 opacityMap + ,in vec2 vOpacityInfos +#endif +#ifdef DETAIL + ,in vec4 detailColor + ,in vec4 vDetailInfos +#endif +#ifdef DECAL + ,in vec4 decalColor + ,in vec4 vDecalInfos +#endif +) +{ + albedoOpacityOutParams outParams; + // _____________________________ Albedo Information ______________________________ + vec3 surfaceAlbedo = vAlbedoColor.rgb; + float alpha = vAlbedoColor.a; + + #ifdef BASE_COLOR + #if defined(ALPHAFROMALBEDO) || defined(ALPHATEST) + alpha *= albedoTexture.a; + #endif + + #ifdef BASE_COLOR_GAMMA + surfaceAlbedo *= toLinearSpace(albedoTexture.rgb); + #else + surfaceAlbedo *= albedoTexture.rgb; + #endif + + surfaceAlbedo *= albedoInfos.y; + #endif + + #ifndef DECAL_AFTER_DETAIL + #include + #endif + + #if defined(VERTEXCOLOR) || defined(INSTANCESCOLOR) && defined(INSTANCES) + surfaceAlbedo *= vColor.rgb; + #endif + + #ifdef DETAIL + float detailAlbedo = 2.0 * mix(0.5, detailColor.r, vDetailInfos.y); + surfaceAlbedo.rgb = surfaceAlbedo.rgb * detailAlbedo * detailAlbedo; // should be pow(detailAlbedo, 2.2) but detailAlbedo² is close enough and cheaper to compute + #endif + + #ifdef DECAL_AFTER_DETAIL + #include + #endif + + #define CUSTOM_FRAGMENT_UPDATE_ALBEDO + + // According to OpenPBR: + // - for metals, base_weight is a factor to the base_color (F0, thus surfaceAlbedo in + // Babylons.js). + // - for dielectrics, base_weight is a factor to the diffuse BRDF (i.e. it should be + // applied in computeDiffuseLighting), but with the diffuse model *currently* used + // in Babylon.js, factoring it into the surfaceAlbedo is equivalent. + surfaceAlbedo *= baseWeight; + #ifdef BASE_WEIGHT + surfaceAlbedo *= baseWeightTexture.r; + #endif + + // _____________________________ Alpha Information _______________________________ + #ifdef OPACITY + #ifdef OPACITYRGB + alpha = getLuminance(opacityMap.rgb); + #else + alpha *= opacityMap.a; + #endif + + alpha *= vOpacityInfos.y; + #endif + + #if defined(VERTEXALPHA) || defined(INSTANCESCOLOR) && defined(INSTANCES) + alpha *= vColor.a; + #endif + + #if !defined(SS_LINKREFRACTIONTOTRANSPARENCY) && !defined(ALPHAFRESNEL) + #ifdef ALPHATEST + #if DEBUGMODE != 88 + if (alpha < ALPHATESTVALUE) + discard; + #endif + + #ifndef ALPHABLEND + // Prevent to blend with the canvas. + alpha = 1.0; + #endif + #endif + #endif + + outParams.surfaceAlbedo = surfaceAlbedo; + outParams.alpha = alpha; + + return outParams; +} diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx index fe2d0db835c..4bbc1106acd 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx @@ -15,7 +15,7 @@ uniform float visibility; uniform vec3 vAmbientColor; // Samplers -#ifdef ALBEDO +#ifdef BASE_COLOR uniform vec2 vBaseColorInfos; #endif diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx index 24783ded67f..673e42f5069 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx @@ -1,4 +1,4 @@ -#include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,BaseColor,_SAMPLERNAME_,baseColor) +#include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor,_SAMPLERNAME_,baseColor) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_SAMPLERNAME_,baseWeight) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_SAMPLERNAME_,baseDiffuseRoughness) #include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_SAMPLERNAME_,ambient) diff --git a/packages/dev/core/src/Shaders/openpbr.fragment.fx b/packages/dev/core/src/Shaders/openpbr.fragment.fx index 18f8c4fd57d..6ce8d8bde9f 100644 --- a/packages/dev/core/src/Shaders/openpbr.fragment.fx +++ b/packages/dev/core/src/Shaders/openpbr.fragment.fx @@ -60,7 +60,7 @@ precision highp float; #define CUSTOM_FRAGMENT_DEFINITIONS -#include +#include #include #include #include @@ -83,7 +83,7 @@ void main(void) { // _____________________________ Albedo & Opacity ______________________________ albedoOpacityOutParams albedoOpacityOut; -#ifdef ALBEDO +#ifdef BASE_COLOR vec4 baseColorFromTexture = texture2D(baseColorSampler, vBaseColorUV + uvOffset); #endif @@ -101,7 +101,7 @@ void main(void) { albedoOpacityOut = albedoOpacityBlock( vBaseColor - #ifdef ALBEDO + #ifdef BASE_COLOR , baseColorFromTexture , vBaseColorInfos #endif @@ -145,7 +145,6 @@ void main(void) { - // _____________________________ AO _______________________________ ambientOcclusionOutParams aoOut; diff --git a/packages/dev/core/src/Shaders/openpbr.vertex.fx b/packages/dev/core/src/Shaders/openpbr.vertex.fx index 3bf844c7304..7836a4b20ee 100644 --- a/packages/dev/core/src/Shaders/openpbr.vertex.fx +++ b/packages/dev/core/src/Shaders/openpbr.vertex.fx @@ -33,7 +33,7 @@ attribute vec4 color; #include #include -#include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,Albedo) +#include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness) #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail) @@ -212,7 +212,7 @@ void main(void) { #include[3..7] - #include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,Albedo,_MATRIXNAME_,albedo,_INFONAME_,AlbedoInfos.x) + #include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor,_MATRIXNAME_,albedo,_INFONAME_,BaseColorInfos.x) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_MATRIXNAME_,baseWeight,_INFONAME_,BaseWeightInfos.x) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_MATRIXNAME_,baseDiffuseRoughness,_INFONAME_,BaseDiffuseRoughnessInfos.x) #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockAlbedoOpacity.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockAlbedoOpacity.fx new file mode 100644 index 00000000000..beeab50f8ec --- /dev/null +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockAlbedoOpacity.fx @@ -0,0 +1,116 @@ +struct albedoOpacityOutParams +{ + surfaceAlbedo: vec3f, + alpha: f32 +}; + +#define pbr_inline +fn albedoOpacityBlock( + vAlbedoColor: vec4f +#ifdef BASE_COLOR + ,albedoTexture: vec4f + ,albedoInfos: vec2f +#endif + , baseWeight: f32 +#ifdef BASE_WEIGHT + , baseWeightTexture: vec4f + , vBaseWeightInfos: vec2f +#endif +#ifdef OPACITY + ,opacityMap: vec4f + ,vOpacityInfos: vec2f +#endif +#ifdef DETAIL + ,detailColor: vec4f + ,vDetailInfos: vec4f +#endif +#ifdef DECAL + ,decalColor: vec4f + ,vDecalInfos: vec4f +#endif +) -> albedoOpacityOutParams +{ + var outParams: albedoOpacityOutParams; + // _____________________________ Albedo Information ______________________________ + var surfaceAlbedo: vec3f = vAlbedoColor.rgb; + var alpha: f32 = vAlbedoColor.a; + + #ifdef BASE_COLOR + #if defined(ALPHAFROMALBEDO) || defined(ALPHATEST) + alpha *= albedoTexture.a; + #endif + + #ifdef BASE_COLOR_GAMMA + surfaceAlbedo *= toLinearSpaceVec3(albedoTexture.rgb); + #else + surfaceAlbedo *= albedoTexture.rgb; + #endif + + surfaceAlbedo *= albedoInfos.y; + #endif + + #ifndef DECAL_AFTER_DETAIL + #include + #endif + + #if defined(VERTEXCOLOR) || defined(INSTANCESCOLOR) && defined(INSTANCES) + surfaceAlbedo *= fragmentInputs.vColor.rgb; + #endif + + #ifdef DETAIL + var detailAlbedo: f32 = 2.0 * mix(0.5, detailColor.r, vDetailInfos.y); + surfaceAlbedo = surfaceAlbedo.rgb * detailAlbedo * detailAlbedo; // should be pow(detailAlbedo, 2.2) but detailAlbedo² is close enough and cheaper to compute + #endif + + #ifdef DECAL_AFTER_DETAIL + #include + #endif + + #define CUSTOM_FRAGMENT_UPDATE_ALBEDO + + // According to OpenPBR: + // - for metals, base_weight is a factor to the base_color (F0, thus surfaceAlbedo in + // Babylons.js). + // - for dielectrics, base_weight is a factor to the diffuse BRDF (i.e. it should be + // applied in computeDiffuseLighting), but with the diffuse model *currently* used + // in Babylon.js, factoring it into the surfaceAlbedo is equivalent. + surfaceAlbedo *= baseWeight; + #ifdef BASE_WEIGHT + surfaceAlbedo *= baseWeightTexture.r; + #endif + + // _____________________________ Alpha Information _______________________________ + #ifdef OPACITY + #ifdef OPACITYRGB + alpha = getLuminance(opacityMap.rgb); + #else + alpha *= opacityMap.a; + #endif + + alpha *= vOpacityInfos.y; + #endif + + #if defined(VERTEXALPHA) || defined(INSTANCESCOLOR) && defined(INSTANCES) + alpha *= fragmentInputs.vColor.a; + #endif + + #if !defined(SS_LINKREFRACTIONTOTRANSPARENCY) && !defined(ALPHAFRESNEL) + #ifdef ALPHATEST + #if DEBUGMODE != 88 + if (alpha < ALPHATESTVALUE) { + discard; + } + #endif + + #ifndef ALPHABLEND + // Prevent to blend with the canvas. + alpha = 1.0; + #endif + #endif + #endif + + outParams.surfaceAlbedo = surfaceAlbedo; + outParams.alpha = alpha; + + return outParams; +} diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx index 9fb632b5df8..dd80615a595 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx @@ -1,4 +1,4 @@ -#include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,BaseColor,_SAMPLERNAME_,baseColor) +#include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor,_SAMPLERNAME_,baseColor) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_SAMPLERNAME_,baseWeight) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_SAMPLERNAME_,baseDiffuseRoughness) #include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_SAMPLERNAME_,ambient) diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx index c664ab9513c..c7c5c09738d 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx @@ -44,7 +44,7 @@ #define CUSTOM_FRAGMENT_DEFINITIONS -#include +#include #include #include #include @@ -68,7 +68,7 @@ fn main(input: FragmentInputs) -> FragmentOutputs { // _____________________________ Albedo & Opacity ______________________________ var albedoOpacityOut: albedoOpacityOutParams; -#ifdef ALBEDO +#ifdef BASE_COLOR var baseColorFromTexture: vec4f = textureSample(baseColorSampler, baseColorSamplerSampler, fragmentInputs.vBaseColorUV + uvOffset); #endif @@ -86,7 +86,7 @@ fn main(input: FragmentInputs) -> FragmentOutputs { albedoOpacityOut = albedoOpacityBlock( uniforms.vBaseColor - #ifdef ALBEDO + #ifdef BASE_COLOR , baseColorFromTexture , uniforms.vBaseColorInfos #endif diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx index 87435b5a65a..10fc816f04f 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx @@ -29,7 +29,7 @@ attribute color: vec4f; #include #include -#include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,Albedo) +#include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,Albedo) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness) #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail) @@ -199,7 +199,7 @@ fn main(input : VertexInputs) -> FragmentInputs { #include[3..7] - #include(_DEFINENAME_,ALBEDO,_VARYINGNAME_,BaseColor,_MATRIXNAME_,baseColor,_INFONAME_,BaseColorInfos.x) + #include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor,_MATRIXNAME_,baseColor,_INFONAME_,BaseColorInfos.x) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_MATRIXNAME_,baseWeight,_INFONAME_,BaseWeightInfos.x) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_MATRIXNAME_,baseDiffuseRoughness,_INFONAME_,BaseDiffuseRoughnessInfos.x) #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) From d71b50609175b0b3b58a8488dda21aab45636140 Mon Sep 17 00:00:00 2001 From: Michael Bond Date: Thu, 10 Jul 2025 12:34:52 -0700 Subject: [PATCH 20/23] WIP glTFLoader dynamic material load --- .../Extensions/KHR_materials_anisotropy.ts | 24 +++-- .../2.0/Extensions/KHR_materials_clearcoat.ts | 70 +++++++++---- .../KHR_materials_diffuse_transmission.ts | 77 +++++++++------ .../Extensions/KHR_materials_dispersion.ts | 40 +++++--- .../KHR_materials_emissive_strength.ts | 17 +++- .../glTF/2.0/Extensions/KHR_materials_ior.ts | 29 ++++-- .../Extensions/KHR_materials_iridescence.ts | 54 +++++++--- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 98 +++++++++---------- 8 files changed, 270 insertions(+), 139 deletions(-) diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts index c425c295da5..a9d2cb7e2eb 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -21,6 +22,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_anisotropy) */ @@ -60,8 +63,15 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial)); @@ -70,23 +80,23 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { } private async _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsAnisotropy, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); - babylonMaterial.anisotropy.isEnabled = true; + (babylonMaterial as PBRMaterial).anisotropy.isEnabled = true; - babylonMaterial.anisotropy.intensity = properties.anisotropyStrength ?? 0; - babylonMaterial.anisotropy.angle = properties.anisotropyRotation ?? 0; + (babylonMaterial as PBRMaterial).anisotropy.intensity = properties.anisotropyStrength ?? 0; + (babylonMaterial as PBRMaterial).anisotropy.angle = properties.anisotropyRotation ?? 0; if (properties.anisotropyTexture) { (properties.anisotropyTexture as ITextureInfo).nonColorData = true; promises.push( this._loader.loadTextureInfoAsync(`${context}/anisotropyTexture`, properties.anisotropyTexture, (texture) => { texture.name = `${babylonMaterial.name} (Anisotropy Intensity)`; - babylonMaterial.anisotropy.texture = texture; + (babylonMaterial as PBRMaterial).anisotropy.texture = texture; }) ); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts index bc394cd1040..034c3b49f8b 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts @@ -1,6 +1,8 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; +import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +23,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md) * [Playground Sample](https://www.babylonjs-playground.com/frame.html#7F7PN6#8) @@ -61,46 +65,58 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } + if (!(babylonMaterial instanceof PBRMaterialClass)) { + throw new Error(`${context}: Material type not supported`); + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadClearCoatPropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadClearCoatPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); await Promise.all(promises); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadClearCoatPropertiesAsync(context: string, properties: IKHRMaterialsClearcoat, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); - - babylonMaterial.clearCoat.isEnabled = true; - babylonMaterial.clearCoat.useRoughnessFromMainTexture = false; - babylonMaterial.clearCoat.remapF0OnInterfaceChange = false; + let coatRoughness = 0; + let coatWeight = 0; + let coatWeightTexture: Nullable = null; + let coatRoughnessTexture: Nullable = null; + let coatNormalTexture: Nullable = null; + let coatNormalTextureScale = 1; if (properties.clearcoatFactor != undefined) { - babylonMaterial.clearCoat.intensity = properties.clearcoatFactor; + coatWeight = properties.clearcoatFactor; } else { - babylonMaterial.clearCoat.intensity = 0; + coatWeight = 0; } if (properties.clearcoatTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/clearcoatTexture`, properties.clearcoatTexture, (texture) => { texture.name = `${babylonMaterial.name} (ClearCoat)`; - babylonMaterial.clearCoat.texture = texture; + coatWeightTexture = texture; }) ); } if (properties.clearcoatRoughnessFactor != undefined) { - babylonMaterial.clearCoat.roughness = properties.clearcoatRoughnessFactor; + coatRoughness = properties.clearcoatRoughnessFactor; } else { - babylonMaterial.clearCoat.roughness = 0; + coatRoughness = 0; } if (properties.clearcoatRoughnessTexture) { @@ -108,7 +124,7 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/clearcoatRoughnessTexture`, properties.clearcoatRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (ClearCoat Roughness)`; - babylonMaterial.clearCoat.textureRoughness = texture; + coatRoughnessTexture = texture; }) ); } @@ -118,19 +134,37 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/clearcoatNormalTexture`, properties.clearcoatNormalTexture, (texture) => { texture.name = `${babylonMaterial.name} (ClearCoat Normal)`; - babylonMaterial.clearCoat.bumpTexture = texture; + coatNormalTexture = texture; }) ); babylonMaterial.invertNormalMapX = !babylonMaterial.getScene().useRightHandedSystem; babylonMaterial.invertNormalMapY = babylonMaterial.getScene().useRightHandedSystem; if (properties.clearcoatNormalTexture.scale != undefined) { - babylonMaterial.clearCoat.bumpTexture!.level = properties.clearcoatNormalTexture.scale; + coatNormalTextureScale = properties.clearcoatNormalTexture.scale; } } // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => {}); + return Promise.all(promises).then(() => { + if (useOpenPBR) { + // eslint-disable-next-line github/no-then + return; + } + const material = babylonMaterial as PBRMaterial; + material.clearCoat.isEnabled = true; + material.clearCoat.useRoughnessFromMainTexture = false; + material.clearCoat.remapF0OnInterfaceChange = false; + material.clearCoat.intensity = coatWeight; + material.clearCoat.texture = coatWeightTexture; + material.clearCoat.roughness = coatRoughness; + material.clearCoat.textureRoughness = coatRoughnessTexture; + + material.clearCoat.bumpTexture = coatNormalTexture; + if (coatNormalTexture) { + material.clearCoat.bumpTexture!.level = coatNormalTextureScale; + } + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts index 5507ebfb1ab..91930aef943 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts @@ -1,6 +1,7 @@ /* eslint-disable github/no-then */ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -23,6 +24,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825) * !!! Experimental Extension Subject to Changes !!! @@ -66,8 +69,15 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadTranslucentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); @@ -77,62 +87,71 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async private _loadTranslucentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDiffuseTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const pbrMaterial = babylonMaterial; - - // Enables "translucency" texture which represents diffusely-transmitted light. - pbrMaterial.subSurface.isTranslucencyEnabled = true; - - // Since this extension models thin-surface transmission only, we must make the - // internal IOR == 1.0 and set the thickness to 0. - pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; - pbrMaterial.subSurface.minimumThickness = 0.0; - pbrMaterial.subSurface.maximumThickness = 0.0; - - // Tint color will be used for transmission. - pbrMaterial.subSurface.useAlbedoToTintTranslucency = false; + let translucencyWeight = 0.0; + let translucencyWeightTexture: Nullable; + let translucencyColor = Color3.White(); + let translucencyColorTexture: Nullable; if (extension.diffuseTransmissionFactor !== undefined) { - pbrMaterial.subSurface.translucencyIntensity = extension.diffuseTransmissionFactor; - } else { - pbrMaterial.subSurface.translucencyIntensity = 0.0; - pbrMaterial.subSurface.isTranslucencyEnabled = false; - return Promise.resolve(); + translucencyWeight = extension.diffuseTransmissionFactor; } const promises = new Array>(); - pbrMaterial.subSurface.useGltfStyleTextures = true; - if (extension.diffuseTransmissionTexture) { (extension.diffuseTransmissionTexture as ITextureInfo).nonColorData = true; promises.push( this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionTexture`, extension.diffuseTransmissionTexture).then((texture: BaseTexture) => { texture.name = `${babylonMaterial.name} (Diffuse Transmission)`; - pbrMaterial.subSurface.translucencyIntensityTexture = texture; + translucencyWeightTexture = texture; }) ); } if (extension.diffuseTransmissionColorFactor !== undefined) { - pbrMaterial.subSurface.translucencyColor = Color3.FromArray(extension.diffuseTransmissionColorFactor); - } else { - pbrMaterial.subSurface.translucencyColor = Color3.White(); + translucencyColor = Color3.FromArray(extension.diffuseTransmissionColorFactor); } if (extension.diffuseTransmissionColorTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionColorTexture`, extension.diffuseTransmissionColorTexture).then((texture: BaseTexture) => { texture.name = `${babylonMaterial.name} (Diffuse Transmission Color)`; - pbrMaterial.subSurface.translucencyColorTexture = texture; + translucencyColorTexture = texture; }) ); } - return Promise.all(promises).then(() => {}); + return Promise.all(promises).then(() => { + const pbrMaterial = babylonMaterial as PBRMaterial; + + // Enables "translucency" texture which represents diffusely-transmitted light. + pbrMaterial.subSurface.isTranslucencyEnabled = true; + + // Since this extension models thin-surface transmission only, we must make the + // internal IOR == 1.0 and set the thickness to 0. + pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; + pbrMaterial.subSurface.minimumThickness = 0.0; + pbrMaterial.subSurface.maximumThickness = 0.0; + + // Tint color will be used for transmission. + pbrMaterial.subSurface.useAlbedoToTintTranslucency = false; + + pbrMaterial.subSurface.translucencyIntensity = translucencyWeight; + if (translucencyWeight === 0.0) { + pbrMaterial.subSurface.isTranslucencyEnabled = false; + return; + } + + pbrMaterial.subSurface.useGltfStyleTextures = true; + pbrMaterial.subSurface.translucencyIntensityTexture = translucencyWeightTexture; + + pbrMaterial.subSurface.translucencyColor = translucencyColor; + pbrMaterial.subSurface.translucencyColorTexture = translucencyColorTexture; + }); } } 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 1a99485b358..31bbbf7b404 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 @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +22,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/87bd64a7f5e23c84b6aef2e6082069583ed0ddb4/extensions/2.0/Khronos/KHR_materials_dispersion/README.md) * @experimental @@ -61,29 +64,44 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadDispersionPropertiesAsync(extensionContext, material, babylonMaterial, extension)); + promises.push(this._loadDispersionPropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadDispersionPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDispersion): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadDispersionPropertiesAsync( + context: string, + material: IMaterial, + babylonMaterial: Material, + extension: IKHRMaterialsDispersion, + useOpenPBR: boolean = false + ): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { 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_diffuse_transmission extensions. - if (!babylonMaterial.subSurface.isRefractionEnabled || !extension.dispersion) { - return Promise.resolve(); + if (!useOpenPBR) { + // If transparency isn't enabled already, this extension shouldn't do anything. + // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions. + if (!(babylonMaterial as PBRMaterial).subSurface.isRefractionEnabled || !extension.dispersion) { + return Promise.resolve(); + } + (babylonMaterial as PBRMaterial).subSurface.isDispersionEnabled = true; + (babylonMaterial as PBRMaterial).subSurface.dispersion = extension.dispersion; } - babylonMaterial.subSurface.isDispersionEnabled = true; - babylonMaterial.subSurface.dispersion = extension.dispersion; return Promise.resolve(); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts index 47785510fe7..0b334915f2c 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -22,6 +22,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md) */ @@ -61,8 +63,15 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } // eslint-disable-next-line github/no-then return await this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial).then(() => { this._loadEmissiveProperties(extensionContext, extension, babylonMaterial); @@ -71,7 +80,7 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { } private _loadEmissiveProperties(context: string, properties: IKHRMaterialsEmissiveStrength, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts index ad70f99ba58..6c3479fa586 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -21,6 +22,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_ior/README.md) */ @@ -65,26 +68,38 @@ export class KHR_materials_ior implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadIorPropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadIorPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadIorPropertiesAsync(context: string, properties: IKHRMaterialsIor, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } + let indexOfRefraction = 1.5; if (properties.ior !== undefined) { - babylonMaterial.indexOfRefraction = properties.ior; + indexOfRefraction = properties.ior; } else { - babylonMaterial.indexOfRefraction = KHR_materials_ior._DEFAULT_IOR; + indexOfRefraction = KHR_materials_ior._DEFAULT_IOR; + } + + if (!useOpenPBR) { + (babylonMaterial as PBRMaterial).indexOfRefraction = indexOfRefraction; } return Promise.resolve(); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts index 11168af02da..22271fa7961 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts @@ -1,6 +1,8 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; +import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +23,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_iridescence/README.md) */ @@ -60,36 +64,48 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadIridescencePropertiesAsync(context: string, properties: IKHRMaterialsIridescence, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const promises = new Array>(); + let iridescenceWeight = 0.0; + let iridescenceWeightTexture: Nullable = null; + let iridescenceIor = 1.3; + let iridescenceThicknessMinimum = 100; + let iridescenceThicknessMaximum = 400; + let iridescenceThicknessTexture: Nullable = null; - babylonMaterial.iridescence.isEnabled = true; + const promises = new Array>(); - babylonMaterial.iridescence.intensity = properties.iridescenceFactor ?? 0; - babylonMaterial.iridescence.indexOfRefraction = properties.iridescenceIor ?? (properties as any).iridescenceIOR ?? 1.3; - babylonMaterial.iridescence.minimumThickness = properties.iridescenceThicknessMinimum ?? 100; - babylonMaterial.iridescence.maximumThickness = properties.iridescenceThicknessMaximum ?? 400; + iridescenceWeight = properties.iridescenceFactor ?? 0; + iridescenceIor = properties.iridescenceIor ?? (properties as any).iridescenceIOR ?? 1.3; + iridescenceThicknessMinimum = properties.iridescenceThicknessMinimum ?? 100; + iridescenceThicknessMaximum = properties.iridescenceThicknessMaximum ?? 400; if (properties.iridescenceTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/iridescenceTexture`, properties.iridescenceTexture, (texture) => { texture.name = `${babylonMaterial.name} (Iridescence)`; - babylonMaterial.iridescence.texture = texture; + iridescenceWeightTexture = texture; }) ); } @@ -98,13 +114,23 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/iridescenceThicknessTexture`, properties.iridescenceThicknessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Iridescence Thickness)`; - babylonMaterial.iridescence.thicknessTexture = texture; + iridescenceThicknessTexture = texture; }) ); } // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => {}); + return Promise.all(promises).then(() => { + const pbrMaterial = babylonMaterial as PBRMaterial; + pbrMaterial.iridescence.isEnabled = true; + + pbrMaterial.iridescence.intensity = iridescenceWeight; + pbrMaterial.iridescence.indexOfRefraction = iridescenceIor; + pbrMaterial.iridescence.minimumThickness = iridescenceThicknessMinimum; + pbrMaterial.iridescence.maximumThickness = iridescenceThicknessMaximum; + pbrMaterial.iridescence.texture = iridescenceWeightTexture; + pbrMaterial.iridescence.thicknessTexture = iridescenceThicknessTexture; + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index 5a12ad340d3..9b91b05253d 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -16,8 +16,8 @@ import type { AnimationGroup } from "core/Animations/animationGroup"; import { Bone } from "core/Bones/bone"; import { Skeleton } from "core/Bones/skeleton"; import { Material } from "core/Materials/material"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { ITextureCreationOptions } from "core/Materials/Textures/texture"; import { Texture } from "core/Materials/Textures/texture"; @@ -87,6 +87,8 @@ import { GetTypedArrayConstructor } from "core/Buffers/bufferUtils"; export { GLTFFileLoader }; +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + interface ILoaderProperty extends IProperty { _activeLoaderExtensionFunctions: { [id: string]: boolean; @@ -400,6 +402,14 @@ export class GLTFLoader implements IGLTFLoader { await this._loadExtensionsAsync(); + if (this.parent.useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } + const loadingToReadyCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.READY]}`; const loadingToCompleteCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.COMPLETE]}`; @@ -2128,45 +2138,44 @@ export class GLTFLoader implements IGLTFLoader { } private _loadMaterialMetallicRoughnessPropertiesAsync(context: string, properties: IMaterialPbrMetallicRoughness, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); if (properties) { - if (babylonMaterial instanceof OpenPBRMaterial) { + if (this.parent.useOpenPBR) { + const mat = babylonMaterial as OpenPBRMaterial; if (properties.baseColorFactor) { - babylonMaterial.baseColor = Color3.FromArray(properties.baseColorFactor); - babylonMaterial.geometryOpacity = properties.baseColorFactor[3]; + mat.baseColor = Color3.FromArray(properties.baseColorFactor); + mat.geometryOpacity = properties.baseColorFactor[3]; } else { - babylonMaterial.baseColor = Color3.White(); + mat.baseColor = Color3.White(); } + mat.baseMetalness = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; + mat.specularRoughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; } else { + const mat = babylonMaterial as PBRMaterial; if (properties.baseColorFactor) { - babylonMaterial.albedoColor = Color3.FromArray(properties.baseColorFactor); - babylonMaterial.alpha = properties.baseColorFactor[3]; + mat.albedoColor = Color3.FromArray(properties.baseColorFactor); + mat.alpha = properties.baseColorFactor[3]; } else { - babylonMaterial.albedoColor = Color3.White(); + mat.albedoColor = Color3.White(); } - } - - if (babylonMaterial instanceof PBRMaterial) { - babylonMaterial.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; - babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; - } else if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseMetalness = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; - babylonMaterial.specularRoughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; + mat.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; + mat.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; + babylonMaterial = mat; } if (properties.baseColorTexture) { promises.push( this.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Base Color)`; - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseColorTexture = texture; + if (this.parent.useOpenPBR) { + (babylonMaterial as OpenPBRMaterial).baseColorTexture = texture; } else { - babylonMaterial.albedoTexture = texture; + (babylonMaterial as PBRMaterial).albedoTexture = texture; } }) ); @@ -2177,18 +2186,18 @@ export class GLTFLoader implements IGLTFLoader { promises.push( this.loadTextureInfoAsync(`${context}/metallicRoughnessTexture`, properties.metallicRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Metallic Roughness)`; - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseMetalRoughTexture = texture; + if (this.parent.useOpenPBR) { + (babylonMaterial as OpenPBRMaterial).baseMetalRoughTexture = texture; } else { - babylonMaterial.metallicTexture = texture; + (babylonMaterial as PBRMaterial).metallicTexture = texture; } }) ); - if (babylonMaterial instanceof PBRMaterial) { - babylonMaterial.useMetallnessFromMetallicTextureBlue = true; - babylonMaterial.useRoughnessFromMetallicTextureGreen = true; - babylonMaterial.useRoughnessFromMetallicTextureAlpha = false; + if (!this.parent.useOpenPBR) { + (babylonMaterial as PBRMaterial).useMetallnessFromMetallicTextureBlue = true; + (babylonMaterial as PBRMaterial).useRoughnessFromMetallicTextureGreen = true; + (babylonMaterial as PBRMaterial).useRoughnessFromMetallicTextureAlpha = false; } } } @@ -2252,12 +2261,7 @@ export class GLTFLoader implements IGLTFLoader { private _createDefaultMaterial(name: string, babylonDrawMode: number): Material { this._babylonScene._blockEntityCollection = !!this._assetContainer; - let babylonMaterial; - if (this.parent.useOpenPBR) { - babylonMaterial = new OpenPBRMaterial(name, this._babylonScene); - } else { - babylonMaterial = new PBRMaterial(name, this._babylonScene); - } + const babylonMaterial = new PBRMaterialClass(name, this._babylonScene); babylonMaterial._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; // Moved to mesh so user can change materials on gltf meshes: babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation; @@ -2265,11 +2269,7 @@ export class GLTFLoader implements IGLTFLoader { babylonMaterial.enableSpecularAntiAliasing = true; babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage; babylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage; - babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE; - if (babylonMaterial instanceof PBRMaterial) { - babylonMaterial.metallic = 1; - babylonMaterial.roughness = 1; - } + babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_OPAQUE; return babylonMaterial; } @@ -2327,16 +2327,16 @@ export class GLTFLoader implements IGLTFLoader { * @returns A promise that resolves when the load is complete */ public loadMaterialBasePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.emissionColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); + if (this.parent.useOpenPBR) { + (babylonMaterial as OpenPBRMaterial).emissionColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); } else { - babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); + (babylonMaterial as PBRMaterial).emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0); } if (material.doubleSided) { babylonMaterial.backFaceCulling = false; @@ -2396,21 +2396,21 @@ export class GLTFLoader implements IGLTFLoader { * @param babylonMaterial The Babylon material */ public loadMaterialAlphaProperties(context: string, material: IMaterial, babylonMaterial: Material): void { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const baseColorTexture = babylonMaterial instanceof OpenPBRMaterial ? babylonMaterial.baseColorTexture : babylonMaterial.albedoTexture; + const baseColorTexture = this.parent.useOpenPBR ? (babylonMaterial as OpenPBRMaterial).baseColorTexture : (babylonMaterial as PBRMaterial).albedoTexture; const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE; switch (alphaMode) { case MaterialAlphaMode.OPAQUE: { - babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE; + babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_OPAQUE; babylonMaterial.alpha = 1.0; // Force alpha to 1.0 for opaque mode. break; } case MaterialAlphaMode.MASK: { - babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHATEST; + babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_ALPHATEST; babylonMaterial.alphaCutOff = material.alphaCutoff == undefined ? 0.5 : material.alphaCutoff; if (baseColorTexture) { baseColorTexture.hasAlpha = true; @@ -2418,7 +2418,7 @@ export class GLTFLoader implements IGLTFLoader { break; } case MaterialAlphaMode.BLEND: { - babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHABLEND; + babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_ALPHABLEND; if (baseColorTexture) { baseColorTexture.hasAlpha = true; babylonMaterial.useAlphaFromAlbedoTexture = true; @@ -2939,7 +2939,7 @@ export class GLTFLoader implements IGLTFLoader { return this._applyExtensions( material, "loadMaterialProperties", - (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial) + (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial, this.parent.useOpenPBR) ); } From ddefcfa5360e06a48bd1354f5b1f09f6222b28af Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Fri, 11 Jul 2025 08:42:43 -0700 Subject: [PATCH 21/23] Finish glTFLoader dynamic material load --- .../2.0/Extensions/KHR_materials_sheen.ts | 59 ++++++---- .../2.0/Extensions/KHR_materials_specular.ts | 27 +++-- .../Extensions/KHR_materials_transmission.ts | 104 +++++++++++------- .../2.0/Extensions/KHR_materials_volume.ts | 81 ++++++++++---- .../glTF/2.0/Extensions/MSFT_minecraftMesh.ts | 17 ++- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 27 +++-- .../src/glTF/2.0/glTFLoaderExtension.ts | 3 +- 7 files changed, 217 insertions(+), 101 deletions(-) diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts index 4816792a5e3..2a2a734fa02 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts @@ -1,6 +1,8 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; +import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -22,6 +24,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_sheen/README.md) * [Playground Sample](https://www.babylonjs-playground.com/frame.html#BNIZX6#4) @@ -62,46 +66,51 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadSheenPropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadSheenPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadSheenPropertiesAsync(context: string, properties: IKHRMaterialsSheen, babylonMaterial: Material, useOpenPBR: boolean): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const promises = new Array>(); + let sheenColor = Color3.Black(); + let sheenColorTexture: Nullable = null; + let sheenRoughness = 0.0; + let sheenRoughnessTexture: Nullable = null; - babylonMaterial.sheen.isEnabled = true; - babylonMaterial.sheen.intensity = 1; + const promises = new Array>(); if (properties.sheenColorFactor != undefined) { - babylonMaterial.sheen.color = Color3.FromArray(properties.sheenColorFactor); - } else { - babylonMaterial.sheen.color = Color3.Black(); + sheenColor = Color3.FromArray(properties.sheenColorFactor); } if (properties.sheenColorTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/sheenColorTexture`, properties.sheenColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Sheen Color)`; - babylonMaterial.sheen.texture = texture; + sheenColorTexture = texture; }) ); } if (properties.sheenRoughnessFactor !== undefined) { - babylonMaterial.sheen.roughness = properties.sheenRoughnessFactor; - } else { - babylonMaterial.sheen.roughness = 0; + sheenRoughness = properties.sheenRoughnessFactor; } if (properties.sheenRoughnessTexture) { @@ -109,16 +118,26 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/sheenRoughnessTexture`, properties.sheenRoughnessTexture, (texture) => { texture.name = `${babylonMaterial.name} (Sheen Roughness)`; - babylonMaterial.sheen.textureRoughness = texture; + sheenRoughnessTexture = texture; }) ); } - babylonMaterial.sheen.albedoScaling = true; - babylonMaterial.sheen.useRoughnessFromMainTexture = false; - // eslint-disable-next-line github/no-then - return Promise.all(promises).then(() => {}); + return Promise.all(promises).then(() => { + if (useOpenPBR) { + return; + } + const pbrMaterial = babylonMaterial as PBRMaterial; + pbrMaterial.sheen.isEnabled = true; + pbrMaterial.sheen.intensity = 1; + pbrMaterial.sheen.color = sheenColor; + pbrMaterial.sheen.texture = sheenColorTexture; + pbrMaterial.sheen.roughness = sheenRoughness; + pbrMaterial.sheen.textureRoughness = sheenRoughnessTexture; + pbrMaterial.sheen.albedoScaling = true; + pbrMaterial.sheen.useRoughnessFromMainTexture = false; + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts index ae0db035daf..94dc328cf07 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts @@ -1,6 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -24,6 +24,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_specular/README.md) */ @@ -63,18 +65,25 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadSpecularPropertiesAsync(extensionContext, extension, babylonMaterial)); + promises.push(this._loadSpecularPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // Handle the EXT_materials_specular_edge_color sub-extension // https://github.com/KhronosGroup/glTF/blob/2a1111b88f052cbd3e2d82abb9faee56e7494904/extensions/2.0/Vendor/EXT_materials_specular_edge_color/README.md - if (extension.extensions && extension.extensions.EXT_materials_specular_edge_color && babylonMaterial instanceof PBRMaterial) { + if (!useOpenPBR && extension.extensions && extension.extensions.EXT_materials_specular_edge_color) { const specularEdgeColorExtension = extension.extensions.EXT_materials_specular_edge_color as IEXTMaterialsSpecularEdgeColor; if (specularEdgeColorExtension.specularEdgeColorEnabled) { - babylonMaterial.brdf.dielectricSpecularModel = Constants.MATERIAL_DIELECTRIC_SPECULAR_MODEL_OPENPBR; - babylonMaterial.brdf.conductorSpecularModel = Constants.MATERIAL_CONDUCTOR_SPECULAR_MODEL_OPENPBR; + (babylonMaterial as PBRMaterial).brdf.dielectricSpecularModel = Constants.MATERIAL_DIELECTRIC_SPECULAR_MODEL_OPENPBR; + (babylonMaterial as PBRMaterial).brdf.conductorSpecularModel = Constants.MATERIAL_CONDUCTOR_SPECULAR_MODEL_OPENPBR; } } // eslint-disable-next-line github/no-then @@ -83,8 +92,8 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + private _loadSpecularPropertiesAsync(context: string, properties: IKHRMaterialsSpecular, babylonMaterial: Material, useOpenPBR: boolean): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts index 5f91a41d555..b404b2d822f 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts @@ -1,5 +1,6 @@ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; @@ -62,6 +63,8 @@ interface ITransmissionHelperOptions { clearColor?: Color4; } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * A class to handle setting up the rendering of opaque objects to be shown through transmissive objects. */ @@ -166,7 +169,7 @@ class TransmissionHelper { if (!material) { return false; } - if (material instanceof PBRMaterial && material.subSurface.isRefractionEnabled) { + if (material instanceof PBRMaterialClass && (material as any).subSurface.isRefractionEnabled) { return true; } return false; @@ -220,8 +223,8 @@ class TransmissionHelper { // If the material is transparent, make sure that it's added to the transparent list and removed from the opaque list const useTransmission = this._shouldRenderAsTransmission(mesh.material); if (useTransmission) { - if (mesh.material instanceof PBRMaterial) { - mesh.material.subSurface.refractionTexture = this._opaqueRenderTarget; + if (mesh.material instanceof PBRMaterialClass) { + (mesh.material as any).subSurface.refractionTexture = this._opaqueRenderTarget; } if (opaqueIdx !== -1) { this._opaqueMeshesCache.splice(opaqueIdx, 1); @@ -366,60 +369,87 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); + promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async - private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadTransparentPropertiesAsync( + context: string, + material: IMaterial, + babylonMaterial: Material, + extension: IKHRMaterialsTransmission, + useOpenPBR: boolean + ): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const pbrMaterial = babylonMaterial; - - // Enables "refraction" texture which represents transmitted light. - pbrMaterial.subSurface.isRefractionEnabled = true; - - // Since this extension models thin-surface transmission only, we must make IOR = 1.0 - pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; - // Albedo colour will tint transmission. - pbrMaterial.subSurface.useAlbedoToTintRefraction = true; + let transmissionWeight = 0.0; + let transmissionWeightTexture: Nullable = null; + const promises = new Array>(); if (extension.transmissionFactor !== undefined) { - pbrMaterial.subSurface.refractionIntensity = extension.transmissionFactor; - const scene = pbrMaterial.getScene() as unknown as ITransmissionHelperHolder; - if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper) { - new TransmissionHelper({}, pbrMaterial.getScene()); - } else if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper?._isRenderTargetValid()) { - // If the render target is not valid, recreate it. - scene._transmissionHelper?._setupRenderTargets(); - } + transmissionWeight = extension.transmissionFactor; } else { - pbrMaterial.subSurface.refractionIntensity = 0.0; - pbrMaterial.subSurface.isRefractionEnabled = false; return Promise.resolve(); } - - pbrMaterial.subSurface.minimumThickness = 0.0; - pbrMaterial.subSurface.maximumThickness = 0.0; if (extension.transmissionTexture) { (extension.transmissionTexture as ITextureInfo).nonColorData = true; // eslint-disable-next-line github/no-then - return this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, undefined).then((texture: BaseTexture) => { - texture.name = `${babylonMaterial.name} (Transmission)`; - pbrMaterial.subSurface.refractionIntensityTexture = texture; - pbrMaterial.subSurface.useGltfStyleTextures = true; - }); - } else { - return Promise.resolve(); + promises.push( + this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, (texture: BaseTexture) => { + texture.name = `${babylonMaterial.name} (Transmission)`; + transmissionWeightTexture = texture; + }) + ); } + + // eslint-disable-next-line github/no-then + return Promise.all(promises).then(() => { + if (useOpenPBR) { + return; + } + const pbrMaterial = babylonMaterial as PBRMaterial; + + // Enables "refraction" texture which represents transmitted light. + pbrMaterial.subSurface.isRefractionEnabled = transmissionWeight !== 0; + + // Since this extension models thin-surface transmission only, we must make IOR = 1.0 + pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; + + // Albedo colour will tint transmission. + pbrMaterial.subSurface.useAlbedoToTintRefraction = true; + + pbrMaterial.subSurface.refractionIntensity = transmissionWeight; + + if (transmissionWeight) { + const scene = pbrMaterial.getScene() as unknown as ITransmissionHelperHolder; + if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper) { + new TransmissionHelper({}, pbrMaterial.getScene()); + } else if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper?._isRenderTargetValid()) { + // If the render target is not valid, recreate it. + scene._transmissionHelper?._setupRenderTargets(); + } + } + pbrMaterial.subSurface.minimumThickness = 0.0; + pbrMaterial.subSurface.maximumThickness = 0.0; + pbrMaterial.subSurface.refractionIntensityTexture = transmissionWeightTexture; + pbrMaterial.subSurface.useGltfStyleTextures = true; + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts index 349cbd67c10..6b70b2453bf 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts @@ -1,7 +1,9 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Nullable } from "core/types"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; +import { Color3 } from "core/Maths/math.color"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -22,6 +24,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_volume/README.md) * @since 5.0.0 @@ -69,50 +73,85 @@ export class KHR_materials_volume implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } const promises = new Array>(); promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); - promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension)); + promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume): Promise { - if (!(babylonMaterial instanceof PBRMaterial)) { + private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume, useOpenPBR: boolean): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } + if (useOpenPBR) { + return Promise.resolve(); + } // If transparency isn't enabled already, this extension shouldn't do anything. // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions. - if ((!babylonMaterial.subSurface.isRefractionEnabled && !babylonMaterial.subSurface.isTranslucencyEnabled) || !extension.thicknessFactor) { + if ( + (!(babylonMaterial as PBRMaterial).subSurface.isRefractionEnabled && !(babylonMaterial as PBRMaterial).subSurface.isTranslucencyEnabled) || + !extension.thicknessFactor + ) { return Promise.resolve(); } - // IOR in this extension only affects interior. - babylonMaterial.subSurface.volumeIndexOfRefraction = babylonMaterial.indexOfRefraction; - const attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE; - babylonMaterial.subSurface.tintColorAtDistance = attenuationDistance; + let attenuationDistance = Number.MAX_VALUE; + const attenuationColor: Color3 = Color3.White(); + let thicknessTexture: Nullable = null; + let thicknessFactor = 0.0; + + const promises = new Array>(); + + attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE; if (extension.attenuationColor !== undefined && extension.attenuationColor.length == 3) { - babylonMaterial.subSurface.tintColor.copyFromFloats(extension.attenuationColor[0], extension.attenuationColor[1], extension.attenuationColor[2]); + attenuationColor.copyFromFloats(extension.attenuationColor[0], extension.attenuationColor[1], extension.attenuationColor[2]); } - babylonMaterial.subSurface.minimumThickness = 0.0; - babylonMaterial.subSurface.maximumThickness = extension.thicknessFactor; - babylonMaterial.subSurface.useThicknessAsDepth = true; + thicknessFactor = extension.thicknessFactor; if (extension.thicknessTexture) { (extension.thicknessTexture as ITextureInfo).nonColorData = true; // eslint-disable-next-line github/no-then - return this._loader.loadTextureInfoAsync(`${context}/thicknessTexture`, extension.thicknessTexture).then((texture: BaseTexture) => { - texture.name = `${babylonMaterial.name} (Thickness)`; - babylonMaterial.subSurface.thicknessTexture = texture; - babylonMaterial.subSurface.useGltfStyleTextures = true; - }); - } else { - return Promise.resolve(); + promises.push( + this._loader.loadTextureInfoAsync(`${context}/thicknessTexture`, extension.thicknessTexture, (texture: BaseTexture) => { + texture.name = `${babylonMaterial.name} (Thickness)`; + thicknessTexture = texture; + }) + ); } + + // eslint-disable-next-line github/no-then + return Promise.all(promises).then(() => { + if (useOpenPBR) { + return; + } + + const pbrMaterial = babylonMaterial as PBRMaterial; + // IOR in this extension only affects interior. + pbrMaterial.subSurface.volumeIndexOfRefraction = pbrMaterial.indexOfRefraction; + pbrMaterial.subSurface.tintColorAtDistance = attenuationDistance; + pbrMaterial.subSurface.tintColor = attenuationColor; + + pbrMaterial.subSurface.minimumThickness = 0.0; + pbrMaterial.subSurface.maximumThickness = thicknessFactor; + pbrMaterial.subSurface.useThicknessAsDepth = true; + if (thicknessTexture) { + pbrMaterial.subSurface.thicknessTexture = thicknessTexture; + pbrMaterial.subSurface.useGltfStyleTextures = true; + } + }); } } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts index f52207f3e74..ecb866e40c5 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +21,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** @internal */ // eslint-disable-next-line @typescript-eslint/naming-convention export class MSFT_minecraftMesh implements IGLTFLoaderExtension { @@ -45,10 +47,17 @@ export class MSFT_minecraftMesh implements IGLTFLoaderExtension { /** @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } if (extra) { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${extraContext}: Material type not supported`); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index 76f6932f2b3..4283dc3a8c7 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import type { Material } from "core/Materials/material"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { IMaterial } from "../glTFLoaderInterfaces"; import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; @@ -21,6 +21,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** @internal */ // eslint-disable-next-line @typescript-eslint/naming-convention export class MSFT_sRGBFactors implements IGLTFLoaderExtension { @@ -45,23 +47,30 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { /** @internal*/ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtraAsync(context, material, this.name, async (extraContext, extra) => { + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } if (extra) { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${extraContext}: Material type not supported`); } const promise = this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial); const useExactSrgbConversions = babylonMaterial.getScene().getEngine().useExactSrgbConversions; - if (babylonMaterial instanceof OpenPBRMaterial) { - if (!babylonMaterial.baseColorTexture) { - babylonMaterial.baseColor.toLinearSpaceToRef(babylonMaterial.baseColor, useExactSrgbConversions); + if (useOpenPBR) { + if (!(babylonMaterial as OpenPBRMaterial).baseColorTexture) { + (babylonMaterial as OpenPBRMaterial).baseColor.toLinearSpaceToRef((babylonMaterial as OpenPBRMaterial).baseColor, useExactSrgbConversions); } } else { - if (!babylonMaterial.albedoTexture) { - babylonMaterial.albedoColor.toLinearSpaceToRef(babylonMaterial.albedoColor, useExactSrgbConversions); + if (!(babylonMaterial as PBRMaterial).albedoTexture) { + (babylonMaterial as PBRMaterial).albedoColor.toLinearSpaceToRef((babylonMaterial as PBRMaterial).albedoColor, useExactSrgbConversions); } if (!babylonMaterial.reflectivityTexture) { babylonMaterial.reflectivityColor.toLinearSpaceToRef(babylonMaterial.reflectivityColor, useExactSrgbConversions); diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts index 72ae55dce23..15930ba12e6 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts @@ -127,9 +127,10 @@ export interface IGLTFLoaderExtension extends IGLTFBaseLoaderExtension, IDisposa * @param context The context when loading the asset * @param material The glTF material property * @param babylonMaterial The Babylon material + * @param useOpenPBR Load materials as OpenPBR materials instead of glTF PBR materials. * @returns A promise that resolves when the load is complete or null if not handled */ - loadMaterialPropertiesAsync?(context: string, material: IMaterial, babylonMaterial: Material): Nullable>; + loadMaterialPropertiesAsync?(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean): Nullable>; /** * Define this method to modify the default behavior when loading texture infos. From d23804d4546cadbe741cb5cb9f50c54dfd5441e4 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Fri, 18 Jul 2025 10:12:26 -0700 Subject: [PATCH 22/23] Fix dynamic loading of materials in glTF loader --- .../Extensions/KHR_materials_anisotropy.ts | 4 +- .../2.0/Extensions/KHR_materials_clearcoat.ts | 4 +- .../KHR_materials_diffuse_transmission.ts | 4 +- .../Extensions/KHR_materials_dispersion.ts | 4 +- .../KHR_materials_emissive_strength.ts | 7 ++- .../glTF/2.0/Extensions/KHR_materials_ior.ts | 4 +- .../Extensions/KHR_materials_iridescence.ts | 4 +- .../2.0/Extensions/KHR_materials_sheen.ts | 4 +- .../2.0/Extensions/KHR_materials_specular.ts | 26 ++++----- .../Extensions/KHR_materials_transmission.ts | 4 +- .../2.0/Extensions/KHR_materials_unlit.ts | 53 +++++++++++-------- .../2.0/Extensions/KHR_materials_volume.ts | 4 +- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 4 +- 13 files changed, 66 insertions(+), 60 deletions(-) diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts index a9d2cb7e2eb..9c3e82ddad3 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts @@ -65,6 +65,8 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -72,8 +74,6 @@ export class KHR_materials_anisotropy implements IGLTFLoaderExtension { const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial)); await Promise.all(promises); }); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts index 034c3b49f8b..22d4b3e84d5 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts @@ -67,6 +67,8 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -77,8 +79,6 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension { if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadClearCoatPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); await Promise.all(promises); }); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts index 91930aef943..5b511ac53cf 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts @@ -71,6 +71,8 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -78,8 +80,6 @@ export class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadTranslucentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); return await Promise.all(promises).then(() => {}); }); 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 31bbbf7b404..1783343dba8 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 @@ -66,6 +66,8 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -73,8 +75,6 @@ export class KHR_materials_dispersion implements IGLTFLoaderExtension { const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadDispersionPropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts index 0b334915f2c..690a54a4c7e 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts @@ -65,6 +65,7 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + await this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -72,10 +73,8 @@ export class KHR_materials_emissive_strength implements IGLTFLoaderExtension { const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - // eslint-disable-next-line github/no-then - return await this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial).then(() => { - this._loadEmissiveProperties(extensionContext, extension, babylonMaterial); - }); + this._loadEmissiveProperties(extensionContext, extension, babylonMaterial); + return await Promise.resolve(); }); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts index 6c3479fa586..08a06b1ab9d 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts @@ -70,6 +70,8 @@ export class KHR_materials_ior implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -77,8 +79,6 @@ export class KHR_materials_ior implements IGLTFLoaderExtension { const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadIorPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts index 22271fa7961..5bd277b1e6f 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts @@ -66,6 +66,8 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -73,8 +75,6 @@ export class KHR_materials_iridescence implements IGLTFLoaderExtension { const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts index 2a2a734fa02..cea6ceb4f3c 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts @@ -68,6 +68,8 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -75,8 +77,6 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension { const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadSheenPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts index 94dc328cf07..61d705cb697 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts @@ -67,6 +67,8 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -74,8 +76,6 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadSpecularPropertiesAsync(extensionContext, extension, babylonMaterial, useOpenPBR)); // Handle the EXT_materials_specular_edge_color sub-extension // https://github.com/KhronosGroup/glTF/blob/2a1111b88f052cbd3e2d82abb9faee56e7494904/extensions/2.0/Vendor/EXT_materials_specular_edge_color/README.md @@ -99,13 +99,13 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { const promises = new Array>(); - if (babylonMaterial instanceof OpenPBRMaterial) { + if (useOpenPBR) { if (properties.specularFactor !== undefined) { - babylonMaterial.specularWeight = properties.specularFactor; + (babylonMaterial as OpenPBRMaterial).specularWeight = properties.specularFactor; } if (properties.specularColorFactor !== undefined) { - babylonMaterial.specularColor = Color3.FromArray(properties.specularColorFactor); + (babylonMaterial as OpenPBRMaterial).specularColor = Color3.FromArray(properties.specularColorFactor); } if (properties.specularTexture) { @@ -113,8 +113,8 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/specularTexture`, properties.specularTexture, (texture) => { texture.name = `${babylonMaterial.name} (Specular)`; - babylonMaterial.specularWeightTexture = texture; - babylonMaterial.useSpecularWeightFromTextureAlpha = true; + (babylonMaterial as OpenPBRMaterial).specularWeightTexture = texture; + (babylonMaterial as OpenPBRMaterial).useSpecularWeightFromTextureAlpha = true; }) ); } @@ -123,17 +123,17 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/specularColorTexture`, properties.specularColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Specular Color)`; - babylonMaterial.specularColorTexture = texture; + (babylonMaterial as OpenPBRMaterial).specularColorTexture = texture; }) ); } } else { if (properties.specularFactor !== undefined) { - babylonMaterial.metallicF0Factor = properties.specularFactor; + (babylonMaterial as PBRMaterial).metallicF0Factor = properties.specularFactor; } if (properties.specularColorFactor !== undefined) { - babylonMaterial.metallicReflectanceColor = Color3.FromArray(properties.specularColorFactor); + (babylonMaterial as PBRMaterial).metallicReflectanceColor = Color3.FromArray(properties.specularColorFactor); } if (properties.specularTexture) { @@ -141,8 +141,8 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/specularTexture`, properties.specularTexture, (texture) => { texture.name = `${babylonMaterial.name} (Specular)`; - babylonMaterial.metallicReflectanceTexture = texture; - babylonMaterial.useOnlyMetallicFromMetallicReflectanceTexture = true; + (babylonMaterial as PBRMaterial).metallicReflectanceTexture = texture; + (babylonMaterial as PBRMaterial).useOnlyMetallicFromMetallicReflectanceTexture = true; }) ); } @@ -151,7 +151,7 @@ export class KHR_materials_specular implements IGLTFLoaderExtension { promises.push( this._loader.loadTextureInfoAsync(`${context}/specularColorTexture`, properties.specularColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Specular Color)`; - babylonMaterial.reflectanceTexture = texture; + (babylonMaterial as PBRMaterial).reflectionTexture = texture; }) ); } diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts index b404b2d822f..c0022868174 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts @@ -371,6 +371,8 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -378,8 +380,6 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension { const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts index aa64856fe9e..056511dbb80 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts @@ -1,7 +1,7 @@ import type { Nullable } from "core/types"; import { Color3 } from "core/Maths/math.color"; -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; -import { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; import type { Material } from "core/Materials/material"; import type { IMaterial } from "../glTFLoaderInterfaces"; @@ -22,6 +22,8 @@ declare module "../../glTFFileLoader" { } } +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; + /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_unlit/README.md) */ @@ -61,53 +63,58 @@ export class KHR_materials_unlit implements IGLTFLoaderExtension { * @internal */ // eslint-disable-next-line no-restricted-syntax - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable> { + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async () => { - return await this._loadUnlitPropertiesAsync(context, material, babylonMaterial); + if (useOpenPBR) { + const mod = await import("core/Materials/PBR/openPbrMaterial"); + PBRMaterialClass = mod.OpenPBRMaterial; + } else { + const mod = await import("core/Materials/PBR/pbrMaterial"); + PBRMaterialClass = mod.PBRMaterial; + } + return await this._loadUnlitPropertiesAsync(context, material, babylonMaterial, useOpenPBR); }); } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax - private _loadUnlitPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise { - if (!(babylonMaterial instanceof PBRMaterial) && !(babylonMaterial instanceof OpenPBRMaterial)) { + private _loadUnlitPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Promise { + if (!(babylonMaterial instanceof PBRMaterialClass)) { throw new Error(`${context}: Material type not supported`); } const promises = new Array>(); babylonMaterial.unlit = true; - + let baseColor: Color3 = Color3.White(); + let alpha: number = 1; const properties = material.pbrMetallicRoughness; if (properties) { if (properties.baseColorFactor) { - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseColor = Color3.FromArray(properties.baseColorFactor); - } else { - babylonMaterial.albedoColor = Color3.FromArray(properties.baseColorFactor); - } - - babylonMaterial.alpha = properties.baseColorFactor[3]; - } else { - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseColor = Color3.White(); - } else { - babylonMaterial.albedoColor = Color3.White(); - } + baseColor = Color3.FromArray(properties.baseColorFactor); + alpha = properties.baseColorFactor[3]; } if (properties.baseColorTexture) { promises.push( this._loader.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => { texture.name = `${babylonMaterial.name} (Base Color)`; - if (babylonMaterial instanceof OpenPBRMaterial) { - babylonMaterial.baseColorTexture = texture; + if (useOpenPBR) { + (babylonMaterial as OpenPBRMaterial).baseColorTexture = texture; } else { - babylonMaterial.albedoTexture = texture; + (babylonMaterial as PBRMaterial).albedoTexture = texture; } }) ); } } + if (useOpenPBR) { + (babylonMaterial as OpenPBRMaterial).baseColor = baseColor; + (babylonMaterial as OpenPBRMaterial).geometryOpacity = alpha; + } else { + (babylonMaterial as PBRMaterial).albedoColor = baseColor; + (babylonMaterial as PBRMaterial).alpha = alpha; + } + if (material.doubleSided) { babylonMaterial.backFaceCulling = false; babylonMaterial.twoSidedLighting = true; diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts index 6b70b2453bf..f3e39c352d4 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts @@ -75,6 +75,8 @@ export class KHR_materials_volume implements IGLTFLoaderExtension { // eslint-disable-next-line no-restricted-syntax public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable> { return GLTFLoader.LoadExtensionAsync(context, material, this.name, async (extensionContext, extension) => { + const promises = new Array>(); + promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); if (useOpenPBR) { const mod = await import("core/Materials/PBR/openPbrMaterial"); PBRMaterialClass = mod.OpenPBRMaterial; @@ -82,8 +84,6 @@ export class KHR_materials_volume implements IGLTFLoaderExtension { const mod = await import("core/Materials/PBR/pbrMaterial"); PBRMaterialClass = mod.PBRMaterial; } - const promises = new Array>(); - promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); // eslint-disable-next-line github/no-then return await Promise.all(promises).then(() => {}); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index 4283dc3a8c7..de92d12c984 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -72,8 +72,8 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { if (!(babylonMaterial as PBRMaterial).albedoTexture) { (babylonMaterial as PBRMaterial).albedoColor.toLinearSpaceToRef((babylonMaterial as PBRMaterial).albedoColor, useExactSrgbConversions); } - if (!babylonMaterial.reflectivityTexture) { - babylonMaterial.reflectivityColor.toLinearSpaceToRef(babylonMaterial.reflectivityColor, useExactSrgbConversions); + if (!(babylonMaterial as PBRMaterial).reflectivityTexture) { + (babylonMaterial as PBRMaterial).reflectivityColor.toLinearSpaceToRef(babylonMaterial.reflectivityColor, useExactSrgbConversions); } } From ae4e4be64f59aaeaf5cdf9f0095e4979b9bab3a7 Mon Sep 17 00:00:00 2001 From: Mike Bond Date: Fri, 18 Jul 2025 14:14:14 -0700 Subject: [PATCH 23/23] Add more OpenPBR properties --- .vscode/settings.json | 2 +- .../core/src/Materials/PBR/openPbrMaterial.ts | 318 +++--------------- .../ShadersInclude/openPbrUboDeclaration.fx | 19 +- .../openpbrBlockFinalColorComposition.fx | 3 +- .../openpbrFragmentDeclaration.fx | 16 +- .../openpbrFragmentSamplersDeclaration.fx | 13 +- .../openpbrVertexDeclaration.fx | 124 +------ .../dev/core/src/Shaders/openpbr.fragment.fx | 47 ++- .../dev/core/src/Shaders/openpbr.vertex.fx | 22 +- .../ShadersInclude/openPbrUboDeclaration.fx | 20 +- .../openpbrBlockFinalColorComposition.fx | 3 +- .../openpbrFragmentSamplersDeclaration.fx | 10 +- .../core/src/ShadersWGSL/openpbr.fragment.fx | 36 +- .../core/src/ShadersWGSL/openpbr.vertex.fx | 24 +- .../glTF/2.0/Extensions/MSFT_sRGBFactors.ts | 5 +- .../dev/loaders/src/glTF/2.0/glTFLoader.ts | 32 +- 16 files changed, 214 insertions(+), 480 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 76978e3d834..0211eae9519 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -34,6 +34,6 @@ "[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "editor.formatOnSave": false, + "editor.formatOnSave": true, "jest.runMode": "on-demand" } diff --git a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts index a6f43d0eef8..d6ca912183a 100644 --- a/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts +++ b/packages/dev/core/src/Materials/PBR/openPbrMaterial.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { serialize, serializeAsColor3, expandToProperty, serializeAsTexture, addAccessorsForMaterialProperty } from "../../Misc/decorators"; +import { serialize, expandToProperty, serializeAsTexture, addAccessorsForMaterialProperty } from "../../Misc/decorators"; import { GetEnvironmentBRDFTexture } from "../../Misc/brdfTextureTools"; import type { Nullable } from "../../types"; import { Scene } from "../../scene"; @@ -217,14 +217,7 @@ export class OpenPBRMaterialDefines extends ImageProcessingDefinesMixin(OpenPBRM public BAKED_VERTEX_ANIMATION_TEXTURE = false; - public AMBIENT = false; - public AMBIENTDIRECTUV = 0; - public AMBIENTINGRAYSCALE = false; - - public OPACITY = false; public VERTEXALPHA = false; - public OPACITYDIRECTUV = 0; - public OPACITYRGB = false; public ALPHATEST = false; public DEPTHPREPASS = false; public ALPHABLEND = false; @@ -232,10 +225,6 @@ export class OpenPBRMaterialDefines extends ImageProcessingDefinesMixin(OpenPBRM public ALPHATESTVALUE = "0.5"; public PREMULTIPLYALPHA = false; - public EMISSIVE = false; - public EMISSIVEDIRECTUV = 0; - public GAMMAEMISSIVE = false; - public REFLECTIVITY_GAMMA = false; public REFLECTIVITYDIRECTUV = 0; public SPECULARTERM = false; @@ -576,7 +565,8 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { private _baseMetalRoughTexture: Sampler = new Sampler("base_metalness_specular_roughness", "baseMetalRough", "METALLIC_ROUGHNESS"); /** - * Defines the opacity of the material's geometry. See OpenPBR's specs for geometry_opacity + * Defines the opacity of the material's geometry. + * See OpenPBR's specs for geometry_opacity */ public geometryOpacity: number; @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "geometryOpacity") @@ -584,12 +574,39 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { private _geometryOpacity: Property = new Property("geometry_opacity", 1.0, "vBaseColor", 4, 3); /** - * Defines the color of the material's emission. See OpenPBR's specs for emission_color + * Defines the opacity of the material's geometry. + * See OpenPBR's specs for geometry_opacity + */ + public geometryOpacityTexture: BaseTexture; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "geometryOpacityTexture") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _geometryOpacityTexture: Sampler = new Sampler("geometry_opacity", "geometryOpacity", "GEOMETRY_OPACITY"); + + /** + * Defines the color of the material's emission. + * See OpenPBR's specs for emission_color */ public emissionColor: Color3; @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "emissionColor") // eslint-disable-next-line @typescript-eslint/no-unused-vars - private _emissionColor: Property = new Property("emission_color", Color3.Black(), "vEmissiveColor", 3); + private _emissionColor: Property = new Property("emission_color", Color3.Black(), "vEmissionColor", 3); + + /** + * Defines the color of the material's emission. + * See OpenPBR's specs for emission_color + */ + public emissionTexture: BaseTexture; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "emissionTexture") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _emissionTexture: Sampler = new Sampler("emission", "emission", "EMISSION"); + + /** + * Defines the ambient occlusion texture. + */ + public ambientOcclusionTexture: BaseTexture; + @addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "ambientOcclusionTexture") + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _ambientOcclusionTexture: Sampler = new Sampler("ambient_occlusion", "ambientOcclusion", "AMBIENT_OCCLUSION"); private _propertyList: { [name: string]: Property }; private _uniformsList: { [name: string]: Uniform } = {}; @@ -627,36 +644,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public disableBumpMap: boolean = false; - /** - * AKA Occlusion Texture in other nomenclature. - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public ambientTexture: Nullable; - - /** - * AKA Occlusion Texture Intensity in other nomenclature. - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public ambientTextureStrength: number = 1.0; - - /** - * Defines how much the AO map is occluding the analytical lights (point spot...). - * 1 means it completely occludes it - * 0 mean it has no impact - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public ambientTextureImpactOnAnalyticalLights: number = OpenPBRMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; - - /** - * Stores the alpha values in a texture. Use luminance if texture.getAlphaFromRGB is true. - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesAndMiscDirty") - public opacityTexture: Nullable; - /** * Stores the reflection values in a texture. */ @@ -664,13 +651,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty") public reflectionTexture: Nullable; - /** - * Stores the emissive values in a texture. - */ - @serializeAsTexture() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public emissiveTexture: Nullable; - /** * Specifies that the specular weight is stored in the alpha channel of the specular weight texture. */ @@ -692,27 +672,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesDirty", null) public lightmapTexture: Nullable; - /** - * The color of a material in ambient lighting. - */ - @serializeAsColor3("ambient") - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public ambientColor = new Color3(0, 0, 0); - - /** - * AKA Specular Color in other nomenclature. - */ - @serializeAsColor3("reflectivity") - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public reflectivityColor = new Color3(1, 1, 1); - - /** - * The color reflected from the material. - */ - @serializeAsColor3("reflection") - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public reflectionColor = new Color3(1.0, 1.0, 1.0); - /** * If true, the light map contains occlusion information instead of lighting info. */ @@ -741,14 +700,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { @expandToProperty("_markAllSubMeshesAsTexturesAndMiscDirty") public alphaCutOff = 0.4; - /** - * Specifies that the material will keep the specular highlights over a transparent surface (only the most luminous ones). - * A car glass is a good example of that. When sun reflects on it you can not see what is behind. - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public useSpecularOverAlpha = true; - /** * Specifies if the reflectivity texture contains the glossiness information in its alpha channel. */ @@ -832,14 +783,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - /** - * Specifies that the material will keeps the reflection highlights over a transparent surface (only the most luminous ones). - * A car glass is a good example of that. When the street lights reflects on it you can not see what is behind. - */ - @serialize() - @expandToProperty("_markAllSubMeshesAsTexturesDirty") - public useRadianceOverAlpha = true; - /** * Allows using an object space normal map (instead of tangent space). */ @@ -1038,44 +981,12 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { */ public _disableBumpMap: boolean = false; - /** - * AKA Occlusion Texture in other nomenclature. - * @internal - */ - public _ambientTexture: Nullable = null; - - /** - * AKA Occlusion Texture Intensity in other nomenclature. - * @internal - */ - public _ambientTextureStrength: number = 1.0; - - /** - * Defines how much the AO map is occluding the analytical lights (point spot...). - * 1 means it completely occludes it - * 0 mean it has no impact - * @internal - */ - public _ambientTextureImpactOnAnalyticalLights: number = PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS; - - /** - * Stores the alpha values in a texture. - * @internal - */ - public _opacityTexture: Nullable = null; - /** * Stores the reflection values in a texture. * @internal */ public _reflectionTexture: Nullable = null; - /** - * Stores the emissive values in a texture. - * @internal - */ - public _emissiveTexture: Nullable = null; - /** * Specifies that only the A channel from _metallicReflectanceTexture should be used. * If false, both RGB and A channels will be used @@ -1323,11 +1234,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { */ private _renderTargets = new SmartArray(16); - /** - * Sets the global ambient color for the material used in lighting calculations. - */ - private _globalAmbientColor = new Color3(0, 0, 0); - /** * If set to true, no lighting calculations will be applied. */ @@ -1464,7 +1370,10 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { this._specularIor; this._baseMetalRoughTexture; this._geometryOpacity; + this._geometryOpacityTexture; this._emissionColor; + this._emissionTexture; + this._ambientOcclusionTexture; } /** @@ -1511,7 +1420,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { return false; } - return this.geometryOpacity < 1.0 || this._opacityTexture != null || this._shouldUseAlphaFromAlbedoTexture(); + return this.geometryOpacity < 1.0 || this.geometryOpacityTexture != null || this._shouldUseAlphaFromAlbedoTexture(); } /** @@ -1536,13 +1445,13 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { * @returns whether or not there is a usable alpha channel for transparency. */ protected _hasAlphaChannel(): boolean { - return this._opacityTexture != null; + return this.geometryOpacityTexture != null; } /** * Makes a duplicate of the current material. * @param name - name to use for the new material. - * @param cloneTexturesOnlyOnce - if a texture is used in more than one channel (e.g diffuse and opacity), only clone it once and reuse it on the other channels. Default false. + * @param cloneTexturesOnlyOnce - if a texture is used in more than one channel (e.g baseColor and opacity), only clone it once and reuse it on the other channels. Default false. * @param rootUrl defines the root URL to use to load textures * @returns cloned material instance */ @@ -1689,18 +1598,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { - if (!this._ambientTexture.isReadyOrNotBlocking()) { - return false; - } - } - - if (this._opacityTexture && MaterialFlags.OpacityTextureEnabled) { - if (!this._opacityTexture.isReadyOrNotBlocking()) { - return false; - } - } - const reflectionTexture = this._getReflectionTexture(); if (reflectionTexture && MaterialFlags.ReflectionTextureEnabled) { if (!reflectionTexture.isReadyOrNotBlocking()) { @@ -1724,12 +1621,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { - if (!this._emissiveTexture.isReadyOrNotBlocking()) { - return false; - } - } - if (engine.getCaps().standardDerivatives && this._bumpTexture && MaterialFlags.BumpTextureEnabled && !this._disableBumpMap) { // Bump texture cannot be not blocking. if (!this._bumpTexture.isReady()) { @@ -1825,22 +1716,14 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { public override buildUniformLayout(): void { // Order is important ! const ubo = this._uniformBuffer; - ubo.addUniform("vAmbientInfos", 4); - ubo.addUniform("vOpacityInfos", 2); - ubo.addUniform("vEmissiveInfos", 2); ubo.addUniform("vLightmapInfos", 2); ubo.addUniform("vBumpInfos", 3); - ubo.addUniform("ambientMatrix", 16); - ubo.addUniform("opacityMatrix", 16); - ubo.addUniform("emissiveMatrix", 16); ubo.addUniform("lightmapMatrix", 16); ubo.addUniform("bumpMatrix", 16); ubo.addUniform("vTangentSpaceParams", 2); ubo.addUniform("vLightingIntensity", 4); ubo.addUniform("pointSize", 1); - // ubo.addUniform("vEmissiveColor", 3); - ubo.addUniform("vAmbientColor", 3); ubo.addUniform("vDebugMode", 2); @@ -1933,27 +1816,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { - ubo.updateFloat4( - "vAmbientInfos", - this._ambientTexture.coordinatesIndex, - this._ambientTexture.level, - this._ambientTextureStrength, - this._ambientTextureImpactOnAnalyticalLights - ); - BindTextureMatrix(this._ambientTexture, ubo, "ambient"); - } - - if (this._opacityTexture && MaterialFlags.OpacityTextureEnabled) { - ubo.updateFloat2("vOpacityInfos", this._opacityTexture.coordinatesIndex, this._opacityTexture.level); - BindTextureMatrix(this._opacityTexture, ubo, "opacity"); - } - - if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { - ubo.updateFloat2("vEmissiveInfos", this._emissiveTexture.coordinatesIndex, this._emissiveTexture.level); - BindTextureMatrix(this._emissiveTexture, ubo, "emissive"); - } - if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { ubo.updateFloat2("vLightmapInfos", this._lightmapTexture.coordinatesIndex, this._lightmapTexture.level); BindTextureMatrix(this._lightmapTexture, ubo, "lightmap"); @@ -1978,8 +1840,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { ubo.updateFloat("pointSize", this.pointSize); } - // ubo.updateColor3("vEmissiveColor", MaterialFlags.EmissiveTextureEnabled ? this._emissiveColor : Color3.BlackReadOnly); - Object.values(this._uniformsList).forEach((uniform) => { // If the property actually defines a uniform, update it. if (uniform.numComponents === 4) { @@ -2004,11 +1864,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { ubo.updateVector4("vLightingIntensity", this._lightingInfos); - // Colors - scene.ambientColor.multiplyToRef(this._ambientColor, this._globalAmbientColor); - - ubo.updateColor3("vAmbientColor", this._globalAmbientColor); - ubo.updateFloat2("vDebugMode", this.debugLimit, this.debugFactor); } @@ -2022,24 +1877,12 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { - ubo.setTexture("ambientSampler", this._ambientTexture); - } - - if (this._opacityTexture && MaterialFlags.OpacityTextureEnabled) { - ubo.setTexture("opacitySampler", this._opacityTexture); - } - BindIBLSamplers(scene, defines, ubo, reflectionTexture, this.realTimeFiltering); if (defines.ENVIRONMENTBRDF) { ubo.setTexture("environmentBrdfSampler", this._environmentBRDFTexture); } - if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { - ubo.setTexture("emissiveSampler", this._emissiveTexture); - } - if (this._lightmapTexture && MaterialFlags.LightmapTextureEnabled) { ubo.setTexture("lightmapSampler", this._lightmapTexture); } @@ -2116,22 +1959,10 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - if (this._ambientTexture && this._ambientTexture.animations && this._ambientTexture.animations.length > 0) { - results.push(this._ambientTexture); - } - - if (this._opacityTexture && this._opacityTexture.animations && this._opacityTexture.animations.length > 0) { - results.push(this._opacityTexture); - } - if (this._reflectionTexture && this._reflectionTexture.animations && this._reflectionTexture.animations.length > 0) { results.push(this._reflectionTexture); } - if (this._emissiveTexture && this._emissiveTexture.animations && this._emissiveTexture.animations.length > 0) { - results.push(this._emissiveTexture); - } - if (this._bumpTexture && this._bumpTexture.animations && this._bumpTexture.animations.length > 0) { results.push(this._bumpTexture); } @@ -2158,22 +1989,10 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - if (this._ambientTexture) { - activeTextures.push(this._ambientTexture); - } - - if (this._opacityTexture) { - activeTextures.push(this._opacityTexture); - } - if (this._reflectionTexture) { activeTextures.push(this._reflectionTexture); } - if (this._emissiveTexture) { - activeTextures.push(this._emissiveTexture); - } - if (this._bumpTexture) { activeTextures.push(this._bumpTexture); } @@ -2203,22 +2022,10 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - if (this._ambientTexture === texture) { - return true; - } - - if (this._opacityTexture === texture) { - return true; - } - if (this._reflectionTexture === texture) { return true; } - if (this._emissiveTexture === texture) { - return true; - } - if (this._bumpTexture === texture) { return true; } @@ -2258,10 +2065,7 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { sampler.value?.dispose(); } - this._ambientTexture?.dispose(); - this._opacityTexture?.dispose(); this._reflectionTexture?.dispose(); - this._emissiveTexture?.dispose(); this._bumpTexture?.dispose(); this._lightmapTexture?.dispose(); } @@ -2370,14 +2174,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { fallbacks.addFallback(fallbackRank++, "NORMAL"); } - if (defines.AMBIENT) { - fallbacks.addFallback(fallbackRank++, "AMBIENT"); - } - - if (defines.EMISSIVE) { - fallbacks.addFallback(fallbackRank++, "EMISSIVE"); - } - if (defines.VERTEXCOLOR) { fallbacks.addFallback(fallbackRank++, "VERTEXCOLOR"); } @@ -2424,30 +2220,16 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { "viewProjection", "vEyePosition", "vLightsType", - "vAmbientColor", - "vMetallicReflectanceFactors", "visibility", "vFogInfos", "vFogColor", "pointSize", - "vAlbedoInfos", - "vAmbientInfos", - "vOpacityInfos", - "vEmissiveInfos", - "vMetallicReflectanceInfos", - "vReflectanceInfos", "vBumpInfos", "vLightmapInfos", "mBones", - "albedoMatrix", - "ambientMatrix", - "opacityMatrix", - "emissiveMatrix", "normalMatrix", "bumpMatrix", "lightmapMatrix", - "metallicReflectanceMatrix", - "reflectanceMatrix", "vLightingIntensity", "logarithmicDepthConstant", "vTangentSpaceParams", @@ -2464,11 +2246,8 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { const samplers = [ "reflectivitySampler", - "ambientSampler", - "emissiveSampler", "bumpSampler", "lightmapSampler", - "opacitySampler", "environmentBrdfSampler", "boneSampler", "metallicReflectanceSampler", @@ -2623,20 +2402,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { } } - if (this._ambientTexture && MaterialFlags.AmbientTextureEnabled) { - PrepareDefinesForMergedUV(this._ambientTexture, defines, "AMBIENT"); - defines.AMBIENTINGRAYSCALE = this._useAmbientInGrayScale; - } else { - defines.AMBIENT = false; - } - - if (this._opacityTexture && MaterialFlags.OpacityTextureEnabled) { - PrepareDefinesForMergedUV(this._opacityTexture, defines, "OPACITY"); - defines.OPACITYRGB = this._opacityTexture.getAlphaFromRGB; - } else { - defines.OPACITY = false; - } - const reflectionTexture = this._getReflectionTexture(); const useSHInFragment: boolean = this._forceIrradianceInFragment || @@ -2655,13 +2420,6 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase { defines.LIGHTMAP = false; } - if (this._emissiveTexture && MaterialFlags.EmissiveTextureEnabled) { - PrepareDefinesForMergedUV(this._emissiveTexture, defines, "EMISSIVE"); - defines.GAMMAEMISSIVE = this._emissiveTexture.gammaSpace; - } else { - defines.EMISSIVE = false; - } - if (MaterialFlags.SpecularTextureEnabled) { if (this._baseMetalRoughTexture) { defines.AOSTOREINMETALMAPRED = this._useAmbientOcclusionFromMetallicTextureRed; diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx index 1d1cf2e74b2..c1157e90f43 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openPbrUboDeclaration.fx @@ -23,21 +23,14 @@ layout(std140, column_major) uniform; // } uniform Material { - vec4 vAmbientInfos; - vec2 vOpacityInfos; - vec2 vEmissiveInfos; vec2 vLightmapInfos; vec3 vBumpInfos; - mat4 ambientMatrix; - mat4 opacityMatrix; - mat4 emissiveMatrix; mat4 lightmapMatrix; mat4 bumpMatrix; vec2 vTangentSpaceParams; vec4 vLightingIntensity; float pointSize; - vec3 vAmbientColor; vec2 vDebugMode; @@ -77,7 +70,7 @@ uniform Material { float vBaseDiffuseRoughness; vec4 vReflectanceInfo; vec4 vSpecularColor; - vec3 vEmissiveColor; + vec3 vEmissionColor; vec2 vBaseWeightInfos; mat4 baseWeightMatrix; @@ -85,12 +78,18 @@ uniform Material { mat4 baseColorMatrix; vec2 vBaseDiffuseRoughnessInfos; mat4 baseDiffuseRoughnessMatrix; - vec2 vBaseMetalRoughInfos; - mat4 baseMetalRoughMatrix; vec2 vSpecularWeightInfos; mat4 specularWeightMatrix; vec2 vSpecularColorInfos; mat4 specularColorMatrix; + vec2 vBaseMetalRoughInfos; + mat4 baseMetalRoughMatrix; + vec2 vGeometryOpacityInfos; + mat4 geometryOpacityMatrix; + vec2 vEmissionInfos; + mat4 emissionMatrix; + vec2 vAmbientOcclusionInfos; + mat4 ambientOcclusionMatrix; #define ADDITIONAL_UBO_DECLARATION }; diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalColorComposition.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalColorComposition.fx index e0a0d3613df..aa96e0ca8cb 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalColorComposition.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrBlockFinalColorComposition.fx @@ -10,7 +10,6 @@ vec4 finalColor = vec4( finalRadianceScaled + #endif #endif - finalAmbient + finalDiffuse, alpha); @@ -26,7 +25,7 @@ vec4 finalColor = vec4( #endif // _____________________________ EmissiveLight _____________________________________ -finalColor.rgb += finalEmissive; +finalColor.rgb += finalEmission; #define CUSTOM_FRAGMENT_BEFORE_FOG diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx index 4bbc1106acd..d317ba67432 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx @@ -8,12 +8,10 @@ uniform float vBaseDiffuseRoughness; // CUSTOM CONTROLS uniform vec4 vLightingIntensity; -uniform vec3 vEmissiveColor; +uniform vec3 vEmissionColor; uniform float visibility; -uniform vec3 vAmbientColor; - // Samplers #ifdef BASE_COLOR uniform vec2 vBaseColorInfos; @@ -27,8 +25,8 @@ uniform vec2 vBaseWeightInfos; uniform vec2 vBaseDiffuseRoughnessInfos; #endif -#ifdef AMBIENT -uniform vec4 vAmbientInfos; +#ifdef AMBIENT_OCCLUSION +uniform vec4 vAmbientOcclusionInfos; #endif #ifdef BUMP @@ -36,12 +34,12 @@ uniform vec3 vBumpInfos; uniform vec2 vTangentSpaceParams; #endif -#ifdef OPACITY -uniform vec2 vOpacityInfos; +#ifdef GEOMETRY_OPACITY +uniform vec2 vGeometryOpacityInfos; #endif -#ifdef EMISSIVE -uniform vec2 vEmissiveInfos; +#ifdef EMISSION +uniform vec2 vEmissionInfos; #endif #ifdef LIGHTMAP diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx index 673e42f5069..f9955dbdf73 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx @@ -1,14 +1,15 @@ #include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor,_SAMPLERNAME_,baseColor) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_SAMPLERNAME_,baseWeight) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_SAMPLERNAME_,baseDiffuseRoughness) -#include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_SAMPLERNAME_,ambient) -#include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_SAMPLERNAME_,opacity) -#include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_SAMPLERNAME_,emissive) -#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_SAMPLERNAME_,lightmap) #include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough,_SAMPLERNAME_,baseMetalRough) -#include(_DEFINENAME_,METALLIC_REFLECTANCE,_VARYINGNAME_,MetallicReflectance,_SAMPLERNAME_,metallicReflectance) -#include(_DEFINENAME_,REFLECTANCE,_VARYINGNAME_,Reflectance,_SAMPLERNAME_,reflectance) +#include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight,_SAMPLERNAME_,specularWeight) +#include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor,_SAMPLERNAME_,specularColor) +#include(_DEFINENAME_,GEOMETRY_OPACITY,_VARYINGNAME_,GeometryOpacity,_SAMPLERNAME_,geometryOpacity) +#include(_DEFINENAME_,EMISSION,_VARYINGNAME_,Emission,_SAMPLERNAME_,emission) + +#include(_DEFINENAME_,AMBIENT_OCCLUSION,_VARYINGNAME_,AmbientOcclusion,_SAMPLERNAME_,ambientOcclusion) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_SAMPLERNAME_,decal) +#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_SAMPLERNAME_,lightmap) // Reflection #ifdef REFLECTION diff --git a/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx b/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx index c304218eb3e..4997164b647 100644 --- a/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx +++ b/packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx @@ -5,7 +5,7 @@ uniform vec4 vEyePosition; mat4 viewProjectionR; #endif -#ifdef ALBEDO +#ifdef BASE_COLOR uniform vec2 vBaseColorInfos; uniform mat4 baseColorMatrix; #endif @@ -21,19 +21,19 @@ uniform mat4 baseDiffuseRoughnessMatrix; uniform vec2 vBaseDiffuseRoughnessInfos; #endif -#ifdef AMBIENT -uniform mat4 ambientMatrix; -uniform vec4 vAmbientInfos; +#ifdef GEOMETRY_OPACITY +uniform mat4 geometryOpacityMatrix; +uniform vec2 vGeometryOpacityInfos; #endif -#ifdef OPACITY -uniform mat4 opacityMatrix; -uniform vec2 vOpacityInfos; +#ifdef AMBIENT_OCCLUSION +uniform vec2 vAmbientOcclusionInfos; +uniform mat4 ambientOcclusionMatrix; #endif -#ifdef EMISSIVE -uniform vec2 vEmissiveInfos; -uniform mat4 emissiveMatrix; +#ifdef EMISSION +uniform vec2 vEmissionInfos; +uniform mat4 emissionMatrix; #endif #ifdef LIGHTMAP @@ -46,13 +46,14 @@ uniform vec2 vBaseMetalRoughInfos; uniform mat4 baseMetalRoughMatrix; #endif -#ifdef METALLIC_REFLECTANCE - uniform vec2 vMetallicReflectanceInfos; - uniform mat4 metallicReflectanceMatrix; +#ifdef SPECULAR_WEIGHT +uniform vec2 vSpecularWeightInfos; +uniform mat4 specularWeightMatrix; #endif -#ifdef REFLECTANCE - uniform vec2 vReflectanceInfos; - uniform mat4 reflectanceMatrix; + +#ifdef SPECULAR_COLOR +uniform vec2 vSpecularColorInfos; +uniform mat4 specularColorMatrix; #endif #ifdef BUMP @@ -72,97 +73,6 @@ uniform vec4 cameraInfo; uniform mat4 reflectionMatrix; #endif -// Clear Coat -#ifdef CLEARCOAT - #if defined(CLEARCOAT_TEXTURE) || defined(CLEARCOAT_TEXTURE_ROUGHNESS) - uniform vec4 vClearCoatInfos; - #endif - - #ifdef CLEARCOAT_TEXTURE - uniform mat4 clearCoatMatrix; - #endif - - #ifdef CLEARCOAT_TEXTURE_ROUGHNESS - uniform mat4 clearCoatRoughnessMatrix; - #endif - - #ifdef CLEARCOAT_BUMP - uniform vec2 vClearCoatBumpInfos; - uniform mat4 clearCoatBumpMatrix; - #endif - - #ifdef CLEARCOAT_TINT_TEXTURE - uniform vec2 vClearCoatTintInfos; - uniform mat4 clearCoatTintMatrix; - #endif -#endif - -// Iridescence -#ifdef IRIDESCENCE - #if defined(IRIDESCENCE_TEXTURE) || defined(IRIDESCENCE_THICKNESS_TEXTURE) - uniform vec4 vIridescenceInfos; - #endif - - #ifdef IRIDESCENCE_TEXTURE - uniform mat4 iridescenceMatrix; - #endif - - #ifdef IRIDESCENCE_THICKNESS_TEXTURE - uniform mat4 iridescenceThicknessMatrix; - #endif -#endif - -// Anisotropy -#ifdef ANISOTROPIC - #ifdef ANISOTROPIC_TEXTURE - uniform vec2 vAnisotropyInfos; - uniform mat4 anisotropyMatrix; - #endif -#endif - -// Sheen -#ifdef SHEEN - #if defined(SHEEN_TEXTURE) || defined(SHEEN_TEXTURE_ROUGHNESS) - uniform vec4 vSheenInfos; - #endif - - #ifdef SHEEN_TEXTURE - uniform mat4 sheenMatrix; - #endif - - #ifdef SHEEN_TEXTURE_ROUGHNESS - uniform mat4 sheenRoughnessMatrix; - #endif -#endif - -// Sub Surface -#ifdef SUBSURFACE - #ifdef SS_REFRACTION - uniform vec4 vRefractionInfos; - uniform mat4 refractionMatrix; - #endif - - #ifdef SS_THICKNESSANDMASK_TEXTURE - uniform vec2 vThicknessInfos; - uniform mat4 thicknessMatrix; - #endif - - #ifdef SS_REFRACTIONINTENSITY_TEXTURE - uniform vec2 vRefractionIntensityInfos; - uniform mat4 refractionIntensityMatrix; - #endif - - #ifdef SS_TRANSLUCENCYINTENSITY_TEXTURE - uniform vec2 vTranslucencyIntensityInfos; - uniform mat4 translucencyIntensityMatrix; - #endif - - #ifdef SS_TRANSLUCENCYCOLOR_TEXTURE - uniform vec2 vTranslucencyColorInfos; - uniform mat4 translucencyColorMatrix; - #endif -#endif - #ifdef NORMAL #if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX) #ifdef USESPHERICALFROMREFLECTIONMAP diff --git a/packages/dev/core/src/Shaders/openpbr.fragment.fx b/packages/dev/core/src/Shaders/openpbr.fragment.fx index 6ce8d8bde9f..32da1a6614d 100644 --- a/packages/dev/core/src/Shaders/openpbr.fragment.fx +++ b/packages/dev/core/src/Shaders/openpbr.fragment.fx @@ -62,7 +62,7 @@ precision highp float; #include #include -#include +#include #include #include @@ -148,14 +148,14 @@ void main(void) { // _____________________________ AO _______________________________ ambientOcclusionOutParams aoOut; -#ifdef AMBIENT - vec3 ambientOcclusionColorMap = texture2D(ambientSampler, vAmbientUV + uvOffset).rgb; +#ifdef AMBIENT_OCCLUSION + vec3 ambientOcclusionFromTexture = texture2D(ambientOcclusionSampler, vAmbientOcclusionUV + uvOffset).rgb; #endif aoOut = ambientOcclusionBlock( - #ifdef AMBIENT - ambientOcclusionColorMap, - vAmbientInfos + #ifdef AMBIENT_OCCLUSION + ambientOcclusionFromTexture, + vAmbientOcclusionInfos #endif ); @@ -213,9 +213,9 @@ vec4 specularColor = vSpecularColor; #ifdef METALLIC_ROUGHNESS , vec3(vBaseMetalRoughInfos, 1.0f) , metallicRoughnessFromTexture - #endif - #if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) - , aoOut.ambientOcclusionColor + #ifdef AOSTOREINMETALMAPRED + , aoOut.ambientOcclusionColor + #endif #endif #ifdef DETAIL , detailColor @@ -225,8 +225,6 @@ vec4 specularColor = vSpecularColor; float roughness = reflectivityOut.roughness; float diffuseRoughness = reflectivityOut.diffuseRoughness; - - // surfaceAlbedo = reflectivityOut.surfaceAlbedo; #if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED) aoOut.ambientOcclusionColor = reflectivityOut.ambientOcclusionColor; @@ -235,7 +233,6 @@ vec4 specularColor = vSpecularColor; // _____________________________ Compute Geometry info _________________________________ #include - // _____________________________ Reflection Info _______________________________________ #ifdef REFLECTION reflectionOutParams reflectionOut; @@ -312,7 +309,31 @@ vec4 specularColor = vSpecularColor; #include #endif // !UNLIT - #include + // #include + // _____________________________ Diffuse ________________________________________ + vec3 finalDiffuse = diffuseBase; + finalDiffuse *= surfaceAlbedo; + + finalDiffuse = max(finalDiffuse, 0.0); + finalDiffuse *= vLightingIntensity.x; + + // _____________________________ Emissive ________________________________________ + vec3 finalEmission = vEmissionColor; + #ifdef EMISSION + vec3 emissionColorTex = texture2D(emissionSampler, vEmissionUV + uvOffset).rgb; + #ifdef EMISSION_GAMMA + finalEmission *= toLinearSpace(emissionColorTex.rgb); + #else + finalEmission *= emissionColorTex.rgb; + #endif + finalEmission *= vEmissionInfos.y; + #endif + finalEmission *= vLightingIntensity.y; + + // ______________________________ Ambient ________________________________________ + #ifdef AMBIENT_OCCLUSION + finalDiffuse *= mix(vec3(1.), aoOut.ambientOcclusionColor, 1.0 - vAmbientOcclusionInfos.y); + #endif #define CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION diff --git a/packages/dev/core/src/Shaders/openpbr.vertex.fx b/packages/dev/core/src/Shaders/openpbr.vertex.fx index 7836a4b20ee..1f3ffdf2f8c 100644 --- a/packages/dev/core/src/Shaders/openpbr.vertex.fx +++ b/packages/dev/core/src/Shaders/openpbr.vertex.fx @@ -36,16 +36,17 @@ attribute vec4 color; #include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness) -#include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail) -#include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient) -#include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity) -#include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive) -#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap) #include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough) #include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight) #include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor) +#include(_DEFINENAME_,GEOMETRY_OPACITY,_VARYINGNAME_,GeometryOpacity) +#include(_DEFINENAME_,EMISSION,_VARYINGNAME_,Emission) + +#include(_DEFINENAME_,AMBIENT_OCCLUSION,_VARYINGNAME_,AmbientOcclusion) #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal) +#include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail) +#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap) // Output varying vec3 vPositionW; @@ -215,16 +216,17 @@ void main(void) { #include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor,_MATRIXNAME_,albedo,_INFONAME_,BaseColorInfos.x) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_MATRIXNAME_,baseWeight,_INFONAME_,BaseWeightInfos.x) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_MATRIXNAME_,baseDiffuseRoughness,_INFONAME_,BaseDiffuseRoughnessInfos.x) - #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) - #include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_MATRIXNAME_,ambient,_INFONAME_,AmbientInfos.x) - #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_MATRIXNAME_,opacity,_INFONAME_,OpacityInfos.x) - #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_MATRIXNAME_,emissive,_INFONAME_,EmissiveInfos.x) - #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_MATRIXNAME_,lightmap,_INFONAME_,LightmapInfos.x) #include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough,_MATRIXNAME_,baseMetalRough,_INFONAME_,BaseMetalRoughInfos.x) #include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight,_MATRIXNAME_,specularWeight,_INFONAME_,SpecularWeightInfos.x) #include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor,_MATRIXNAME_,specularColor,_INFONAME_,SpecularColorInfos.x) + #include(_DEFINENAME_,GEOMETRY_OPACITY,_VARYINGNAME_,GeometryOpacity,_MATRIXNAME_,geometryOpacity,_INFONAME_,GeometryOpacityInfos.x) + #include(_DEFINENAME_,EMISSION,_VARYINGNAME_,Emission,_MATRIXNAME_,emission,_INFONAME_,EmissionInfos.x) + + #include(_DEFINENAME_,AMBIENT_OCCLUSION,_VARYINGNAME_,AmbientOcclusion,_MATRIXNAME_,ambientOcclusion,_INFONAME_,AmbientOcclusionInfos.x) #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump,_MATRIXNAME_,bump,_INFONAME_,BumpInfos.x) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_MATRIXNAME_,decal,_INFONAME_,DecalInfos.x) + #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) + #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_MATRIXNAME_,lightmap,_INFONAME_,LightmapInfos.x) // TBN #include diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx index be6feacd61c..a401a7e0a8d 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openPbrUboDeclaration.fx @@ -1,18 +1,12 @@ -uniform vAmbientInfos: vec4f; -uniform vOpacityInfos: vec2f; -uniform vEmissiveInfos: vec2f; + uniform vLightmapInfos: vec2f; uniform vBumpInfos: vec3f; -uniform ambientMatrix: mat4x4f; -uniform opacityMatrix: mat4x4f; -uniform emissiveMatrix: mat4x4f; uniform lightmapMatrix: mat4x4f; uniform bumpMatrix: mat4x4f; uniform vTangentSpaceParams: vec2f; uniform vLightingIntensity: vec4f; uniform pointSize: f32; -uniform vAmbientColor: vec3f; uniform vDebugMode: vec2f; @@ -52,7 +46,7 @@ uniform vBaseColor: vec4f; uniform vBaseDiffuseRoughness: f32; uniform vReflectanceInfo: vec4f; uniform vSpecularColor: vec4f; -uniform vEmissiveColor: vec3f; +uniform vEmissionColor: vec3f; uniform vBaseWeightInfos: vec2f; uniform baseWeightMatrix: mat4x4f; @@ -60,12 +54,18 @@ uniform vBaseColorInfos: vec2f; uniform baseColorMatrix: mat4x4f; uniform vBaseDiffuseRoughnessInfos: vec2f; uniform baseDiffuseRoughnessMatrix: mat4x4f; -uniform vBaseMetalRoughInfos: vec2f; -uniform baseMetalRoughMatrix: mat4x4f; uniform vSpecularWeightInfos: vec2f; uniform specularWeightMatrix: mat4x4f; uniform vSpecularColorInfos: vec2f; uniform specularColorMatrix: mat4x4f; +uniform vBaseMetalRoughInfos: vec2f; +uniform baseMetalRoughMatrix: mat4x4f; +uniform vGeometryOpacityInfos: vec2f; +uniform geometryOpacityMatrix: mat4x4f; +uniform vEmissionInfos: vec2f; +uniform emissionMatrix: mat4x4f; +uniform vAmbientOcclusionInfos: vec2f; +uniform ambientOcclusionMatrix: mat4x4f; #define ADDITIONAL_UBO_DECLARATION diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalColorComposition.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalColorComposition.fx index a56f7056b55..1f45834e4b8 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalColorComposition.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrBlockFinalColorComposition.fx @@ -10,7 +10,6 @@ var finalColor: vec4f = vec4f( finalRadianceScaled + #endif #endif - finalAmbient + finalDiffuse, alpha); @@ -26,7 +25,7 @@ var finalColor: vec4f = vec4f( #endif // _____________________________ EmissiveLight _____________________________________ -finalColor = vec4f(finalColor.rgb + finalEmissive, finalColor.a); +finalColor = vec4f(finalColor.rgb + finalEmission, finalColor.a); #define CUSTOM_FRAGMENT_BEFORE_FOG diff --git a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx index dd80615a595..78bf8a3c071 100644 --- a/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx +++ b/packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrFragmentSamplersDeclaration.fx @@ -1,14 +1,16 @@ #include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor,_SAMPLERNAME_,baseColor) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_SAMPLERNAME_,baseWeight) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_SAMPLERNAME_,baseDiffuseRoughness) -#include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_SAMPLERNAME_,ambient) -#include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_SAMPLERNAME_,opacity) -#include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_SAMPLERNAME_,emissive) -#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_SAMPLERNAME_,lightmap) #include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough,_SAMPLERNAME_,baseMetalRough) #include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight,_SAMPLERNAME_,specularWeight) #include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor,_SAMPLERNAME_,specularColor) +#include(_DEFINENAME_,GEOMETRY_OPACITY,_VARYINGNAME_,GeometryOpacity,_SAMPLERNAME_,geometryOpacity) +#include(_DEFINENAME_,EMISSION,_VARYINGNAME_,Emission,_SAMPLERNAME_,emission) + +#include(_DEFINENAME_,AMBIENT_OCCLUSION,_VARYINGNAME_,AmbientOcclusion,_SAMPLERNAME_,ambientOcclusion) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_SAMPLERNAME_,decal) +#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_SAMPLERNAME_,lightmap) + // Reflection #ifdef REFLECTION diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx index c7c5c09738d..3e29dd60f18 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.fragment.fx @@ -46,7 +46,7 @@ #include #include -#include +#include #include #include @@ -121,14 +121,14 @@ fn main(input: FragmentInputs) -> FragmentOutputs { // _____________________________ AO _______________________________ var aoOut: ambientOcclusionOutParams; -#ifdef AMBIENT - var ambientOcclusionColorMap: vec3f = textureSample(ambientSampler, ambientSamplerSampler, fragmentInputs.vAmbientUV + uvOffset).rgb; +#ifdef AMBIENT_OCCLUSION + var ambientOcclusionFromTexture: vec3f = textureSample(ambientOcclusionSampler, ambientOcclusionSamplerSampler, fragmentInputs.vAmbientOcclusionUV + uvOffset).rgb; #endif aoOut = ambientOcclusionBlock( - #ifdef AMBIENT - ambientOcclusionColorMap, - uniforms.vAmbientInfos + #ifdef AMBIENT_OCCLUSION + ambientOcclusionFromTexture, + uniforms.vAmbientOcclusionInfos #endif ); @@ -286,7 +286,29 @@ var specularColor: vec4f = uniforms.vSpecularColor; #include #endif // UNLIT - #include + // _____________________________ Diffuse ________________________________________ + var finalDiffuse: vec3f = diffuseBase; + finalDiffuse *= surfaceAlbedo; + finalDiffuse = max(finalDiffuse, vec3f(0.0)); + finalDiffuse *= uniforms.vLightingIntensity.x; + + // _____________________________ Emissive ________________________________________ + var finalEmission: vec3f = uniforms.vEmissionColor; + #ifdef EMISSION + var emissionColorTex: vec3f = textureSample(emissionSampler, emissionSamplerSampler, fragmentInputs.vEmissionUV + uvOffset).rgb; + #ifdef EMISSION_GAMMA + finalEmission *= toLinearSpaceVec3(emissionColorTex.rgb); + #else + finalEmission *= emissionColorTex.rgb; + #endif + finalEmission *= uniforms.vEmissionInfos.y; + #endif + finalEmission *= uniforms.vLightingIntensity.y; + + // ______________________________ Ambient ________________________________________ + #ifdef AMBIENT_OCCLUSION + finalDiffuse *= mix( vec3f(1.), aoOut.ambientOcclusionColor, 1.0 - uniforms.vAmbientOcclusionInfos.y); + #endif #define CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION diff --git a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx index 10fc816f04f..8daa3da7b79 100644 --- a/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx +++ b/packages/dev/core/src/ShadersWGSL/openpbr.vertex.fx @@ -32,16 +32,17 @@ attribute color: vec4f; #include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,Albedo) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness) -#include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail) -#include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient) -#include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity) -#include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive) -#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap) #include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough) #include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight) #include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor) +#include(_DEFINENAME_,GEOMETRY_OPACITY,_VARYINGNAME_,GeometryOpacity) +#include(_DEFINENAME_,EMISSION,_VARYINGNAME_,Emission) + +#include(_DEFINENAME_,AMBIENT_OCCLUSION,_VARYINGNAME_,AmbientOcclusion) #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal) +#include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail) +#include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap) // Output varying vPositionW: vec3f; @@ -202,17 +203,18 @@ fn main(input : VertexInputs) -> FragmentInputs { #include(_DEFINENAME_,BASE_COLOR,_VARYINGNAME_,BaseColor,_MATRIXNAME_,baseColor,_INFONAME_,BaseColorInfos.x) #include(_DEFINENAME_,BASE_WEIGHT,_VARYINGNAME_,BaseWeight,_MATRIXNAME_,baseWeight,_INFONAME_,BaseWeightInfos.x) #include(_DEFINENAME_,BASE_DIFFUSE_ROUGHNESS,_VARYINGNAME_,BaseDiffuseRoughness,_MATRIXNAME_,baseDiffuseRoughness,_INFONAME_,BaseDiffuseRoughnessInfos.x) - #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) - #include(_DEFINENAME_,AMBIENT,_VARYINGNAME_,Ambient,_MATRIXNAME_,ambient,_INFONAME_,AmbientInfos.x) - #include(_DEFINENAME_,OPACITY,_VARYINGNAME_,Opacity,_MATRIXNAME_,opacity,_INFONAME_,OpacityInfos.x) - #include(_DEFINENAME_,EMISSIVE,_VARYINGNAME_,Emissive,_MATRIXNAME_,emissive,_INFONAME_,EmissiveInfos.x) - #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_MATRIXNAME_,lightmap,_INFONAME_,LightmapInfos.x) #include(_DEFINENAME_,METALLIC_ROUGHNESS,_VARYINGNAME_,BaseMetalRough,_MATRIXNAME_,baseMetalRough,_INFONAME_,BaseMetalRoughInfos.x) #include(_DEFINENAME_,SPECULAR_WEIGHT,_VARYINGNAME_,SpecularWeight,_MATRIXNAME_,specularWeight,_INFONAME_,SpecularWeightInfos.x) #include(_DEFINENAME_,SPECULAR_COLOR,_VARYINGNAME_,SpecularColor,_MATRIXNAME_,specularColor,_INFONAME_,SpecularColorInfos.x) + #include(_DEFINENAME_,GEOMETRY_OPACITY,_VARYINGNAME_,GeometryOpacity,_MATRIXNAME_,geometryOpacity,_INFONAME_,GeometryOpacityInfos.x) + #include(_DEFINENAME_,EMISSION,_VARYINGNAME_,Emission,_MATRIXNAME_,emission,_INFONAME_,EmissionInfos.x) + + #include(_DEFINENAME_,AMBIENT_OCCLUSION,_VARYINGNAME_,AmbientOcclusion,_MATRIXNAME_,ambientOcclusion,_INFONAME_,AmbientOcclusionInfos.x) #include(_DEFINENAME_,BUMP,_VARYINGNAME_,Bump,_MATRIXNAME_,bump,_INFONAME_,BumpInfos.x) #include(_DEFINENAME_,DECAL,_VARYINGNAME_,Decal,_MATRIXNAME_,decal,_INFONAME_,DecalInfos.x) - + #include(_DEFINENAME_,DETAIL,_VARYINGNAME_,Detail,_MATRIXNAME_,detail,_INFONAME_,DetailInfos.x) + #include(_DEFINENAME_,LIGHTMAP,_VARYINGNAME_,Lightmap,_MATRIXNAME_,lightmap,_INFONAME_,LightmapInfos.x) + // TBN #include diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts index de92d12c984..815545e6e4b 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts @@ -68,12 +68,15 @@ export class MSFT_sRGBFactors implements IGLTFLoaderExtension { if (!(babylonMaterial as OpenPBRMaterial).baseColorTexture) { (babylonMaterial as OpenPBRMaterial).baseColor.toLinearSpaceToRef((babylonMaterial as OpenPBRMaterial).baseColor, useExactSrgbConversions); } + if (!(babylonMaterial as OpenPBRMaterial).specularColorTexture) { + (babylonMaterial as OpenPBRMaterial).specularColor.toLinearSpaceToRef((babylonMaterial as OpenPBRMaterial).specularColor, useExactSrgbConversions); + } } else { if (!(babylonMaterial as PBRMaterial).albedoTexture) { (babylonMaterial as PBRMaterial).albedoColor.toLinearSpaceToRef((babylonMaterial as PBRMaterial).albedoColor, useExactSrgbConversions); } if (!(babylonMaterial as PBRMaterial).reflectivityTexture) { - (babylonMaterial as PBRMaterial).reflectivityColor.toLinearSpaceToRef(babylonMaterial.reflectivityColor, useExactSrgbConversions); + (babylonMaterial as PBRMaterial).reflectivityColor.toLinearSpaceToRef((babylonMaterial as PBRMaterial).reflectivityColor, useExactSrgbConversions); } } diff --git a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts index 9b91b05253d..53bb821a4d5 100644 --- a/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts +++ b/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts @@ -2267,8 +2267,10 @@ export class GLTFLoader implements IGLTFLoader { // Moved to mesh so user can change materials on gltf meshes: babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation; babylonMaterial.fillMode = babylonDrawMode; babylonMaterial.enableSpecularAntiAliasing = true; - babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage; - babylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage; + if (!this.parent.useOpenPBR) { + (babylonMaterial as PBRMaterial).useRadianceOverAlpha = !this._parent.transparencyAsCoverage; + (babylonMaterial as PBRMaterial).useSpecularOverAlpha = !this._parent.transparencyAsCoverage; + } babylonMaterial.transparencyMode = PBRMaterialClass.PBRMATERIAL_OPAQUE; return babylonMaterial; @@ -2361,18 +2363,21 @@ export class GLTFLoader implements IGLTFLoader { babylonMaterial.forceIrradianceInFragment = true; } + let aoTexture: BaseTexture; + let aoStrength: number = 1.0; + let emissionTexture: BaseTexture; + if (material.occlusionTexture) { material.occlusionTexture.nonColorData = true; promises.push( this.loadTextureInfoAsync(`${context}/occlusionTexture`, material.occlusionTexture, (texture) => { texture.name = `${babylonMaterial.name} (Occlusion)`; - babylonMaterial.ambientTexture = texture; + aoTexture = texture; }) ); - babylonMaterial.useAmbientInGrayScale = true; if (material.occlusionTexture.strength != undefined) { - babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength; + aoStrength = material.occlusionTexture.strength; } } @@ -2380,12 +2385,25 @@ export class GLTFLoader implements IGLTFLoader { promises.push( this.loadTextureInfoAsync(`${context}/emissiveTexture`, material.emissiveTexture, (texture) => { texture.name = `${babylonMaterial.name} (Emissive)`; - babylonMaterial.emissiveTexture = texture; + emissionTexture = texture; }) ); } - return Promise.all(promises).then(() => {}); + return Promise.all(promises).then(() => { + if (this.parent.useOpenPBR) { + (babylonMaterial as OpenPBRMaterial).ambientOcclusionTexture = aoTexture; + (babylonMaterial as OpenPBRMaterial).emissionTexture = emissionTexture; + if (aoTexture) { + (babylonMaterial as OpenPBRMaterial).ambientOcclusionTexture.level = aoStrength; + } + } else { + (babylonMaterial as PBRMaterial).ambientTexture = aoTexture; + (babylonMaterial as PBRMaterial).emissiveTexture = emissionTexture; + (babylonMaterial as PBRMaterial).useAmbientInGrayScale = true; + (babylonMaterial as PBRMaterial).ambientTextureStrength = aoStrength; + } + }); } /**