highlightLayer.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. import { __decorate } from "../tslib.es6.js";
  2. /* eslint-disable @typescript-eslint/no-unused-vars */
  3. import { serialize } from "../Misc/decorators.js";
  4. import { Observable } from "../Misc/observable.js";
  5. import { Vector2 } from "../Maths/math.vector.js";
  6. import { VertexBuffer } from "../Buffers/buffer.js";
  7. import { Material } from "../Materials/material.js";
  8. import { Texture } from "../Materials/Textures/texture.js";
  9. import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture.js";
  10. import { PostProcess } from "../PostProcesses/postProcess.js";
  11. import { PassPostProcess } from "../PostProcesses/passPostProcess.js";
  12. import { BlurPostProcess } from "../PostProcesses/blurPostProcess.js";
  13. import { EffectLayer } from "./effectLayer.js";
  14. import { AbstractScene } from "../abstractScene.js";
  15. import { Logger } from "../Misc/logger.js";
  16. import { RegisterClass } from "../Misc/typeStore.js";
  17. import { Color4, Color3 } from "../Maths/math.color.js";
  18. import "../Shaders/glowMapMerge.fragment.js";
  19. import "../Shaders/glowMapMerge.vertex.js";
  20. import "../Shaders/glowBlurPostProcess.fragment.js";
  21. import "../Layers/effectLayerSceneComponent.js";
  22. import { SerializationHelper } from "../Misc/decorators.serialization.js";
  23. import { GetExponentOfTwo } from "../Misc/tools.functions.js";
  24. AbstractScene.prototype.getHighlightLayerByName = function (name) {
  25. for (let index = 0; index < this.effectLayers?.length; index++) {
  26. if (this.effectLayers[index].name === name && this.effectLayers[index].getEffectName() === HighlightLayer.EffectName) {
  27. return this.effectLayers[index];
  28. }
  29. }
  30. return null;
  31. };
  32. /**
  33. * Special Glow Blur post process only blurring the alpha channel
  34. * It enforces keeping the most luminous color in the color channel.
  35. */
  36. class GlowBlurPostProcess extends PostProcess {
  37. constructor(name, direction, kernel, options, camera, samplingMode = Texture.BILINEAR_SAMPLINGMODE, engine, reusable) {
  38. super(name, "glowBlurPostProcess", ["screenSize", "direction", "blurWidth"], null, options, camera, samplingMode, engine, reusable);
  39. this.direction = direction;
  40. this.kernel = kernel;
  41. this.onApplyObservable.add((effect) => {
  42. effect.setFloat2("screenSize", this.width, this.height);
  43. effect.setVector2("direction", this.direction);
  44. effect.setFloat("blurWidth", this.kernel);
  45. });
  46. }
  47. }
  48. /**
  49. * The highlight layer Helps adding a glow effect around a mesh.
  50. *
  51. * Once instantiated in a scene, simply use the addMesh or removeMesh method to add or remove
  52. * glowy meshes to your scene.
  53. *
  54. * !!! THIS REQUIRES AN ACTIVE STENCIL BUFFER ON THE CANVAS !!!
  55. */
  56. export class HighlightLayer extends EffectLayer {
  57. /**
  58. * Specifies the horizontal size of the blur.
  59. */
  60. set blurHorizontalSize(value) {
  61. this._horizontalBlurPostprocess.kernel = value;
  62. this._options.blurHorizontalSize = value;
  63. }
  64. /**
  65. * Specifies the vertical size of the blur.
  66. */
  67. set blurVerticalSize(value) {
  68. this._verticalBlurPostprocess.kernel = value;
  69. this._options.blurVerticalSize = value;
  70. }
  71. /**
  72. * Gets the horizontal size of the blur.
  73. */
  74. get blurHorizontalSize() {
  75. return this._horizontalBlurPostprocess.kernel;
  76. }
  77. /**
  78. * Gets the vertical size of the blur.
  79. */
  80. get blurVerticalSize() {
  81. return this._verticalBlurPostprocess.kernel;
  82. }
  83. /**
  84. * Instantiates a new highlight Layer and references it to the scene..
  85. * @param name The name of the layer
  86. * @param scene The scene to use the layer in
  87. * @param options Sets of none mandatory options to use with the layer (see IHighlightLayerOptions for more information)
  88. */
  89. constructor(name, scene, options) {
  90. super(name, scene);
  91. this.name = name;
  92. /**
  93. * Specifies whether or not the inner glow is ACTIVE in the layer.
  94. */
  95. this.innerGlow = true;
  96. /**
  97. * Specifies whether or not the outer glow is ACTIVE in the layer.
  98. */
  99. this.outerGlow = true;
  100. /**
  101. * An event triggered when the highlight layer is being blurred.
  102. */
  103. this.onBeforeBlurObservable = new Observable();
  104. /**
  105. * An event triggered when the highlight layer has been blurred.
  106. */
  107. this.onAfterBlurObservable = new Observable();
  108. this._instanceGlowingMeshStencilReference = HighlightLayer.GlowingMeshStencilReference++;
  109. this._meshes = {};
  110. this._excludedMeshes = {};
  111. this.neutralColor = HighlightLayer.NeutralColor;
  112. // Warn on stencil
  113. if (!this._engine.isStencilEnable) {
  114. Logger.Warn("Rendering the Highlight Layer requires the stencil to be active on the canvas. var engine = new Engine(canvas, antialias, { stencil: true }");
  115. }
  116. // Adapt options
  117. this._options = {
  118. mainTextureRatio: 0.5,
  119. blurTextureSizeRatio: 0.5,
  120. blurHorizontalSize: 1.0,
  121. blurVerticalSize: 1.0,
  122. alphaBlendingMode: 2,
  123. camera: null,
  124. renderingGroupId: -1,
  125. mainTextureType: 0,
  126. ...options,
  127. };
  128. // Initialize the layer
  129. this._init({
  130. alphaBlendingMode: this._options.alphaBlendingMode,
  131. camera: this._options.camera,
  132. mainTextureFixedSize: this._options.mainTextureFixedSize,
  133. mainTextureRatio: this._options.mainTextureRatio,
  134. renderingGroupId: this._options.renderingGroupId,
  135. mainTextureType: this._options.mainTextureType,
  136. });
  137. // Do not render as long as no meshes have been added
  138. this._shouldRender = false;
  139. }
  140. /**
  141. * Get the effect name of the layer.
  142. * @returns The effect name
  143. */
  144. getEffectName() {
  145. return HighlightLayer.EffectName;
  146. }
  147. _numInternalDraws() {
  148. return 2; // we need two rendering, one for the inner glow and the other for the outer glow
  149. }
  150. /**
  151. * Create the merge effect. This is the shader use to blit the information back
  152. * to the main canvas at the end of the scene rendering.
  153. * @returns The effect created
  154. */
  155. _createMergeEffect() {
  156. // Effect
  157. return this._engine.createEffect("glowMapMerge", [VertexBuffer.PositionKind], ["offset"], ["textureSampler"], this._options.isStroke ? "#define STROKE \n" : undefined);
  158. }
  159. /**
  160. * Creates the render target textures and post processes used in the highlight layer.
  161. */
  162. _createTextureAndPostProcesses() {
  163. let blurTextureWidth = this._mainTextureDesiredSize.width * this._options.blurTextureSizeRatio;
  164. let blurTextureHeight = this._mainTextureDesiredSize.height * this._options.blurTextureSizeRatio;
  165. blurTextureWidth = this._engine.needPOTTextures ? GetExponentOfTwo(blurTextureWidth, this._maxSize) : blurTextureWidth;
  166. blurTextureHeight = this._engine.needPOTTextures ? GetExponentOfTwo(blurTextureHeight, this._maxSize) : blurTextureHeight;
  167. let textureType = 0;
  168. if (this._engine.getCaps().textureHalfFloatRender) {
  169. textureType = 2;
  170. }
  171. else {
  172. textureType = 0;
  173. }
  174. this._blurTexture = new RenderTargetTexture("HighlightLayerBlurRTT", {
  175. width: blurTextureWidth,
  176. height: blurTextureHeight,
  177. }, this._scene, false, true, textureType);
  178. this._blurTexture.wrapU = Texture.CLAMP_ADDRESSMODE;
  179. this._blurTexture.wrapV = Texture.CLAMP_ADDRESSMODE;
  180. this._blurTexture.anisotropicFilteringLevel = 16;
  181. this._blurTexture.updateSamplingMode(Texture.TRILINEAR_SAMPLINGMODE);
  182. this._blurTexture.renderParticles = false;
  183. this._blurTexture.ignoreCameraViewport = true;
  184. this._textures = [this._blurTexture];
  185. if (this._options.alphaBlendingMode === 2) {
  186. this._downSamplePostprocess = new PassPostProcess("HighlightLayerPPP", this._options.blurTextureSizeRatio, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
  187. this._downSamplePostprocess.externalTextureSamplerBinding = true;
  188. this._downSamplePostprocess.onApplyObservable.add((effect) => {
  189. effect.setTexture("textureSampler", this._mainTexture);
  190. });
  191. this._horizontalBlurPostprocess = new GlowBlurPostProcess("HighlightLayerHBP", new Vector2(1.0, 0), this._options.blurHorizontalSize, 1, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
  192. this._horizontalBlurPostprocess.onApplyObservable.add((effect) => {
  193. effect.setFloat2("screenSize", blurTextureWidth, blurTextureHeight);
  194. });
  195. this._verticalBlurPostprocess = new GlowBlurPostProcess("HighlightLayerVBP", new Vector2(0, 1.0), this._options.blurVerticalSize, 1, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
  196. this._verticalBlurPostprocess.onApplyObservable.add((effect) => {
  197. effect.setFloat2("screenSize", blurTextureWidth, blurTextureHeight);
  198. });
  199. this._postProcesses = [this._downSamplePostprocess, this._horizontalBlurPostprocess, this._verticalBlurPostprocess];
  200. }
  201. else {
  202. this._horizontalBlurPostprocess = new BlurPostProcess("HighlightLayerHBP", new Vector2(1.0, 0), this._options.blurHorizontalSize / 2, {
  203. width: blurTextureWidth,
  204. height: blurTextureHeight,
  205. }, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
  206. this._horizontalBlurPostprocess.width = blurTextureWidth;
  207. this._horizontalBlurPostprocess.height = blurTextureHeight;
  208. this._horizontalBlurPostprocess.externalTextureSamplerBinding = true;
  209. this._horizontalBlurPostprocess.onApplyObservable.add((effect) => {
  210. effect.setTexture("textureSampler", this._mainTexture);
  211. });
  212. this._verticalBlurPostprocess = new BlurPostProcess("HighlightLayerVBP", new Vector2(0, 1.0), this._options.blurVerticalSize / 2, {
  213. width: blurTextureWidth,
  214. height: blurTextureHeight,
  215. }, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
  216. this._postProcesses = [this._horizontalBlurPostprocess, this._verticalBlurPostprocess];
  217. }
  218. this._mainTexture.onAfterUnbindObservable.add(() => {
  219. this.onBeforeBlurObservable.notifyObservers(this);
  220. const internalTexture = this._blurTexture.renderTarget;
  221. if (internalTexture) {
  222. this._scene.postProcessManager.directRender(this._postProcesses, internalTexture, true);
  223. this._engine.unBindFramebuffer(internalTexture, true);
  224. }
  225. this.onAfterBlurObservable.notifyObservers(this);
  226. });
  227. // Prevent autoClear.
  228. this._postProcesses.map((pp) => {
  229. pp.autoClear = false;
  230. });
  231. }
  232. /**
  233. * @returns whether or not the layer needs stencil enabled during the mesh rendering.
  234. */
  235. needStencil() {
  236. return true;
  237. }
  238. /**
  239. * Checks for the readiness of the element composing the layer.
  240. * @param subMesh the mesh to check for
  241. * @param useInstances specify whether or not to use instances to render the mesh
  242. * @returns true if ready otherwise, false
  243. */
  244. isReady(subMesh, useInstances) {
  245. const material = subMesh.getMaterial();
  246. const mesh = subMesh.getRenderingMesh();
  247. if (!material || !mesh || !this._meshes) {
  248. return false;
  249. }
  250. let emissiveTexture = null;
  251. const highlightLayerMesh = this._meshes[mesh.uniqueId];
  252. if (highlightLayerMesh && highlightLayerMesh.glowEmissiveOnly && material) {
  253. emissiveTexture = material.emissiveTexture;
  254. }
  255. return super._isReady(subMesh, useInstances, emissiveTexture);
  256. }
  257. /**
  258. * Implementation specific of rendering the generating effect on the main canvas.
  259. * @param effect The effect used to render through
  260. * @param renderIndex
  261. */
  262. _internalRender(effect, renderIndex) {
  263. // Texture
  264. effect.setTexture("textureSampler", this._blurTexture);
  265. // Cache
  266. const engine = this._engine;
  267. engine.cacheStencilState();
  268. // Stencil operations
  269. engine.setStencilOperationPass(7681);
  270. engine.setStencilOperationFail(7680);
  271. engine.setStencilOperationDepthFail(7680);
  272. // Draw order
  273. engine.setStencilMask(0x00);
  274. engine.setStencilBuffer(true);
  275. engine.setStencilFunctionReference(this._instanceGlowingMeshStencilReference);
  276. // 2 passes inner outer
  277. if (this.outerGlow && renderIndex === 0) {
  278. // the outer glow is rendered the first time _internalRender is called, so when renderIndex == 0 (and only if outerGlow is enabled)
  279. effect.setFloat("offset", 0);
  280. engine.setStencilFunction(517);
  281. engine.drawElementsType(Material.TriangleFillMode, 0, 6);
  282. }
  283. if (this.innerGlow && renderIndex === 1) {
  284. // the inner glow is rendered the second time _internalRender is called, so when renderIndex == 1 (and only if innerGlow is enabled)
  285. effect.setFloat("offset", 1);
  286. engine.setStencilFunction(514);
  287. engine.drawElementsType(Material.TriangleFillMode, 0, 6);
  288. }
  289. // Restore Cache
  290. engine.restoreStencilState();
  291. }
  292. /**
  293. * @returns true if the layer contains information to display, otherwise false.
  294. */
  295. shouldRender() {
  296. if (super.shouldRender()) {
  297. return this._meshes ? true : false;
  298. }
  299. return false;
  300. }
  301. /**
  302. * Returns true if the mesh should render, otherwise false.
  303. * @param mesh The mesh to render
  304. * @returns true if it should render otherwise false
  305. */
  306. _shouldRenderMesh(mesh) {
  307. // Excluded Mesh
  308. if (this._excludedMeshes && this._excludedMeshes[mesh.uniqueId]) {
  309. return false;
  310. }
  311. if (!super.hasMesh(mesh)) {
  312. return false;
  313. }
  314. return true;
  315. }
  316. /**
  317. * Returns true if the mesh can be rendered, otherwise false.
  318. * @param mesh The mesh to render
  319. * @param material The material used on the mesh
  320. * @returns true if it can be rendered otherwise false
  321. */
  322. _canRenderMesh(mesh, material) {
  323. // all meshes can be rendered in the highlight layer, even transparent ones
  324. return true;
  325. }
  326. /**
  327. * Adds specific effects defines.
  328. * @param defines The defines to add specifics to.
  329. */
  330. _addCustomEffectDefines(defines) {
  331. defines.push("#define HIGHLIGHT");
  332. }
  333. /**
  334. * Sets the required values for both the emissive texture and and the main color.
  335. * @param mesh
  336. * @param subMesh
  337. * @param material
  338. */
  339. _setEmissiveTextureAndColor(mesh, subMesh, material) {
  340. const highlightLayerMesh = this._meshes[mesh.uniqueId];
  341. if (highlightLayerMesh) {
  342. this._emissiveTextureAndColor.color.set(highlightLayerMesh.color.r, highlightLayerMesh.color.g, highlightLayerMesh.color.b, 1.0);
  343. }
  344. else {
  345. this._emissiveTextureAndColor.color.set(this.neutralColor.r, this.neutralColor.g, this.neutralColor.b, this.neutralColor.a);
  346. }
  347. if (highlightLayerMesh && highlightLayerMesh.glowEmissiveOnly && material) {
  348. this._emissiveTextureAndColor.texture = material.emissiveTexture;
  349. this._emissiveTextureAndColor.color.set(1.0, 1.0, 1.0, 1.0);
  350. }
  351. else {
  352. this._emissiveTextureAndColor.texture = null;
  353. }
  354. }
  355. /**
  356. * Add a mesh in the exclusion list to prevent it to impact or being impacted by the highlight layer.
  357. * @param mesh The mesh to exclude from the highlight layer
  358. */
  359. addExcludedMesh(mesh) {
  360. if (!this._excludedMeshes) {
  361. return;
  362. }
  363. const meshExcluded = this._excludedMeshes[mesh.uniqueId];
  364. if (!meshExcluded) {
  365. const obj = {
  366. mesh: mesh,
  367. beforeBind: null,
  368. afterRender: null,
  369. stencilState: false,
  370. };
  371. obj.beforeBind = mesh.onBeforeBindObservable.add((mesh) => {
  372. obj.stencilState = mesh.getEngine().getStencilBuffer();
  373. mesh.getEngine().setStencilBuffer(false);
  374. });
  375. obj.afterRender = mesh.onAfterRenderObservable.add((mesh) => {
  376. mesh.getEngine().setStencilBuffer(obj.stencilState);
  377. });
  378. this._excludedMeshes[mesh.uniqueId] = obj;
  379. }
  380. }
  381. /**
  382. * Remove a mesh from the exclusion list to let it impact or being impacted by the highlight layer.
  383. * @param mesh The mesh to highlight
  384. */
  385. removeExcludedMesh(mesh) {
  386. if (!this._excludedMeshes) {
  387. return;
  388. }
  389. const meshExcluded = this._excludedMeshes[mesh.uniqueId];
  390. if (meshExcluded) {
  391. if (meshExcluded.beforeBind) {
  392. mesh.onBeforeBindObservable.remove(meshExcluded.beforeBind);
  393. }
  394. if (meshExcluded.afterRender) {
  395. mesh.onAfterRenderObservable.remove(meshExcluded.afterRender);
  396. }
  397. }
  398. this._excludedMeshes[mesh.uniqueId] = null;
  399. }
  400. /**
  401. * Determine if a given mesh will be highlighted by the current HighlightLayer
  402. * @param mesh mesh to test
  403. * @returns true if the mesh will be highlighted by the current HighlightLayer
  404. */
  405. hasMesh(mesh) {
  406. if (!this._meshes) {
  407. return false;
  408. }
  409. if (!super.hasMesh(mesh)) {
  410. return false;
  411. }
  412. return this._meshes[mesh.uniqueId] !== undefined && this._meshes[mesh.uniqueId] !== null;
  413. }
  414. /**
  415. * Add a mesh in the highlight layer in order to make it glow with the chosen color.
  416. * @param mesh The mesh to highlight
  417. * @param color The color of the highlight
  418. * @param glowEmissiveOnly Extract the glow from the emissive texture
  419. */
  420. addMesh(mesh, color, glowEmissiveOnly = false) {
  421. if (!this._meshes) {
  422. return;
  423. }
  424. const meshHighlight = this._meshes[mesh.uniqueId];
  425. if (meshHighlight) {
  426. meshHighlight.color = color;
  427. }
  428. else {
  429. this._meshes[mesh.uniqueId] = {
  430. mesh: mesh,
  431. color: color,
  432. // Lambda required for capture due to Observable this context
  433. observerHighlight: mesh.onBeforeBindObservable.add((mesh) => {
  434. if (this.isEnabled) {
  435. if (this._excludedMeshes && this._excludedMeshes[mesh.uniqueId]) {
  436. this._defaultStencilReference(mesh);
  437. }
  438. else {
  439. mesh.getScene().getEngine().setStencilFunctionReference(this._instanceGlowingMeshStencilReference);
  440. }
  441. }
  442. }),
  443. observerDefault: mesh.onAfterRenderObservable.add((mesh) => {
  444. if (this.isEnabled) {
  445. this._defaultStencilReference(mesh);
  446. }
  447. }),
  448. glowEmissiveOnly: glowEmissiveOnly,
  449. };
  450. mesh.onDisposeObservable.add(() => {
  451. this._disposeMesh(mesh);
  452. });
  453. }
  454. this._shouldRender = true;
  455. }
  456. /**
  457. * Remove a mesh from the highlight layer in order to make it stop glowing.
  458. * @param mesh The mesh to highlight
  459. */
  460. removeMesh(mesh) {
  461. if (!this._meshes) {
  462. return;
  463. }
  464. const meshHighlight = this._meshes[mesh.uniqueId];
  465. if (meshHighlight) {
  466. if (meshHighlight.observerHighlight) {
  467. mesh.onBeforeBindObservable.remove(meshHighlight.observerHighlight);
  468. }
  469. if (meshHighlight.observerDefault) {
  470. mesh.onAfterRenderObservable.remove(meshHighlight.observerDefault);
  471. }
  472. delete this._meshes[mesh.uniqueId];
  473. }
  474. this._shouldRender = false;
  475. for (const meshHighlightToCheck in this._meshes) {
  476. if (this._meshes[meshHighlightToCheck]) {
  477. this._shouldRender = true;
  478. break;
  479. }
  480. }
  481. }
  482. /**
  483. * Remove all the meshes currently referenced in the highlight layer
  484. */
  485. removeAllMeshes() {
  486. if (!this._meshes) {
  487. return;
  488. }
  489. for (const uniqueId in this._meshes) {
  490. if (Object.prototype.hasOwnProperty.call(this._meshes, uniqueId)) {
  491. const mesh = this._meshes[uniqueId];
  492. if (mesh) {
  493. this.removeMesh(mesh.mesh);
  494. }
  495. }
  496. }
  497. }
  498. /**
  499. * Force the stencil to the normal expected value for none glowing parts
  500. * @param mesh
  501. */
  502. _defaultStencilReference(mesh) {
  503. mesh.getScene().getEngine().setStencilFunctionReference(HighlightLayer.NormalMeshStencilReference);
  504. }
  505. /**
  506. * Free any resources and references associated to a mesh.
  507. * Internal use
  508. * @param mesh The mesh to free.
  509. * @internal
  510. */
  511. _disposeMesh(mesh) {
  512. this.removeMesh(mesh);
  513. this.removeExcludedMesh(mesh);
  514. }
  515. /**
  516. * Dispose the highlight layer and free resources.
  517. */
  518. dispose() {
  519. if (this._meshes) {
  520. // Clean mesh references
  521. for (const id in this._meshes) {
  522. const meshHighlight = this._meshes[id];
  523. if (meshHighlight && meshHighlight.mesh) {
  524. if (meshHighlight.observerHighlight) {
  525. meshHighlight.mesh.onBeforeBindObservable.remove(meshHighlight.observerHighlight);
  526. }
  527. if (meshHighlight.observerDefault) {
  528. meshHighlight.mesh.onAfterRenderObservable.remove(meshHighlight.observerDefault);
  529. }
  530. }
  531. }
  532. this._meshes = null;
  533. }
  534. if (this._excludedMeshes) {
  535. for (const id in this._excludedMeshes) {
  536. const meshHighlight = this._excludedMeshes[id];
  537. if (meshHighlight) {
  538. if (meshHighlight.beforeBind) {
  539. meshHighlight.mesh.onBeforeBindObservable.remove(meshHighlight.beforeBind);
  540. }
  541. if (meshHighlight.afterRender) {
  542. meshHighlight.mesh.onAfterRenderObservable.remove(meshHighlight.afterRender);
  543. }
  544. }
  545. }
  546. this._excludedMeshes = null;
  547. }
  548. super.dispose();
  549. }
  550. /**
  551. * Gets the class name of the effect layer
  552. * @returns the string with the class name of the effect layer
  553. */
  554. getClassName() {
  555. return "HighlightLayer";
  556. }
  557. /**
  558. * Serializes this Highlight layer
  559. * @returns a serialized Highlight layer object
  560. */
  561. serialize() {
  562. const serializationObject = SerializationHelper.Serialize(this);
  563. serializationObject.customType = "BABYLON.HighlightLayer";
  564. // Highlighted meshes
  565. serializationObject.meshes = [];
  566. if (this._meshes) {
  567. for (const m in this._meshes) {
  568. const mesh = this._meshes[m];
  569. if (mesh) {
  570. serializationObject.meshes.push({
  571. glowEmissiveOnly: mesh.glowEmissiveOnly,
  572. color: mesh.color.asArray(),
  573. meshId: mesh.mesh.id,
  574. });
  575. }
  576. }
  577. }
  578. // Excluded meshes
  579. serializationObject.excludedMeshes = [];
  580. if (this._excludedMeshes) {
  581. for (const e in this._excludedMeshes) {
  582. const excludedMesh = this._excludedMeshes[e];
  583. if (excludedMesh) {
  584. serializationObject.excludedMeshes.push(excludedMesh.mesh.id);
  585. }
  586. }
  587. }
  588. return serializationObject;
  589. }
  590. /**
  591. * Creates a Highlight layer from parsed Highlight layer data
  592. * @param parsedHightlightLayer defines the Highlight layer data
  593. * @param scene defines the current scene
  594. * @param rootUrl defines the root URL containing the Highlight layer information
  595. * @returns a parsed Highlight layer
  596. */
  597. static Parse(parsedHightlightLayer, scene, rootUrl) {
  598. const hl = SerializationHelper.Parse(() => new HighlightLayer(parsedHightlightLayer.name, scene, parsedHightlightLayer.options), parsedHightlightLayer, scene, rootUrl);
  599. let index;
  600. // Excluded meshes
  601. for (index = 0; index < parsedHightlightLayer.excludedMeshes.length; index++) {
  602. const mesh = scene.getMeshById(parsedHightlightLayer.excludedMeshes[index]);
  603. if (mesh) {
  604. hl.addExcludedMesh(mesh);
  605. }
  606. }
  607. // Included meshes
  608. for (index = 0; index < parsedHightlightLayer.meshes.length; index++) {
  609. const highlightedMesh = parsedHightlightLayer.meshes[index];
  610. const mesh = scene.getMeshById(highlightedMesh.meshId);
  611. if (mesh) {
  612. hl.addMesh(mesh, Color3.FromArray(highlightedMesh.color), highlightedMesh.glowEmissiveOnly);
  613. }
  614. }
  615. return hl;
  616. }
  617. }
  618. /**
  619. * Effect Name of the highlight layer.
  620. */
  621. HighlightLayer.EffectName = "HighlightLayer";
  622. /**
  623. * The neutral color used during the preparation of the glow effect.
  624. * This is black by default as the blend operation is a blend operation.
  625. */
  626. HighlightLayer.NeutralColor = new Color4(0, 0, 0, 0);
  627. /**
  628. * Stencil value used for glowing meshes.
  629. */
  630. HighlightLayer.GlowingMeshStencilReference = 0x02;
  631. /**
  632. * Stencil value used for the other meshes in the scene.
  633. */
  634. HighlightLayer.NormalMeshStencilReference = 0x01;
  635. __decorate([
  636. serialize()
  637. ], HighlightLayer.prototype, "innerGlow", void 0);
  638. __decorate([
  639. serialize()
  640. ], HighlightLayer.prototype, "outerGlow", void 0);
  641. __decorate([
  642. serialize()
  643. ], HighlightLayer.prototype, "blurHorizontalSize", null);
  644. __decorate([
  645. serialize()
  646. ], HighlightLayer.prototype, "blurVerticalSize", null);
  647. __decorate([
  648. serialize("options")
  649. ], HighlightLayer.prototype, "_options", void 0);
  650. RegisterClass("BABYLON.HighlightLayer", HighlightLayer);
  651. //# sourceMappingURL=highlightLayer.js.map