UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

1,105 lines (1,104 loc) 84.5 kB
import { __decorate } from "../tslib.es6.js"; /* eslint-disable @typescript-eslint/naming-convention */ import { serialize, serializeAsColor3, expandToProperty, serializeAsFresnelParameters, serializeAsTexture } from "../Misc/decorators.js"; import { SmartArray } from "../Misc/smartArray.js"; import { Scene } from "../scene.js"; import { Color3 } from "../Maths/math.color.js"; import { VertexBuffer } from "../Buffers/buffer.js"; import { PrePassConfiguration } from "./prePassConfiguration.js"; import { ImageProcessingConfiguration } from "./imageProcessingConfiguration.js"; import { Material } from "../Materials/material.js"; import { MaterialDefines } from "../Materials/materialDefines.js"; import { PushMaterial } from "./pushMaterial.js"; import { Texture } from "../Materials/Textures/texture.js"; import { RegisterClass } from "../Misc/typeStore.js"; import { MaterialFlags } from "./materialFlags.js"; import { EffectFallbacks } from "./effectFallbacks.js"; import { DetailMapConfiguration } from "./material.detailMapConfiguration.js"; import { AddClipPlaneUniforms, BindClipPlane } from "./clipPlaneMaterialHelper.js"; import { BindBonesParameters, BindFogParameters, BindLights, BindLogDepth, BindMorphTargetParameters, BindTextureMatrix, HandleFallbacksForShadows, PrepareAttributesForBakedVertexAnimation, PrepareAttributesForBones, PrepareAttributesForInstances, PrepareAttributesForMorphTargets, PrepareDefinesForAttributes, PrepareDefinesForFrameBoundValues, PrepareDefinesForLights, PrepareDefinesForMergedUV, PrepareDefinesForMisc, PrepareDefinesForMultiview, PrepareDefinesForOIT, PrepareDefinesForPrePass, PrepareUniformsAndSamplersList, } from "./materialHelper.functions.js"; import { SerializationHelper } from "../Misc/decorators.serialization.js"; import { MaterialHelperGeometryRendering } from "./materialHelper.geometryrendering.js"; const onCreatedEffectParameters = { effect: null, subMesh: null }; /** @internal */ export class StandardMaterialDefines extends MaterialDefines { /** * Initializes the Standard Material defines. * @param externalProperties The external properties */ constructor(externalProperties) { super(externalProperties); this.MAINUV1 = false; this.MAINUV2 = false; this.MAINUV3 = false; this.MAINUV4 = false; this.MAINUV5 = false; this.MAINUV6 = false; this.DIFFUSE = false; this.DIFFUSEDIRECTUV = 0; this.BAKED_VERTEX_ANIMATION_TEXTURE = false; this.AMBIENT = false; this.AMBIENTDIRECTUV = 0; this.OPACITY = false; this.OPACITYDIRECTUV = 0; this.OPACITYRGB = false; this.REFLECTION = false; this.EMISSIVE = false; this.EMISSIVEDIRECTUV = 0; this.SPECULAR = false; this.SPECULARDIRECTUV = 0; this.BUMP = false; this.BUMPDIRECTUV = 0; this.PARALLAX = false; this.PARALLAX_RHS = false; this.PARALLAXOCCLUSION = false; this.SPECULAROVERALPHA = false; this.CLIPPLANE = false; this.CLIPPLANE2 = false; this.CLIPPLANE3 = false; this.CLIPPLANE4 = false; this.CLIPPLANE5 = false; this.CLIPPLANE6 = false; this.ALPHATEST = false; this.DEPTHPREPASS = false; this.ALPHAFROMDIFFUSE = false; this.POINTSIZE = false; this.FOG = false; this.SPECULARTERM = false; this.DIFFUSEFRESNEL = false; this.OPACITYFRESNEL = false; this.REFLECTIONFRESNEL = false; this.REFRACTIONFRESNEL = false; this.EMISSIVEFRESNEL = false; this.FRESNEL = false; this.NORMAL = false; this.TANGENT = false; this.UV1 = false; this.UV2 = false; this.UV3 = false; this.UV4 = false; this.UV5 = false; this.UV6 = false; this.VERTEXCOLOR = false; this.VERTEXALPHA = false; this.NUM_BONE_INFLUENCERS = 0; this.BonesPerMesh = 0; this.BONETEXTURE = false; this.BONES_VELOCITY_ENABLED = false; this.INSTANCES = false; this.THIN_INSTANCES = false; this.INSTANCESCOLOR = false; this.GLOSSINESS = false; this.ROUGHNESS = false; this.EMISSIVEASILLUMINATION = false; this.LINKEMISSIVEWITHDIFFUSE = false; this.REFLECTIONFRESNELFROMSPECULAR = false; this.LIGHTMAP = false; this.LIGHTMAPDIRECTUV = 0; this.OBJECTSPACE_NORMALMAP = false; this.USELIGHTMAPASSHADOWMAP = false; this.REFLECTIONMAP_3D = false; this.REFLECTIONMAP_SPHERICAL = false; this.REFLECTIONMAP_PLANAR = false; this.REFLECTIONMAP_CUBIC = false; this.USE_LOCAL_REFLECTIONMAP_CUBIC = false; this.USE_LOCAL_REFRACTIONMAP_CUBIC = false; this.REFLECTIONMAP_PROJECTION = false; this.REFLECTIONMAP_SKYBOX = false; this.REFLECTIONMAP_EXPLICIT = false; this.REFLECTIONMAP_EQUIRECTANGULAR = false; this.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false; this.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false; this.REFLECTIONMAP_OPPOSITEZ = false; this.INVERTCUBICMAP = false; this.LOGARITHMICDEPTH = false; this.REFRACTION = false; this.REFRACTIONMAP_3D = false; this.REFLECTIONOVERALPHA = false; this.TWOSIDEDLIGHTING = false; this.SHADOWFLOAT = false; this.MORPHTARGETS = false; this.MORPHTARGETS_POSITION = false; this.MORPHTARGETS_NORMAL = false; this.MORPHTARGETS_TANGENT = false; this.MORPHTARGETS_UV = false; this.MORPHTARGETS_UV2 = false; this.MORPHTARGETS_COLOR = false; this.MORPHTARGETTEXTURE_HASPOSITIONS = false; this.MORPHTARGETTEXTURE_HASNORMALS = false; this.MORPHTARGETTEXTURE_HASTANGENTS = false; this.MORPHTARGETTEXTURE_HASUVS = false; this.MORPHTARGETTEXTURE_HASUV2S = false; this.MORPHTARGETTEXTURE_HASCOLORS = false; this.NUM_MORPH_INFLUENCERS = 0; this.MORPHTARGETS_TEXTURE = false; this.NONUNIFORMSCALING = false; // https://playground.babylonjs.com#V6DWIH this.PREMULTIPLYALPHA = false; // https://playground.babylonjs.com#LNVJJ7 this.ALPHATEST_AFTERALLALPHACOMPUTATIONS = false; this.ALPHABLEND = true; this.PREPASS = false; this.PREPASS_COLOR = false; this.PREPASS_COLOR_INDEX = -1; this.PREPASS_IRRADIANCE = false; this.PREPASS_IRRADIANCE_INDEX = -1; this.PREPASS_ALBEDO = false; this.PREPASS_ALBEDO_INDEX = -1; this.PREPASS_ALBEDO_SQRT = false; this.PREPASS_ALBEDO_SQRT_INDEX = -1; this.PREPASS_DEPTH = false; this.PREPASS_DEPTH_INDEX = -1; this.PREPASS_SCREENSPACE_DEPTH = false; this.PREPASS_SCREENSPACE_DEPTH_INDEX = -1; this.PREPASS_NORMALIZED_VIEW_DEPTH = false; this.PREPASS_NORMALIZED_VIEW_DEPTH_INDEX = -1; this.PREPASS_NORMAL = false; this.PREPASS_NORMAL_INDEX = -1; this.PREPASS_NORMAL_WORLDSPACE = false; this.PREPASS_WORLD_NORMAL = false; this.PREPASS_WORLD_NORMAL_INDEX = -1; this.PREPASS_POSITION = false; this.PREPASS_POSITION_INDEX = -1; this.PREPASS_LOCAL_POSITION = false; this.PREPASS_LOCAL_POSITION_INDEX = -1; this.PREPASS_VELOCITY = false; this.PREPASS_VELOCITY_INDEX = -1; this.PREPASS_VELOCITY_LINEAR = false; this.PREPASS_VELOCITY_LINEAR_INDEX = -1; this.PREPASS_REFLECTIVITY = false; this.PREPASS_REFLECTIVITY_INDEX = -1; this.SCENE_MRT_COUNT = 0; this.RGBDLIGHTMAP = false; this.RGBDREFLECTION = false; this.RGBDREFRACTION = false; this.IMAGEPROCESSING = false; this.VIGNETTE = false; this.VIGNETTEBLENDMODEMULTIPLY = false; this.VIGNETTEBLENDMODEOPAQUE = false; this.TONEMAPPING = 0; this.CONTRAST = false; this.COLORCURVES = false; this.COLORGRADING = false; this.COLORGRADING3D = false; this.SAMPLER3DGREENDEPTH = false; this.SAMPLER3DBGRMAP = false; this.DITHER = false; this.IMAGEPROCESSINGPOSTPROCESS = false; this.SKIPFINALCOLORCLAMP = false; this.MULTIVIEW = false; this.ORDER_INDEPENDENT_TRANSPARENCY = false; this.ORDER_INDEPENDENT_TRANSPARENCY_16BITS = false; this.CAMERA_ORTHOGRAPHIC = false; this.CAMERA_PERSPECTIVE = false; this.AREALIGHTSUPPORTED = true; this.USE_VERTEX_PULLING = false; /** * If the reflection texture on this material is in linear color space * @internal */ this.IS_REFLECTION_LINEAR = false; /** * If the refraction texture on this material is in linear color space * @internal */ this.IS_REFRACTION_LINEAR = false; this.EXPOSURE = false; this.DECAL_AFTER_DETAIL = false; this.rebuild(); } setReflectionMode(modeToEnable) { 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; } } } /** * 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 { /** * Gets the image processing configuration used either in this material. */ get 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. */ set imageProcessingConfiguration(value) { this._attachImageProcessingConfiguration(value); // Ensure the effect will be rebuilt. this._markAllSubMeshesAsImageProcessingDirty(); } /** * Attaches a new image processing configuration to the Standard Material. * @param configuration */ _attachImageProcessingConfiguration(configuration) { 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(); }); } } /** * Can this material render to prepass */ get isPrePassCapable() { return !this.disableDepthWrite; } /** * Gets whether the color curves effect is enabled. */ get cameraColorCurvesEnabled() { return this.imageProcessingConfiguration.colorCurvesEnabled; } /** * Sets whether the color curves effect is enabled. */ set cameraColorCurvesEnabled(value) { this.imageProcessingConfiguration.colorCurvesEnabled = value; } /** * Gets whether the color grading effect is enabled. */ get cameraColorGradingEnabled() { return this.imageProcessingConfiguration.colorGradingEnabled; } /** * Gets whether the color grading effect is enabled. */ set cameraColorGradingEnabled(value) { this.imageProcessingConfiguration.colorGradingEnabled = value; } /** * Gets whether tonemapping is enabled or not. */ get cameraToneMappingEnabled() { return this._imageProcessingConfiguration.toneMappingEnabled; } /** * Sets whether tonemapping is enabled or not */ set cameraToneMappingEnabled(value) { 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. */ get cameraExposure() { 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. */ set cameraExposure(value) { this._imageProcessingConfiguration.exposure = value; } /** * Gets The camera contrast used on this material. */ get cameraContrast() { return this._imageProcessingConfiguration.contrast; } /** * Sets The camera contrast used on this material. */ set cameraContrast(value) { this._imageProcessingConfiguration.contrast = value; } /** * Gets the Color Grading 2D Lookup Texture. */ get cameraColorGradingTexture() { return this._imageProcessingConfiguration.colorGradingTexture; } /** * Sets the Color Grading 2D Lookup Texture. */ set cameraColorGradingTexture(value) { 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. */ get cameraColorCurves() { 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. */ set cameraColorCurves(value) { this._imageProcessingConfiguration.colorCurves = value; } /** * Can this material render to several textures at once */ get canRenderToMRT() { return true; } /** * Instantiates a new standard material. * 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 * @param name Define the name of the material in the scene * @param scene Define the scene the material belong to * @param forceGLSL Use the GLSL code generation for the shader (even on WebGPU). Default is false */ constructor(name, scene, forceGLSL = false) { super(name, scene, undefined, forceGLSL || StandardMaterial.ForceGLSL); this._diffuseTexture = null; this._ambientTexture = null; this._opacityTexture = null; this._reflectionTexture = null; this._emissiveTexture = null; this._specularTexture = null; this._bumpTexture = null; this._lightmapTexture = null; this._refractionTexture = null; /** * The color of the material lit by the environmental background lighting. * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/using/materials_introduction#ambient-color-example */ this.ambientColor = new Color3(0, 0, 0); /** * The basic color of the material as viewed under a light. */ this.diffuseColor = new Color3(1, 1, 1); /** * Define how the color and intensity of the highlight given by the light in the material. */ this.specularColor = new Color3(1, 1, 1); /** * Define the color of the material as if self lit. * This will be mixed in the final result even in the absence of light. */ this.emissiveColor = new Color3(0, 0, 0); /** * Defines how sharp are the highlights in the material. * The bigger the value the sharper giving a more glossy feeling to the result. * Reversely, the smaller the value the blurrier giving a more rough feeling to the result. */ this.specularPower = 64; this._useAlphaFromDiffuseTexture = false; this._useEmissiveAsIllumination = false; this._linkEmissiveWithDiffuse = false; this._useSpecularOverAlpha = false; this._useReflectionOverAlpha = false; this._disableLighting = false; this._useObjectSpaceNormalMap = false; this._useParallax = false; this._useParallaxOcclusion = false; /** * Apply a scaling factor that determine which "depth" the height map should reprensent. A value between 0.05 and 0.1 is reasonnable in Parallax, you can reach 0.2 using Parallax Occlusion. */ this.parallaxScaleBias = 0.05; this._roughness = 0; /** * In case of refraction, define the value of the index of refraction. * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/using/reflectionTexture#how-to-obtain-reflections-and-refractions */ this.indexOfRefraction = 0.98; /** * Invert the refraction texture alongside the y axis. * It can be useful with procedural textures or probe for instance. * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/using/reflectionTexture#how-to-obtain-reflections-and-refractions */ this.invertRefractionY = true; /** * Defines the alpha limits in alpha test mode. */ this.alphaCutOff = 0.4; this._useLightmapAsShadowmap = false; this._useReflectionFresnelFromSpecular = false; this._useGlossinessFromSpecularMapAlpha = false; this._maxSimultaneousLights = 4; this._invertNormalMapX = false; this._invertNormalMapY = false; this._twoSidedLighting = false; this._applyDecalMapAfterDetailMap = false; this._shadersLoaded = false; this._renderTargets = new SmartArray(16); this._globalAmbientColor = new Color3(0, 0, 0); this._cacheHasRenderTargetTextures = false; this.detailMap = new DetailMapConfiguration(this); // Setup the default processing configuration to the scene. this._attachImageProcessingConfiguration(null); this.prePassConfiguration = new PrePassConfiguration(); this.getRenderTargetTextures = () => { this._renderTargets.reset(); if (StandardMaterial.ReflectionTextureEnabled && this._reflectionTexture && this._reflectionTexture.isRenderTarget) { this._renderTargets.push(this._reflectionTexture); } if (StandardMaterial.RefractionTextureEnabled && this._refractionTexture && this._refractionTexture.isRenderTarget) { this._renderTargets.push(this._refractionTexture); } this._eventInfo.renderTargets = this._renderTargets; this._callbackPluginEventFillRenderTargetTextures(this._eventInfo); return this._renderTargets; }; } /** * Gets a boolean indicating that current material needs to register RTT */ get hasRenderTargetTextures() { if (StandardMaterial.ReflectionTextureEnabled && this._reflectionTexture && this._reflectionTexture.isRenderTarget) { return true; } if (StandardMaterial.RefractionTextureEnabled && this._refractionTexture && this._refractionTexture.isRenderTarget) { return true; } return this._cacheHasRenderTargetTextures; } /** * Gets the current class name of the material e.g. "StandardMaterial" * Mainly use in serialization. * @returns the class name */ getClassName() { return "StandardMaterial"; } /** * Specifies if the material will require alpha blending * @returns a boolean specifying if alpha blending is needed */ needAlphaBlending() { if (this._hasTransparencyMode) { return this._transparencyModeIsBlend; } if (this._disableAlphaBlending) { return false; } return (this.alpha < 1.0 || this._opacityTexture != null || this._shouldUseAlphaFromDiffuseTexture() || (this._opacityFresnelParameters && this._opacityFresnelParameters.isEnabled)); } /** * Specifies if this material should be rendered in alpha test mode * @returns a boolean specifying if an alpha test is needed. */ needAlphaTesting() { if (this._hasTransparencyMode) { return this._transparencyModeIsTest; } return this._hasAlphaChannel() && (this._transparencyMode == null || this._transparencyMode === Material.MATERIAL_ALPHATEST); } /** * @returns whether or not the alpha value of the diffuse texture should be used for alpha blending. */ _shouldUseAlphaFromDiffuseTexture() { return this._diffuseTexture != null && this._diffuseTexture.hasAlpha && this._useAlphaFromDiffuseTexture && this._transparencyMode !== Material.MATERIAL_OPAQUE; } /** * @returns whether or not there is a usable alpha channel for transparency. */ _hasAlphaChannel() { return (this._diffuseTexture != null && this._diffuseTexture.hasAlpha) || this._opacityTexture != null; } /** * Get the texture used for alpha test purpose. * @returns the diffuse texture in case of the standard material. */ getAlphaTestTexture() { return this._diffuseTexture; } /** * Get if the submesh is ready to be used and all its information available. * Child classes can use it to update shaders * @param mesh defines the mesh to check * @param subMesh defines which submesh to check * @param useInstances specifies that instances should be used * @returns a boolean indicating that the submesh is ready or not */ isReadyForSubMesh(mesh, subMesh, useInstances = false) { 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(4 /* MaterialPluginEvent.GetDefineNames */, this._eventInfo); subMesh.materialDefines = new StandardMaterialDefines(this._eventInfo.defineNames); } const scene = this.getScene(); const defines = subMesh.materialDefines; if (this._isReadyForSubMesh(subMesh)) { return true; } const engine = scene.getEngine(); // Lights defines._needNormals = PrepareDefinesForLights(scene, mesh, defines, true, this._maxSimultaneousLights, this._disableLighting); // 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 if (defines._areTexturesDirty) { this._eventInfo.hasRenderTargetTextures = false; this._callbackPluginEventHasRenderTargetTextures(this._eventInfo); this._cacheHasRenderTargetTextures = this._eventInfo.hasRenderTargetTextures; defines._needUVs = false; for (let i = 1; i <= 6; ++i) { defines["MAINUV" + i] = false; } if (scene.texturesEnabled) { defines.DIFFUSEDIRECTUV = 0; defines.BUMPDIRECTUV = 0; defines.AMBIENTDIRECTUV = 0; defines.OPACITYDIRECTUV = 0; defines.EMISSIVEDIRECTUV = 0; defines.SPECULARDIRECTUV = 0; defines.LIGHTMAPDIRECTUV = 0; if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) { if (!this._diffuseTexture.isReadyOrNotBlocking()) { return false; } else { PrepareDefinesForMergedUV(this._diffuseTexture, defines, "DIFFUSE"); } } else { defines.DIFFUSE = false; } if (this._ambientTexture && StandardMaterial.AmbientTextureEnabled) { if (!this._ambientTexture.isReadyOrNotBlocking()) { return false; } else { PrepareDefinesForMergedUV(this._ambientTexture, defines, "AMBIENT"); } } else { defines.AMBIENT = false; } if (this._opacityTexture && StandardMaterial.OpacityTextureEnabled) { if (!this._opacityTexture.isReadyOrNotBlocking()) { return false; } else { PrepareDefinesForMergedUV(this._opacityTexture, defines, "OPACITY"); defines.OPACITYRGB = this._opacityTexture.getAlphaFromRGB; } } 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; } if (this._emissiveTexture && StandardMaterial.EmissiveTextureEnabled) { if (!this._emissiveTexture.isReadyOrNotBlocking()) { return false; } else { PrepareDefinesForMergedUV(this._emissiveTexture, defines, "EMISSIVE"); } } else { defines.EMISSIVE = false; } if (this._lightmapTexture && StandardMaterial.LightmapTextureEnabled) { if (!this._lightmapTexture.isReadyOrNotBlocking()) { return false; } else { PrepareDefinesForMergedUV(this._lightmapTexture, defines, "LIGHTMAP"); defines.USELIGHTMAPASSHADOWMAP = this._useLightmapAsShadowmap; defines.RGBDLIGHTMAP = this._lightmapTexture.isRGBD; } } else { defines.LIGHTMAP = false; } if (this._specularTexture && StandardMaterial.SpecularTextureEnabled) { if (!this._specularTexture.isReadyOrNotBlocking()) { return false; } else { PrepareDefinesForMergedUV(this._specularTexture, defines, "SPECULAR"); defines.GLOSSINESS = this._useGlossinessFromSpecularMapAlpha; } } else { defines.SPECULAR = false; } if (scene.getEngine().getCaps().standardDerivatives && this._bumpTexture && StandardMaterial.BumpTextureEnabled) { // Bump texture can not be not blocking. if (!this._bumpTexture.isReady()) { return false; } else { PrepareDefinesForMergedUV(this._bumpTexture, defines, "BUMP"); defines.PARALLAX = this._useParallax; defines.PARALLAX_RHS = scene.useRightHandedSystem; defines.PARALLAXOCCLUSION = this._useParallaxOcclusion; } defines.OBJECTSPACE_NORMALMAP = this._useObjectSpaceNormalMap; } else { defines.BUMP = false; defines.PARALLAX = false; defines.PARALLAX_RHS = false; defines.PARALLAXOCCLUSION = false; } if (this._refractionTexture && StandardMaterial.RefractionTextureEnabled) { if (!this._refractionTexture.isReadyOrNotBlocking()) { return false; } else { defines._needUVs = true; defines.REFRACTION = true; defines.REFRACTIONMAP_3D = this._refractionTexture.isCube; defines.RGBDREFRACTION = this._refractionTexture.isRGBD; defines.USE_LOCAL_REFRACTIONMAP_CUBIC = this._refractionTexture.boundingBoxSize ? true : false; } } else { defines.REFRACTION = false; } defines.TWOSIDEDLIGHTING = !this._backFaceCulling && this._twoSidedLighting; } else { defines.DIFFUSE = false; defines.AMBIENT = false; defines.OPACITY = false; defines.REFLECTION = false; defines.EMISSIVE = false; defines.LIGHTMAP = false; defines.BUMP = false; defines.REFRACTION = false; } defines.ALPHAFROMDIFFUSE = this._shouldUseAlphaFromDiffuseTexture(); defines.EMISSIVEASILLUMINATION = this._useEmissiveAsIllumination; defines.LINKEMISSIVEWITHDIFFUSE = this._linkEmissiveWithDiffuse; defines.SPECULAROVERALPHA = this._useSpecularOverAlpha; defines.PREMULTIPLYALPHA = this.alphaMode === 7 || this.alphaMode === 8; defines.ALPHATEST_AFTERALLALPHACOMPUTATIONS = this.transparencyMode !== null; defines.ALPHABLEND = this.transparencyMode === null || this.needAlphaBlendingForMesh(mesh); // check on null for backward compatibility } 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; } this._imageProcessingConfiguration.prepareDefines(defines); defines.IS_REFLECTION_LINEAR = this.reflectionTexture != null && !this.reflectionTexture.gammaSpace; defines.IS_REFRACTION_LINEAR = this.refractionTexture != null && !this.refractionTexture.gammaSpace; } if (defines._areFresnelDirty) { if (StandardMaterial.FresnelEnabled) { // Fresnel if (this._diffuseFresnelParameters || this._opacityFresnelParameters || this._emissiveFresnelParameters || this._refractionFresnelParameters || this._reflectionFresnelParameters) { defines.DIFFUSEFRESNEL = this._diffuseFresnelParameters && this._diffuseFresnelParameters.isEnabled; defines.OPACITYFRESNEL = this._opacityFresnelParameters && this._opacityFresnelParameters.isEnabled; defines.REFLECTIONFRESNEL = this._reflectionFresnelParameters && this._reflectionFresnelParameters.isEnabled; defines.REFLECTIONFRESNELFROMSPECULAR = this._useReflectionFresnelFromSpecular; defines.REFRACTIONFRESNEL = this._refractionFresnelParameters && this._refractionFresnelParameters.isEnabled; defines.EMISSIVEFRESNEL = this._emissiveFresnelParameters && this._emissiveFresnelParameters.isEnabled; defines._needNormals = true; defines.FRESNEL = true; } } else { defines.FRESNEL = 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; } } } // Misc. PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, this.needAlphaTestingForMesh(mesh), defines, this._applyDecalMapAfterDetailMap, this._useVertexPulling, subMesh.getRenderingMesh()); // Values that need to be evaluated on every frame PrepareDefinesForFrameBoundValues(scene, engine, this, defines, useInstances, null, subMesh.getRenderingMesh().hasThinInstances); // External config this._eventInfo.defines = defines; this._eventInfo.mesh = mesh; this._callbackPluginEventPrepareDefinesBeforeAttributes(this._eventInfo); // Attribs PrepareDefinesForAttributes(mesh, defines, true, true, true); // External config this._callbackPluginEventPrepareDefines(this._eventInfo); // Get correct effect let forceWasNotReadyPreviously = false; if (defines.isDirty) { const lightDisposed = defines._areLightsDisposed; defines.markAsProcessed(); // Fallbacks const fallbacks = new EffectFallbacks(); if (defines.REFLECTION) { fallbacks.addFallback(0, "REFLECTION"); } if (defines.SPECULAR) { fallbacks.addFallback(0, "SPECULAR"); } if (defines.BUMP) { fallbacks.addFallback(0, "BUMP"); } if (defines.PARALLAX) { fallbacks.addFallback(1, "PARALLAX"); } if (defines.PARALLAX_RHS) { fallbacks.addFallback(1, "PARALLAX_RHS"); } if (defines.PARALLAXOCCLUSION) { fallbacks.addFallback(0, "PARALLAXOCCLUSION"); } if (defines.SPECULAROVERALPHA) { fallbacks.addFallback(0, "SPECULAROVERALPHA"); } if (defines.FOG) { fallbacks.addFallback(1, "FOG"); } if (defines.POINTSIZE) { fallbacks.addFallback(0, "POINTSIZE"); } if (defines.LOGARITHMICDEPTH) { fallbacks.addFallback(0, "LOGARITHMICDEPTH"); } HandleFallbacksForShadows(defines, fallbacks, this._maxSimultaneousLights); if (defines.SPECULARTERM) { fallbacks.addFallback(0, "SPECULARTERM"); } if (defines.DIFFUSEFRESNEL) { fallbacks.addFallback(1, "DIFFUSEFRESNEL"); } if (defines.OPACITYFRESNEL) { fallbacks.addFallback(2, "OPACITYFRESNEL"); } if (defines.REFLECTIONFRESNEL) { fallbacks.addFallback(3, "REFLECTIONFRESNEL"); } if (defines.EMISSIVEFRESNEL) { fallbacks.addFallback(4, "EMISSIVEFRESNEL"); } if (defines.FRESNEL) { fallbacks.addFallback(4, "FRESNEL"); } 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 <= 6; ++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 = "default"; const uniforms = [ "world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vDiffuseColor", "vSpecularColor", "vEmissiveColor", "visibility", "vFogInfos", "vFogColor", "pointSize", "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos", "vRefractionInfos", "mBones", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "normalMatrix", "lightmapMatrix", "refractionMatrix", "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor", "refractionLeftColor", "refractionRightColor", "vReflectionPosition", "vReflectionSize", "vRefractionPosition", "vRefractionSize", "logarithmicDepthConstant", "vTangentSpaceParams", "alphaCutOff", "boneTextureWidth", "morphTargetTextureInfo", "morphTargetTextureIndices", "cameraInfo", ]; const samplers = [ "diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler", "boneSampler", "morphTargets", "oitDepthSampler", "oitFrontColorSampler", "areaLightsLTC1Sampler", "areaLightsLTC2Sampler", ]; const uniformBuffers = ["Material", "Scene", "Mesh"]; const indexParameters = { maxSimultaneousLights: this._maxSimultaneousLights, maxSimultaneousMorphTargets: defines.NUM_MORPH_INFLUENCERS }; this._eventInfo.fallbacks = fallbacks; this._eventInfo.fallbackRank = 0; 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(128 /* MaterialPluginEvent.PrepareEffect */, this._eventInfo); MaterialHelperGeometryRendering.AddUniformsAndSamplers(uniforms, samplers); PrePassConfiguration.AddUniforms(uniforms); PrePassConfiguration.AddSamplers(samplers); if (ImageProcessingConfiguration) { ImageProcessingConfiguration.PrepareUniforms(uniforms, defines); ImageProcessingConfiguration.PrepareSamplers(samplers, defines); } PrepareUniformsAndSamplersList({ uniformsNames: uniforms, uniformBuffersNames: uniformBuffers, samplers: samplers, defines: defines, maxSimultaneousLights: this._maxSimultaneousLights, }); AddClipPlaneUniforms(uniforms); const csnrOptions = {}; if (this.customShaderNameResolve) { shaderName = this.customShaderNameResolve(shaderName, uniforms, uniformBuffers, samplers, defines, attribs, csnrOptions); } const join = defines.toString(); const previousEffect = subMesh.effect; let effect = scene.getEngine().createEffect(shaderName, { attributes: attribs, uniformsNames: uniforms, uniformBuffersNames: uniformBuffers, samplers: samplers, defines: join, fallbacks: fallbacks, onCompiled: this.onCompiled, onError: this.onError, indexParameters, processFinalCode: csnrOptions.processFinalCode, processCodeAfterIncludes: this._eventInfo.customCode, multiTarget: defines.PREPASS, shaderLanguage: this._shaderLanguage, extraInitializationsAsync: this._shadersLoaded ? undefined : async () => { if (this._shaderLanguage === 1 /* ShaderLanguage.WGSL */) { await Promise.all([import("../ShadersWGSL/default.vertex.js"), import("../ShadersWGSL/default.fragment.js")]); } else { await Promise.all([import("../Shaders/default.vertex.js"), import("../Shaders/default.fragment.js")]); } this._shadersLoaded = true; }, }, engine); this._eventInfo.customCode = undefined; 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; } /** * Builds the material UBO layouts. * Used internally during the effect preparation. */ buildUniformLayout() { // Order is important ! const ubo = this._uniformBuffer; ubo.addUniform("diffuseLeftColor", 4); ubo.addUniform("diffuseRightColor", 4); ubo.addUniform("opacityParts", 4); ubo.addUniform("reflectionLeftColor", 4); ubo.addUniform("reflectionRightColor", 4); ubo.addUniform("refractionLeftColor", 4); ubo.addUniform("refractionRightColor", 4); ubo.addUniform("emissiveLeftColor", 4); ubo.addUniform("emissiveRightColor", 4); 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"