123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829 |
- import { __decorate } from "../tslib.es6.js";
- import { serialize, serializeAsColor4, serializeAsCameraReference } from "../Misc/decorators.js";
- import { Tools } from "../Misc/tools.js";
- import { Observable } from "../Misc/observable.js";
- import { Color4 } from "../Maths/math.color.js";
- import { EngineStore } from "../Engines/engineStore.js";
- import { VertexBuffer } from "../Buffers/buffer.js";
- import { Texture } from "../Materials/Textures/texture.js";
- import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture.js";
- import { Material } from "../Materials/material.js";
- import "../Shaders/glowMapGeneration.fragment.js";
- import "../Shaders/glowMapGeneration.vertex.js";
- import { _WarnImport } from "../Misc/devTools.js";
- import { EffectFallbacks } from "../Materials/effectFallbacks.js";
- import { DrawWrapper } from "../Materials/drawWrapper.js";
- import { addClipPlaneUniforms, bindClipPlane, prepareStringDefinesForClipPlanes } from "../Materials/clipPlaneMaterialHelper.js";
- import { BindMorphTargetParameters, PrepareAttributesForMorphTargetsInfluencers, PushAttributesForInstances } from "../Materials/materialHelper.functions.js";
- import { GetExponentOfTwo } from "../Misc/tools.functions.js";
- /**
- * The effect layer Helps adding post process effect blended with the main pass.
- *
- * This can be for instance use to generate glow or highlight effects on the scene.
- *
- * The effect layer class can not be used directly and is intented to inherited from to be
- * customized per effects.
- */
- export class EffectLayer {
- /**
- * Gets the camera attached to the layer.
- */
- get camera() {
- return this._effectLayerOptions.camera;
- }
- /**
- * Gets the rendering group id the layer should render in.
- */
- get renderingGroupId() {
- return this._effectLayerOptions.renderingGroupId;
- }
- set renderingGroupId(renderingGroupId) {
- this._effectLayerOptions.renderingGroupId = renderingGroupId;
- }
- /**
- * Gets the main texture where the effect is rendered
- */
- get mainTexture() {
- return this._mainTexture;
- }
- /**
- * Sets a specific material to be used to render a mesh/a list of meshes in the layer
- * @param mesh mesh or array of meshes
- * @param material material to use by the layer when rendering the mesh(es). If undefined is passed, the specific material created by the layer will be used.
- */
- setMaterialForRendering(mesh, material) {
- this._mainTexture.setMaterialForRendering(mesh, material);
- if (Array.isArray(mesh)) {
- for (let i = 0; i < mesh.length; ++i) {
- const currentMesh = mesh[i];
- if (!material) {
- delete this._materialForRendering[currentMesh.uniqueId];
- }
- else {
- this._materialForRendering[currentMesh.uniqueId] = [currentMesh, material];
- }
- }
- }
- else {
- if (!material) {
- delete this._materialForRendering[mesh.uniqueId];
- }
- else {
- this._materialForRendering[mesh.uniqueId] = [mesh, material];
- }
- }
- }
- /**
- * Gets the intensity of the effect for a specific mesh.
- * @param mesh The mesh to get the effect intensity for
- * @returns The intensity of the effect for the mesh
- */
- getEffectIntensity(mesh) {
- return this._effectIntensity[mesh.uniqueId] ?? 1;
- }
- /**
- * Sets the intensity of the effect for a specific mesh.
- * @param mesh The mesh to set the effect intensity for
- * @param intensity The intensity of the effect for the mesh
- */
- setEffectIntensity(mesh, intensity) {
- this._effectIntensity[mesh.uniqueId] = intensity;
- }
- /**
- * Instantiates a new effect Layer and references it in the scene.
- * @param name The name of the layer
- * @param scene The scene to use the layer in
- */
- constructor(
- /** The Friendly of the effect in the scene */
- name, scene) {
- this._vertexBuffers = {};
- this._maxSize = 0;
- this._mainTextureDesiredSize = { width: 0, height: 0 };
- this._shouldRender = true;
- this._postProcesses = [];
- this._textures = [];
- this._emissiveTextureAndColor = { texture: null, color: new Color4() };
- this._effectIntensity = {};
- /**
- * The clear color of the texture used to generate the glow map.
- */
- this.neutralColor = new Color4();
- /**
- * Specifies whether the highlight layer is enabled or not.
- */
- this.isEnabled = true;
- /**
- * Specifies if the bounding boxes should be rendered normally or if they should undergo the effect of the layer
- */
- this.disableBoundingBoxesFromEffectLayer = false;
- /**
- * An event triggered when the effect layer has been disposed.
- */
- this.onDisposeObservable = new Observable();
- /**
- * An event triggered when the effect layer is about rendering the main texture with the glowy parts.
- */
- this.onBeforeRenderMainTextureObservable = new Observable();
- /**
- * An event triggered when the generated texture is being merged in the scene.
- */
- this.onBeforeComposeObservable = new Observable();
- /**
- * An event triggered when the mesh is rendered into the effect render target.
- */
- this.onBeforeRenderMeshToEffect = new Observable();
- /**
- * An event triggered after the mesh has been rendered into the effect render target.
- */
- this.onAfterRenderMeshToEffect = new Observable();
- /**
- * An event triggered when the generated texture has been merged in the scene.
- */
- this.onAfterComposeObservable = new Observable();
- /**
- * An event triggered when the effect layer changes its size.
- */
- this.onSizeChangedObservable = new Observable();
- this._materialForRendering = {};
- this.name = name;
- this._scene = scene || EngineStore.LastCreatedScene;
- EffectLayer._SceneComponentInitialization(this._scene);
- this._engine = this._scene.getEngine();
- this._maxSize = this._engine.getCaps().maxTextureSize;
- this._scene.effectLayers.push(this);
- this._mergeDrawWrapper = [];
- // Generate Buffers
- this._generateIndexBuffer();
- this._generateVertexBuffer();
- }
- /**
- * Number of times _internalRender will be called. Some effect layers need to render the mesh several times, so they should override this method with the number of times the mesh should be rendered
- * @returns Number of times a mesh must be rendered in the layer
- */
- _numInternalDraws() {
- return 1;
- }
- /**
- * Initializes the effect layer with the required options.
- * @param options Sets of none mandatory options to use with the layer (see IEffectLayerOptions for more information)
- */
- _init(options) {
- // Adapt options
- this._effectLayerOptions = {
- mainTextureRatio: 0.5,
- alphaBlendingMode: 2,
- camera: null,
- renderingGroupId: -1,
- mainTextureType: 0,
- generateStencilBuffer: false,
- ...options,
- };
- this._setMainTextureSize();
- this._createMainTexture();
- this._createTextureAndPostProcesses();
- }
- /**
- * Generates the index buffer of the full screen quad blending to the main canvas.
- */
- _generateIndexBuffer() {
- // Indices
- const indices = [];
- indices.push(0);
- indices.push(1);
- indices.push(2);
- indices.push(0);
- indices.push(2);
- indices.push(3);
- this._indexBuffer = this._engine.createIndexBuffer(indices);
- }
- /**
- * Generates the vertex buffer of the full screen quad blending to the main canvas.
- */
- _generateVertexBuffer() {
- // VBO
- const vertices = [];
- vertices.push(1, 1);
- vertices.push(-1, 1);
- vertices.push(-1, -1);
- vertices.push(1, -1);
- const vertexBuffer = new VertexBuffer(this._engine, vertices, VertexBuffer.PositionKind, false, false, 2);
- this._vertexBuffers[VertexBuffer.PositionKind] = vertexBuffer;
- }
- /**
- * Sets the main texture desired size which is the closest power of two
- * of the engine canvas size.
- */
- _setMainTextureSize() {
- if (this._effectLayerOptions.mainTextureFixedSize) {
- this._mainTextureDesiredSize.width = this._effectLayerOptions.mainTextureFixedSize;
- this._mainTextureDesiredSize.height = this._effectLayerOptions.mainTextureFixedSize;
- }
- else {
- this._mainTextureDesiredSize.width = this._engine.getRenderWidth() * this._effectLayerOptions.mainTextureRatio;
- this._mainTextureDesiredSize.height = this._engine.getRenderHeight() * this._effectLayerOptions.mainTextureRatio;
- this._mainTextureDesiredSize.width = this._engine.needPOTTextures
- ? GetExponentOfTwo(this._mainTextureDesiredSize.width, this._maxSize)
- : this._mainTextureDesiredSize.width;
- this._mainTextureDesiredSize.height = this._engine.needPOTTextures
- ? GetExponentOfTwo(this._mainTextureDesiredSize.height, this._maxSize)
- : this._mainTextureDesiredSize.height;
- }
- this._mainTextureDesiredSize.width = Math.floor(this._mainTextureDesiredSize.width);
- this._mainTextureDesiredSize.height = Math.floor(this._mainTextureDesiredSize.height);
- }
- /**
- * Creates the main texture for the effect layer.
- */
- _createMainTexture() {
- this._mainTexture = new RenderTargetTexture("EffectLayerMainRTT", {
- width: this._mainTextureDesiredSize.width,
- height: this._mainTextureDesiredSize.height,
- }, this._scene, false, true, this._effectLayerOptions.mainTextureType, false, Texture.TRILINEAR_SAMPLINGMODE, true, this._effectLayerOptions.generateStencilBuffer);
- this._mainTexture.activeCamera = this._effectLayerOptions.camera;
- this._mainTexture.wrapU = Texture.CLAMP_ADDRESSMODE;
- this._mainTexture.wrapV = Texture.CLAMP_ADDRESSMODE;
- this._mainTexture.anisotropicFilteringLevel = 1;
- this._mainTexture.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
- this._mainTexture.renderParticles = false;
- this._mainTexture.renderList = null;
- this._mainTexture.ignoreCameraViewport = true;
- for (const id in this._materialForRendering) {
- const [mesh, material] = this._materialForRendering[id];
- this._mainTexture.setMaterialForRendering(mesh, material);
- }
- this._mainTexture.customIsReadyFunction = (mesh, refreshRate, preWarm) => {
- if ((preWarm || refreshRate === 0) && mesh.subMeshes) {
- for (let i = 0; i < mesh.subMeshes.length; ++i) {
- const subMesh = mesh.subMeshes[i];
- const material = subMesh.getMaterial();
- const renderingMesh = subMesh.getRenderingMesh();
- if (!material) {
- continue;
- }
- const batch = renderingMesh._getInstancesRenderList(subMesh._id, !!subMesh.getReplacementMesh());
- const hardwareInstancedRendering = batch.hardwareInstancedRendering[subMesh._id] || renderingMesh.hasThinInstances;
- this._setEmissiveTextureAndColor(renderingMesh, subMesh, material);
- if (!this._isReady(subMesh, hardwareInstancedRendering, this._emissiveTextureAndColor.texture)) {
- return false;
- }
- }
- }
- return true;
- };
- // Custom render function
- this._mainTexture.customRenderFunction = (opaqueSubMeshes, alphaTestSubMeshes, transparentSubMeshes, depthOnlySubMeshes) => {
- this.onBeforeRenderMainTextureObservable.notifyObservers(this);
- let index;
- const engine = this._scene.getEngine();
- if (depthOnlySubMeshes.length) {
- engine.setColorWrite(false);
- for (index = 0; index < depthOnlySubMeshes.length; index++) {
- this._renderSubMesh(depthOnlySubMeshes.data[index]);
- }
- engine.setColorWrite(true);
- }
- for (index = 0; index < opaqueSubMeshes.length; index++) {
- this._renderSubMesh(opaqueSubMeshes.data[index]);
- }
- for (index = 0; index < alphaTestSubMeshes.length; index++) {
- this._renderSubMesh(alphaTestSubMeshes.data[index]);
- }
- const previousAlphaMode = engine.getAlphaMode();
- for (index = 0; index < transparentSubMeshes.length; index++) {
- this._renderSubMesh(transparentSubMeshes.data[index], true);
- }
- engine.setAlphaMode(previousAlphaMode);
- };
- this._mainTexture.onClearObservable.add((engine) => {
- engine.clear(this.neutralColor, true, true, true);
- });
- // Prevent package size in es6 (getBoundingBoxRenderer might not be present)
- if (this._scene.getBoundingBoxRenderer) {
- const boundingBoxRendererEnabled = this._scene.getBoundingBoxRenderer().enabled;
- this._mainTexture.onBeforeBindObservable.add(() => {
- this._scene.getBoundingBoxRenderer().enabled = !this.disableBoundingBoxesFromEffectLayer && boundingBoxRendererEnabled;
- });
- this._mainTexture.onAfterUnbindObservable.add(() => {
- this._scene.getBoundingBoxRenderer().enabled = boundingBoxRendererEnabled;
- });
- }
- }
- /**
- * Adds specific effects defines.
- * @param defines The defines to add specifics to.
- */
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- _addCustomEffectDefines(defines) {
- // Nothing to add by default.
- }
- /**
- * Checks for the readiness of the element composing the layer.
- * @param subMesh the mesh to check for
- * @param useInstances specify whether or not to use instances to render the mesh
- * @param emissiveTexture the associated emissive texture used to generate the glow
- * @returns true if ready otherwise, false
- */
- _isReady(subMesh, useInstances, emissiveTexture) {
- const engine = this._scene.getEngine();
- const mesh = subMesh.getMesh();
- const renderingMaterial = mesh._internalAbstractMeshDataInfo._materialForRenderPass?.[engine.currentRenderPassId];
- if (renderingMaterial) {
- return renderingMaterial.isReadyForSubMesh(mesh, subMesh, useInstances);
- }
- const material = subMesh.getMaterial();
- if (!material) {
- return false;
- }
- if (this._useMeshMaterial(subMesh.getRenderingMesh())) {
- return material.isReadyForSubMesh(subMesh.getMesh(), subMesh, useInstances);
- }
- const defines = [];
- const attribs = [VertexBuffer.PositionKind];
- let uv1 = false;
- let uv2 = false;
- // Diffuse
- if (material) {
- const needAlphaTest = material.needAlphaTesting();
- const diffuseTexture = material.getAlphaTestTexture();
- const needAlphaBlendFromDiffuse = diffuseTexture && diffuseTexture.hasAlpha && (material.useAlphaFromDiffuseTexture || material._useAlphaFromAlbedoTexture);
- if (diffuseTexture && (needAlphaTest || needAlphaBlendFromDiffuse)) {
- defines.push("#define DIFFUSE");
- if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind) && diffuseTexture.coordinatesIndex === 1) {
- defines.push("#define DIFFUSEUV2");
- uv2 = true;
- }
- else if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
- defines.push("#define DIFFUSEUV1");
- uv1 = true;
- }
- if (needAlphaTest) {
- defines.push("#define ALPHATEST");
- defines.push("#define ALPHATESTVALUE 0.4");
- }
- if (!diffuseTexture.gammaSpace) {
- defines.push("#define DIFFUSE_ISLINEAR");
- }
- }
- const opacityTexture = material.opacityTexture;
- if (opacityTexture) {
- defines.push("#define OPACITY");
- if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind) && opacityTexture.coordinatesIndex === 1) {
- defines.push("#define OPACITYUV2");
- uv2 = true;
- }
- else if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
- defines.push("#define OPACITYUV1");
- uv1 = true;
- }
- }
- }
- // Emissive
- if (emissiveTexture) {
- defines.push("#define EMISSIVE");
- if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind) && emissiveTexture.coordinatesIndex === 1) {
- defines.push("#define EMISSIVEUV2");
- uv2 = true;
- }
- else if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
- defines.push("#define EMISSIVEUV1");
- uv1 = true;
- }
- if (!emissiveTexture.gammaSpace) {
- defines.push("#define EMISSIVE_ISLINEAR");
- }
- }
- // Vertex
- if (mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind) && mesh.hasVertexAlpha && material.transparencyMode !== Material.MATERIAL_OPAQUE) {
- attribs.push(VertexBuffer.ColorKind);
- defines.push("#define VERTEXALPHA");
- }
- if (uv1) {
- attribs.push(VertexBuffer.UVKind);
- defines.push("#define UV1");
- }
- if (uv2) {
- attribs.push(VertexBuffer.UV2Kind);
- defines.push("#define UV2");
- }
- // Bones
- const fallbacks = new EffectFallbacks();
- if (mesh.useBones && mesh.computeBonesUsingShaders) {
- attribs.push(VertexBuffer.MatricesIndicesKind);
- attribs.push(VertexBuffer.MatricesWeightsKind);
- if (mesh.numBoneInfluencers > 4) {
- attribs.push(VertexBuffer.MatricesIndicesExtraKind);
- attribs.push(VertexBuffer.MatricesWeightsExtraKind);
- }
- defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
- const skeleton = mesh.skeleton;
- if (skeleton && skeleton.isUsingTextureForMatrices) {
- defines.push("#define BONETEXTURE");
- }
- else {
- defines.push("#define BonesPerMesh " + (skeleton ? skeleton.bones.length + 1 : 0));
- }
- if (mesh.numBoneInfluencers > 0) {
- fallbacks.addCPUSkinningFallback(0, mesh);
- }
- }
- else {
- defines.push("#define NUM_BONE_INFLUENCERS 0");
- }
- // Morph targets
- const manager = mesh.morphTargetManager;
- let morphInfluencers = 0;
- if (manager) {
- morphInfluencers = manager.numMaxInfluencers || manager.numInfluencers;
- if (morphInfluencers > 0) {
- defines.push("#define MORPHTARGETS");
- defines.push("#define NUM_MORPH_INFLUENCERS " + morphInfluencers);
- if (manager.isUsingTextureForTargets) {
- defines.push("#define MORPHTARGETS_TEXTURE");
- }
- PrepareAttributesForMorphTargetsInfluencers(attribs, mesh, morphInfluencers);
- }
- }
- // Instances
- if (useInstances) {
- defines.push("#define INSTANCES");
- PushAttributesForInstances(attribs);
- if (subMesh.getRenderingMesh().hasThinInstances) {
- defines.push("#define THIN_INSTANCES");
- }
- }
- // ClipPlanes
- prepareStringDefinesForClipPlanes(material, this._scene, defines);
- this._addCustomEffectDefines(defines);
- // Get correct effect
- const drawWrapper = subMesh._getDrawWrapper(undefined, true);
- const cachedDefines = drawWrapper.defines;
- const join = defines.join("\n");
- if (cachedDefines !== join) {
- const uniforms = [
- "world",
- "mBones",
- "viewProjection",
- "glowColor",
- "morphTargetInfluences",
- "morphTargetCount",
- "boneTextureWidth",
- "diffuseMatrix",
- "emissiveMatrix",
- "opacityMatrix",
- "opacityIntensity",
- "morphTargetTextureInfo",
- "morphTargetTextureIndices",
- "glowIntensity",
- ];
- addClipPlaneUniforms(uniforms);
- drawWrapper.setEffect(this._engine.createEffect("glowMapGeneration", attribs, uniforms, ["diffuseSampler", "emissiveSampler", "opacitySampler", "boneSampler", "morphTargets"], join, fallbacks, undefined, undefined, { maxSimultaneousMorphTargets: morphInfluencers }), join);
- }
- return drawWrapper.effect.isReady();
- }
- /**
- * Renders the glowing part of the scene by blending the blurred glowing meshes on top of the rendered scene.
- */
- render() {
- for (let i = 0; i < this._postProcesses.length; i++) {
- if (!this._postProcesses[i].isReady()) {
- return;
- }
- }
- const engine = this._scene.getEngine();
- const numDraws = this._numInternalDraws();
- // Check
- let isReady = true;
- for (let i = 0; i < numDraws; ++i) {
- let currentEffect = this._mergeDrawWrapper[i];
- if (!currentEffect) {
- currentEffect = this._mergeDrawWrapper[i] = new DrawWrapper(this._engine);
- currentEffect.setEffect(this._createMergeEffect());
- }
- isReady = isReady && currentEffect.effect.isReady();
- }
- if (!isReady) {
- return;
- }
- this.onBeforeComposeObservable.notifyObservers(this);
- const previousAlphaMode = engine.getAlphaMode();
- for (let i = 0; i < numDraws; ++i) {
- const currentEffect = this._mergeDrawWrapper[i];
- // Render
- engine.enableEffect(currentEffect);
- engine.setState(false);
- // VBOs
- engine.bindBuffers(this._vertexBuffers, this._indexBuffer, currentEffect.effect);
- // Go Blend.
- engine.setAlphaMode(this._effectLayerOptions.alphaBlendingMode);
- // Blends the map on the main canvas.
- this._internalRender(currentEffect.effect, i);
- }
- // Restore Alpha
- engine.setAlphaMode(previousAlphaMode);
- this.onAfterComposeObservable.notifyObservers(this);
- // Handle size changes.
- const size = this._mainTexture.getSize();
- this._setMainTextureSize();
- if ((size.width !== this._mainTextureDesiredSize.width || size.height !== this._mainTextureDesiredSize.height) &&
- this._mainTextureDesiredSize.width !== 0 &&
- this._mainTextureDesiredSize.height !== 0) {
- // Recreate RTT and post processes on size change.
- this.onSizeChangedObservable.notifyObservers(this);
- this._disposeTextureAndPostProcesses();
- this._createMainTexture();
- this._createTextureAndPostProcesses();
- }
- }
- /**
- * Determine if a given mesh will be used in the current effect.
- * @param mesh mesh to test
- * @returns true if the mesh will be used
- */
- hasMesh(mesh) {
- if (this.renderingGroupId === -1 || mesh.renderingGroupId === this.renderingGroupId) {
- return true;
- }
- return false;
- }
- /**
- * Returns true if the layer contains information to display, otherwise false.
- * @returns true if the glow layer should be rendered
- */
- shouldRender() {
- return this.isEnabled && this._shouldRender;
- }
- /**
- * Returns true if the mesh should render, otherwise false.
- * @param mesh The mesh to render
- * @returns true if it should render otherwise false
- */
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- _shouldRenderMesh(mesh) {
- return true;
- }
- /**
- * Returns true if the mesh can be rendered, otherwise false.
- * @param mesh The mesh to render
- * @param material The material used on the mesh
- * @returns true if it can be rendered otherwise false
- */
- _canRenderMesh(mesh, material) {
- return !material.needAlphaBlendingForMesh(mesh);
- }
- /**
- * Returns true if the mesh should render, otherwise false.
- * @returns true if it should render otherwise false
- */
- _shouldRenderEmissiveTextureForMesh() {
- return true;
- }
- /**
- * Renders the submesh passed in parameter to the generation map.
- * @param subMesh
- * @param enableAlphaMode
- */
- _renderSubMesh(subMesh, enableAlphaMode = false) {
- if (!this.shouldRender()) {
- return;
- }
- const material = subMesh.getMaterial();
- const ownerMesh = subMesh.getMesh();
- const replacementMesh = subMesh.getReplacementMesh();
- const renderingMesh = subMesh.getRenderingMesh();
- const effectiveMesh = subMesh.getEffectiveMesh();
- const scene = this._scene;
- const engine = scene.getEngine();
- effectiveMesh._internalAbstractMeshDataInfo._isActiveIntermediate = false;
- if (!material) {
- return;
- }
- // Do not block in blend mode.
- if (!this._canRenderMesh(renderingMesh, material)) {
- return;
- }
- // Culling
- let sideOrientation = renderingMesh.overrideMaterialSideOrientation ?? material.sideOrientation;
- const mainDeterminant = effectiveMesh._getWorldMatrixDeterminant();
- if (mainDeterminant < 0) {
- sideOrientation = sideOrientation === Material.ClockWiseSideOrientation ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
- }
- const reverse = sideOrientation === Material.ClockWiseSideOrientation;
- engine.setState(material.backFaceCulling, material.zOffset, undefined, reverse, material.cullBackFaces, undefined, material.zOffsetUnits);
- // Managing instances
- const batch = renderingMesh._getInstancesRenderList(subMesh._id, !!replacementMesh);
- if (batch.mustReturn) {
- return;
- }
- // Early Exit per mesh
- if (!this._shouldRenderMesh(renderingMesh)) {
- return;
- }
- const hardwareInstancedRendering = batch.hardwareInstancedRendering[subMesh._id] || renderingMesh.hasThinInstances;
- this._setEmissiveTextureAndColor(renderingMesh, subMesh, material);
- this.onBeforeRenderMeshToEffect.notifyObservers(ownerMesh);
- if (this._useMeshMaterial(renderingMesh)) {
- renderingMesh.render(subMesh, enableAlphaMode, replacementMesh || undefined);
- }
- else if (this._isReady(subMesh, hardwareInstancedRendering, this._emissiveTextureAndColor.texture)) {
- const renderingMaterial = effectiveMesh._internalAbstractMeshDataInfo._materialForRenderPass?.[engine.currentRenderPassId];
- let drawWrapper = subMesh._getDrawWrapper();
- if (!drawWrapper && renderingMaterial) {
- drawWrapper = renderingMaterial._getDrawWrapper();
- }
- if (!drawWrapper) {
- return;
- }
- const effect = drawWrapper.effect;
- engine.enableEffect(drawWrapper);
- if (!hardwareInstancedRendering) {
- renderingMesh._bind(subMesh, effect, material.fillMode);
- }
- if (!renderingMaterial) {
- effect.setMatrix("viewProjection", scene.getTransformMatrix());
- effect.setMatrix("world", effectiveMesh.getWorldMatrix());
- effect.setFloat4("glowColor", this._emissiveTextureAndColor.color.r, this._emissiveTextureAndColor.color.g, this._emissiveTextureAndColor.color.b, this._emissiveTextureAndColor.color.a);
- }
- else {
- renderingMaterial.bindForSubMesh(effectiveMesh.getWorldMatrix(), effectiveMesh, subMesh);
- }
- if (!renderingMaterial) {
- const needAlphaTest = material.needAlphaTesting();
- const diffuseTexture = material.getAlphaTestTexture();
- const needAlphaBlendFromDiffuse = diffuseTexture && diffuseTexture.hasAlpha && (material.useAlphaFromDiffuseTexture || material._useAlphaFromAlbedoTexture);
- if (diffuseTexture && (needAlphaTest || needAlphaBlendFromDiffuse)) {
- effect.setTexture("diffuseSampler", diffuseTexture);
- const textureMatrix = diffuseTexture.getTextureMatrix();
- if (textureMatrix) {
- effect.setMatrix("diffuseMatrix", textureMatrix);
- }
- }
- const opacityTexture = material.opacityTexture;
- if (opacityTexture) {
- effect.setTexture("opacitySampler", opacityTexture);
- effect.setFloat("opacityIntensity", opacityTexture.level);
- const textureMatrix = opacityTexture.getTextureMatrix();
- if (textureMatrix) {
- effect.setMatrix("opacityMatrix", textureMatrix);
- }
- }
- // Glow emissive only
- if (this._emissiveTextureAndColor.texture) {
- effect.setTexture("emissiveSampler", this._emissiveTextureAndColor.texture);
- effect.setMatrix("emissiveMatrix", this._emissiveTextureAndColor.texture.getTextureMatrix());
- }
- // Bones
- if (renderingMesh.useBones && renderingMesh.computeBonesUsingShaders && renderingMesh.skeleton) {
- const skeleton = renderingMesh.skeleton;
- if (skeleton.isUsingTextureForMatrices) {
- const boneTexture = skeleton.getTransformMatrixTexture(renderingMesh);
- if (!boneTexture) {
- return;
- }
- effect.setTexture("boneSampler", boneTexture);
- effect.setFloat("boneTextureWidth", 4.0 * (skeleton.bones.length + 1));
- }
- else {
- effect.setMatrices("mBones", skeleton.getTransformMatrices(renderingMesh));
- }
- }
- // Morph targets
- BindMorphTargetParameters(renderingMesh, effect);
- if (renderingMesh.morphTargetManager && renderingMesh.morphTargetManager.isUsingTextureForTargets) {
- renderingMesh.morphTargetManager._bind(effect);
- }
- // Alpha mode
- if (enableAlphaMode) {
- engine.setAlphaMode(material.alphaMode);
- }
- // Intensity of effect
- effect.setFloat("glowIntensity", this.getEffectIntensity(renderingMesh));
- // Clip planes
- bindClipPlane(effect, material, scene);
- }
- // Draw
- renderingMesh._processRendering(effectiveMesh, subMesh, effect, material.fillMode, batch, hardwareInstancedRendering, (isInstance, world) => effect.setMatrix("world", world));
- }
- else {
- // Need to reset refresh rate of the main map
- this._mainTexture.resetRefreshCounter();
- }
- this.onAfterRenderMeshToEffect.notifyObservers(ownerMesh);
- }
- /**
- * Defines whether the current material of the mesh should be use to render the effect.
- * @param mesh defines the current mesh to render
- * @returns true if the mesh material should be use
- */
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- _useMeshMaterial(mesh) {
- return false;
- }
- /**
- * Rebuild the required buffers.
- * @internal Internal use only.
- */
- _rebuild() {
- const vb = this._vertexBuffers[VertexBuffer.PositionKind];
- if (vb) {
- vb._rebuild();
- }
- this._generateIndexBuffer();
- }
- /**
- * Dispose only the render target textures and post process.
- */
- _disposeTextureAndPostProcesses() {
- this._mainTexture.dispose();
- for (let i = 0; i < this._postProcesses.length; i++) {
- if (this._postProcesses[i]) {
- this._postProcesses[i].dispose();
- }
- }
- this._postProcesses = [];
- for (let i = 0; i < this._textures.length; i++) {
- if (this._textures[i]) {
- this._textures[i].dispose();
- }
- }
- this._textures = [];
- }
- /**
- * Dispose the highlight layer and free resources.
- */
- dispose() {
- const vertexBuffer = this._vertexBuffers[VertexBuffer.PositionKind];
- if (vertexBuffer) {
- vertexBuffer.dispose();
- this._vertexBuffers[VertexBuffer.PositionKind] = null;
- }
- if (this._indexBuffer) {
- this._scene.getEngine()._releaseBuffer(this._indexBuffer);
- this._indexBuffer = null;
- }
- for (const drawWrapper of this._mergeDrawWrapper) {
- drawWrapper.dispose();
- }
- this._mergeDrawWrapper = [];
- // Clean textures and post processes
- this._disposeTextureAndPostProcesses();
- // Remove from scene
- const index = this._scene.effectLayers.indexOf(this, 0);
- if (index > -1) {
- this._scene.effectLayers.splice(index, 1);
- }
- // Callback
- this.onDisposeObservable.notifyObservers(this);
- this.onDisposeObservable.clear();
- this.onBeforeRenderMainTextureObservable.clear();
- this.onBeforeComposeObservable.clear();
- this.onBeforeRenderMeshToEffect.clear();
- this.onAfterRenderMeshToEffect.clear();
- this.onAfterComposeObservable.clear();
- this.onSizeChangedObservable.clear();
- }
- /**
- * Gets the class name of the effect layer
- * @returns the string with the class name of the effect layer
- */
- getClassName() {
- return "EffectLayer";
- }
- /**
- * Creates an effect layer from parsed effect layer data
- * @param parsedEffectLayer defines effect layer data
- * @param scene defines the current scene
- * @param rootUrl defines the root URL containing the effect layer information
- * @returns a parsed effect Layer
- */
- static Parse(parsedEffectLayer, scene, rootUrl) {
- const effectLayerType = Tools.Instantiate(parsedEffectLayer.customType);
- return effectLayerType.Parse(parsedEffectLayer, scene, rootUrl);
- }
- }
- /**
- * @internal
- */
- EffectLayer._SceneComponentInitialization = (_) => {
- throw _WarnImport("EffectLayerSceneComponent");
- };
- __decorate([
- serialize()
- ], EffectLayer.prototype, "name", void 0);
- __decorate([
- serializeAsColor4()
- ], EffectLayer.prototype, "neutralColor", void 0);
- __decorate([
- serialize()
- ], EffectLayer.prototype, "isEnabled", void 0);
- __decorate([
- serializeAsCameraReference()
- ], EffectLayer.prototype, "camera", null);
- __decorate([
- serialize()
- ], EffectLayer.prototype, "renderingGroupId", null);
- __decorate([
- serialize()
- ], EffectLayer.prototype, "disableBoundingBoxesFromEffectLayer", void 0);
- //# sourceMappingURL=effectLayer.js.map
|