glowLayer.ts 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. import { serialize, SerializationHelper } from "../Misc/decorators";
  2. import { Nullable } from "../types";
  3. import { Camera } from "../Cameras/camera";
  4. import { Scene } from "../scene";
  5. import { Vector2 } from "../Maths/math.vector";
  6. import { VertexBuffer } from "../Meshes/buffer";
  7. import { SubMesh } from "../Meshes/subMesh";
  8. import { AbstractMesh } from "../Meshes/abstractMesh";
  9. import { Mesh } from "../Meshes/mesh";
  10. import { Texture } from "../Materials/Textures/texture";
  11. import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
  12. import { Effect } from "../Materials/effect";
  13. import { Material } from "../Materials/material";
  14. import { PostProcess } from "../PostProcesses/postProcess";
  15. import { BlurPostProcess } from "../PostProcesses/blurPostProcess";
  16. import { EffectLayer } from "./effectLayer";
  17. import { AbstractScene } from "../abstractScene";
  18. import { Constants } from "../Engines/constants";
  19. import { _TypeStore } from '../Misc/typeStore';
  20. import { Engine } from '../Engines/engine';
  21. import { Color4 } from '../Maths/math.color';
  22. import "../Shaders/glowMapMerge.fragment";
  23. import "../Shaders/glowMapMerge.vertex";
  24. import "../Layers/effectLayerSceneComponent";
  25. declare module "../abstractScene" {
  26. export interface AbstractScene {
  27. /**
  28. * Return a the first highlight layer of the scene with a given name.
  29. * @param name The name of the highlight layer to look for.
  30. * @return The highlight layer if found otherwise null.
  31. */
  32. getGlowLayerByName(name: string): Nullable<GlowLayer>;
  33. }
  34. }
  35. AbstractScene.prototype.getGlowLayerByName = function(name: string): Nullable<GlowLayer> {
  36. for (var index = 0; index < this.effectLayers.length; index++) {
  37. if (this.effectLayers[index].name === name && this.effectLayers[index].getEffectName() === GlowLayer.EffectName) {
  38. return (<any>this.effectLayers[index]) as GlowLayer;
  39. }
  40. }
  41. return null;
  42. };
  43. /**
  44. * Glow layer options. This helps customizing the behaviour
  45. * of the glow layer.
  46. */
  47. export interface IGlowLayerOptions {
  48. /**
  49. * Multiplication factor apply to the canvas size to compute the render target size
  50. * used to generated the glowing objects (the smaller the faster).
  51. */
  52. mainTextureRatio: number;
  53. /**
  54. * Enforces a fixed size texture to ensure resize independant blur.
  55. */
  56. mainTextureFixedSize?: number;
  57. /**
  58. * How big is the kernel of the blur texture.
  59. */
  60. blurKernelSize: number;
  61. /**
  62. * The camera attached to the layer.
  63. */
  64. camera: Nullable<Camera>;
  65. /**
  66. * Enable MSAA by chosing the number of samples.
  67. */
  68. mainTextureSamples?: number;
  69. /**
  70. * The rendering group to draw the layer in.
  71. */
  72. renderingGroupId: number;
  73. }
  74. /**
  75. * The glow layer Helps adding a glow effect around the emissive parts of a mesh.
  76. *
  77. * Once instantiated in a scene, by default, all the emissive meshes will glow.
  78. *
  79. * Documentation: https://doc.babylonjs.com/how_to/glow_layer
  80. */
  81. export class GlowLayer extends EffectLayer {
  82. /**
  83. * Effect Name of the layer.
  84. */
  85. public static readonly EffectName = "GlowLayer";
  86. /**
  87. * The default blur kernel size used for the glow.
  88. */
  89. public static DefaultBlurKernelSize = 32;
  90. /**
  91. * The default texture size ratio used for the glow.
  92. */
  93. public static DefaultTextureRatio = 0.5;
  94. /**
  95. * Sets the kernel size of the blur.
  96. */
  97. public set blurKernelSize(value: number) {
  98. this._horizontalBlurPostprocess1.kernel = value;
  99. this._verticalBlurPostprocess1.kernel = value;
  100. this._horizontalBlurPostprocess2.kernel = value;
  101. this._verticalBlurPostprocess2.kernel = value;
  102. }
  103. /**
  104. * Gets the kernel size of the blur.
  105. */
  106. @serialize()
  107. public get blurKernelSize(): number {
  108. return this._horizontalBlurPostprocess1.kernel;
  109. }
  110. /**
  111. * Sets the glow intensity.
  112. */
  113. public set intensity(value: number) {
  114. this._intensity = value;
  115. }
  116. /**
  117. * Gets the glow intensity.
  118. */
  119. @serialize()
  120. public get intensity(): number {
  121. return this._intensity;
  122. }
  123. @serialize("options")
  124. private _options: IGlowLayerOptions;
  125. private _intensity: number = 1.0;
  126. private _horizontalBlurPostprocess1: BlurPostProcess;
  127. private _verticalBlurPostprocess1: BlurPostProcess;
  128. private _horizontalBlurPostprocess2: BlurPostProcess;
  129. private _verticalBlurPostprocess2: BlurPostProcess;
  130. private _blurTexture1: RenderTargetTexture;
  131. private _blurTexture2: RenderTargetTexture;
  132. private _postProcesses1: PostProcess[];
  133. private _postProcesses2: PostProcess[];
  134. private _includedOnlyMeshes: number[] = [];
  135. private _excludedMeshes: number[] = [];
  136. private _meshesUsingTheirOwnMaterials: number[] = [];
  137. /**
  138. * Callback used to let the user override the color selection on a per mesh basis
  139. */
  140. public customEmissiveColorSelector: (mesh: Mesh, subMesh: SubMesh, material: Material, result: Color4) => void;
  141. /**
  142. * Callback used to let the user override the texture selection on a per mesh basis
  143. */
  144. public customEmissiveTextureSelector: (mesh: Mesh, subMesh: SubMesh, material: Material) => Texture;
  145. /**
  146. * Instantiates a new glow Layer and references it to the scene.
  147. * @param name The name of the layer
  148. * @param scene The scene to use the layer in
  149. * @param options Sets of none mandatory options to use with the layer (see IGlowLayerOptions for more information)
  150. */
  151. constructor(name: string, scene: Scene, options?: Partial<IGlowLayerOptions>) {
  152. super(name, scene);
  153. this.neutralColor = new Color4(0, 0, 0, 1);
  154. // Adapt options
  155. this._options = {
  156. mainTextureRatio: GlowLayer.DefaultTextureRatio,
  157. blurKernelSize: 32,
  158. mainTextureFixedSize: undefined,
  159. camera: null,
  160. mainTextureSamples: 1,
  161. renderingGroupId: -1,
  162. ...options,
  163. };
  164. // Initialize the layer
  165. this._init({
  166. alphaBlendingMode: Constants.ALPHA_ADD,
  167. camera: this._options.camera,
  168. mainTextureFixedSize: this._options.mainTextureFixedSize,
  169. mainTextureRatio: this._options.mainTextureRatio,
  170. renderingGroupId: this._options.renderingGroupId
  171. });
  172. }
  173. /**
  174. * Get the effect name of the layer.
  175. * @return The effect name
  176. */
  177. public getEffectName(): string {
  178. return GlowLayer.EffectName;
  179. }
  180. /**
  181. * Create the merge effect. This is the shader use to blit the information back
  182. * to the main canvas at the end of the scene rendering.
  183. */
  184. protected _createMergeEffect(): Effect {
  185. // Effect
  186. return this._engine.createEffect("glowMapMerge",
  187. [VertexBuffer.PositionKind],
  188. ["offset"],
  189. ["textureSampler", "textureSampler2"],
  190. "#define EMISSIVE \n");
  191. }
  192. /**
  193. * Creates the render target textures and post processes used in the glow layer.
  194. */
  195. protected _createTextureAndPostProcesses(): void {
  196. var blurTextureWidth = this._mainTextureDesiredSize.width;
  197. var blurTextureHeight = this._mainTextureDesiredSize.height;
  198. blurTextureWidth = this._engine.needPOTTextures ? Engine.GetExponentOfTwo(blurTextureWidth, this._maxSize) : blurTextureWidth;
  199. blurTextureHeight = this._engine.needPOTTextures ? Engine.GetExponentOfTwo(blurTextureHeight, this._maxSize) : blurTextureHeight;
  200. var textureType = 0;
  201. if (this._engine.getCaps().textureHalfFloatRender) {
  202. textureType = Constants.TEXTURETYPE_HALF_FLOAT;
  203. }
  204. else {
  205. textureType = Constants.TEXTURETYPE_UNSIGNED_INT;
  206. }
  207. this._blurTexture1 = new RenderTargetTexture("GlowLayerBlurRTT",
  208. {
  209. width: blurTextureWidth,
  210. height: blurTextureHeight
  211. },
  212. this._scene,
  213. false,
  214. true,
  215. textureType);
  216. this._blurTexture1.wrapU = Texture.CLAMP_ADDRESSMODE;
  217. this._blurTexture1.wrapV = Texture.CLAMP_ADDRESSMODE;
  218. this._blurTexture1.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
  219. this._blurTexture1.renderParticles = false;
  220. this._blurTexture1.ignoreCameraViewport = true;
  221. var blurTextureWidth2 = Math.floor(blurTextureWidth / 2);
  222. var blurTextureHeight2 = Math.floor(blurTextureHeight / 2);
  223. this._blurTexture2 = new RenderTargetTexture("GlowLayerBlurRTT2",
  224. {
  225. width: blurTextureWidth2,
  226. height: blurTextureHeight2
  227. },
  228. this._scene,
  229. false,
  230. true,
  231. textureType);
  232. this._blurTexture2.wrapU = Texture.CLAMP_ADDRESSMODE;
  233. this._blurTexture2.wrapV = Texture.CLAMP_ADDRESSMODE;
  234. this._blurTexture2.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
  235. this._blurTexture2.renderParticles = false;
  236. this._blurTexture2.ignoreCameraViewport = true;
  237. this._textures = [this._blurTexture1, this._blurTexture2];
  238. this._horizontalBlurPostprocess1 = new BlurPostProcess("GlowLayerHBP1", new Vector2(1.0, 0), this._options.blurKernelSize / 2, {
  239. width: blurTextureWidth,
  240. height: blurTextureHeight
  241. },
  242. null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
  243. this._horizontalBlurPostprocess1.width = blurTextureWidth;
  244. this._horizontalBlurPostprocess1.height = blurTextureHeight;
  245. this._horizontalBlurPostprocess1.onApplyObservable.add((effect) => {
  246. effect.setTexture("textureSampler", this._mainTexture);
  247. });
  248. this._verticalBlurPostprocess1 = new BlurPostProcess("GlowLayerVBP1", new Vector2(0, 1.0), this._options.blurKernelSize / 2, {
  249. width: blurTextureWidth,
  250. height: blurTextureHeight
  251. },
  252. null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
  253. this._horizontalBlurPostprocess2 = new BlurPostProcess("GlowLayerHBP2", new Vector2(1.0, 0), this._options.blurKernelSize / 2, {
  254. width: blurTextureWidth2,
  255. height: blurTextureHeight2
  256. },
  257. null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
  258. this._horizontalBlurPostprocess2.width = blurTextureWidth2;
  259. this._horizontalBlurPostprocess2.height = blurTextureHeight2;
  260. this._horizontalBlurPostprocess2.onApplyObservable.add((effect) => {
  261. effect.setTexture("textureSampler", this._blurTexture1);
  262. });
  263. this._verticalBlurPostprocess2 = new BlurPostProcess("GlowLayerVBP2", new Vector2(0, 1.0), this._options.blurKernelSize / 2, {
  264. width: blurTextureWidth2,
  265. height: blurTextureHeight2
  266. },
  267. null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
  268. this._postProcesses = [this._horizontalBlurPostprocess1, this._verticalBlurPostprocess1, this._horizontalBlurPostprocess2, this._verticalBlurPostprocess2];
  269. this._postProcesses1 = [this._horizontalBlurPostprocess1, this._verticalBlurPostprocess1];
  270. this._postProcesses2 = [this._horizontalBlurPostprocess2, this._verticalBlurPostprocess2];
  271. this._mainTexture.samples = this._options.mainTextureSamples!;
  272. this._mainTexture.onAfterUnbindObservable.add(() => {
  273. let internalTexture = this._blurTexture1.getInternalTexture();
  274. if (internalTexture) {
  275. this._scene.postProcessManager.directRender(
  276. this._postProcesses1,
  277. internalTexture,
  278. true);
  279. let internalTexture2 = this._blurTexture2.getInternalTexture();
  280. if (internalTexture2) {
  281. this._scene.postProcessManager.directRender(
  282. this._postProcesses2,
  283. internalTexture2,
  284. true);
  285. }
  286. this._engine.unBindFramebuffer(internalTexture2 ?? internalTexture, true);
  287. }
  288. });
  289. // Prevent autoClear.
  290. this._postProcesses.map((pp) => { pp.autoClear = false; });
  291. }
  292. /**
  293. * Checks for the readiness of the element composing the layer.
  294. * @param subMesh the mesh to check for
  295. * @param useInstances specify wether or not to use instances to render the mesh
  296. * @param emissiveTexture the associated emissive texture used to generate the glow
  297. * @return true if ready otherwise, false
  298. */
  299. public isReady(subMesh: SubMesh, useInstances: boolean): boolean {
  300. let material = subMesh.getMaterial();
  301. let mesh = subMesh.getRenderingMesh();
  302. if (!material || !mesh) {
  303. return false;
  304. }
  305. let emissiveTexture = (<any>material).emissiveTexture;
  306. return super._isReady(subMesh, useInstances, emissiveTexture);
  307. }
  308. /**
  309. * Returns whether or nood the layer needs stencil enabled during the mesh rendering.
  310. */
  311. public needStencil(): boolean {
  312. return false;
  313. }
  314. /**
  315. * Returns true if the mesh can be rendered, otherwise false.
  316. * @param mesh The mesh to render
  317. * @param material The material used on the mesh
  318. * @returns true if it can be rendered otherwise false
  319. */
  320. protected _canRenderMesh(mesh: AbstractMesh, material: Material): boolean {
  321. return true;
  322. }
  323. /**
  324. * Implementation specific of rendering the generating effect on the main canvas.
  325. * @param effect The effect used to render through
  326. */
  327. protected _internalRender(effect: Effect): void {
  328. // Texture
  329. effect.setTexture("textureSampler", this._blurTexture1);
  330. effect.setTexture("textureSampler2", this._blurTexture2);
  331. effect.setFloat("offset", this._intensity);
  332. // Cache
  333. var engine = this._engine;
  334. var previousStencilBuffer = engine.getStencilBuffer();
  335. // Draw order
  336. engine.setStencilBuffer(false);
  337. engine.drawElementsType(Material.TriangleFillMode, 0, 6);
  338. // Draw order
  339. engine.setStencilBuffer(previousStencilBuffer);
  340. }
  341. /**
  342. * Sets the required values for both the emissive texture and and the main color.
  343. */
  344. protected _setEmissiveTextureAndColor(mesh: Mesh, subMesh: SubMesh, material: Material): void {
  345. var textureLevel = 1.0;
  346. if (this.customEmissiveTextureSelector) {
  347. this._emissiveTextureAndColor.texture = this.customEmissiveTextureSelector(mesh, subMesh, material);
  348. } else {
  349. if (material) {
  350. this._emissiveTextureAndColor.texture = (<any>material).emissiveTexture;
  351. if (this._emissiveTextureAndColor.texture) {
  352. textureLevel = this._emissiveTextureAndColor.texture.level;
  353. }
  354. }
  355. else {
  356. this._emissiveTextureAndColor.texture = null;
  357. }
  358. }
  359. if (this.customEmissiveColorSelector) {
  360. this.customEmissiveColorSelector(mesh, subMesh, material, this._emissiveTextureAndColor.color);
  361. } else {
  362. if ((<any>material).emissiveColor) {
  363. this._emissiveTextureAndColor.color.set(
  364. (<any>material).emissiveColor.r * textureLevel,
  365. (<any>material).emissiveColor.g * textureLevel,
  366. (<any>material).emissiveColor.b * textureLevel,
  367. material.alpha);
  368. }
  369. else {
  370. this._emissiveTextureAndColor.color.set(
  371. this.neutralColor.r,
  372. this.neutralColor.g,
  373. this.neutralColor.b,
  374. this.neutralColor.a);
  375. }
  376. }
  377. }
  378. /**
  379. * Returns true if the mesh should render, otherwise false.
  380. * @param mesh The mesh to render
  381. * @returns true if it should render otherwise false
  382. */
  383. protected _shouldRenderMesh(mesh: Mesh): boolean {
  384. return this.hasMesh(mesh);
  385. }
  386. /**
  387. * Adds specific effects defines.
  388. * @param defines The defines to add specifics to.
  389. */
  390. protected _addCustomEffectDefines(defines: string[]): void {
  391. defines.push("#define GLOW");
  392. }
  393. /**
  394. * Add a mesh in the exclusion list to prevent it to impact or being impacted by the glow layer.
  395. * @param mesh The mesh to exclude from the glow layer
  396. */
  397. public addExcludedMesh(mesh: Mesh): void {
  398. if (this._excludedMeshes.indexOf(mesh.uniqueId) === -1) {
  399. this._excludedMeshes.push(mesh.uniqueId);
  400. }
  401. }
  402. /**
  403. * Remove a mesh from the exclusion list to let it impact or being impacted by the glow layer.
  404. * @param mesh The mesh to remove
  405. */
  406. public removeExcludedMesh(mesh: Mesh): void {
  407. var index = this._excludedMeshes.indexOf(mesh.uniqueId);
  408. if (index !== -1) {
  409. this._excludedMeshes.splice(index, 1);
  410. }
  411. }
  412. /**
  413. * Add a mesh in the inclusion list to impact or being impacted by the glow layer.
  414. * @param mesh The mesh to include in the glow layer
  415. */
  416. public addIncludedOnlyMesh(mesh: Mesh): void {
  417. if (this._includedOnlyMeshes.indexOf(mesh.uniqueId) === -1) {
  418. this._includedOnlyMeshes.push(mesh.uniqueId);
  419. }
  420. }
  421. /**
  422. * Remove a mesh from the Inclusion list to prevent it to impact or being impacted by the glow layer.
  423. * @param mesh The mesh to remove
  424. */
  425. public removeIncludedOnlyMesh(mesh: Mesh): void {
  426. var index = this._includedOnlyMeshes.indexOf(mesh.uniqueId);
  427. if (index !== -1) {
  428. this._includedOnlyMeshes.splice(index, 1);
  429. }
  430. }
  431. /**
  432. * Determine if a given mesh will be used in the glow layer
  433. * @param mesh The mesh to test
  434. * @returns true if the mesh will be highlighted by the current glow layer
  435. */
  436. public hasMesh(mesh: AbstractMesh): boolean {
  437. if (!super.hasMesh(mesh)) {
  438. return false;
  439. }
  440. // Included Mesh
  441. if (this._includedOnlyMeshes.length) {
  442. return this._includedOnlyMeshes.indexOf(mesh.uniqueId) !== -1;
  443. }
  444. // Excluded Mesh
  445. if (this._excludedMeshes.length) {
  446. return this._excludedMeshes.indexOf(mesh.uniqueId) === -1;
  447. }
  448. return true;
  449. }
  450. /**
  451. * Defines whether the current material of the mesh should be use to render the effect.
  452. * @param mesh defines the current mesh to render
  453. */
  454. protected _useMeshMaterial(mesh: AbstractMesh): boolean {
  455. if (this._meshesUsingTheirOwnMaterials.length == 0) {
  456. return false;
  457. }
  458. return this._meshesUsingTheirOwnMaterials.indexOf(mesh.uniqueId) > -1;
  459. }
  460. /**
  461. * Add a mesh to be rendered through its own material and not with emissive only.
  462. * @param mesh The mesh for which we need to use its material
  463. */
  464. public referenceMeshToUseItsOwnMaterial(mesh: AbstractMesh): void {
  465. this._meshesUsingTheirOwnMaterials.push(mesh.uniqueId);
  466. }
  467. /**
  468. * Remove a mesh from being rendered through its own material and not with emissive only.
  469. * @param mesh The mesh for which we need to not use its material
  470. */
  471. public unReferenceMeshFromUsingItsOwnMaterial(mesh: AbstractMesh): void {
  472. let index = this._meshesUsingTheirOwnMaterials.indexOf(mesh.uniqueId);
  473. while (index >= 0) {
  474. this._meshesUsingTheirOwnMaterials.splice(index, 1);
  475. index = this._meshesUsingTheirOwnMaterials.indexOf(mesh.uniqueId);
  476. }
  477. }
  478. /**
  479. * Free any resources and references associated to a mesh.
  480. * Internal use
  481. * @param mesh The mesh to free.
  482. * @hidden
  483. */
  484. public _disposeMesh(mesh: Mesh): void {
  485. this.removeIncludedOnlyMesh(mesh);
  486. this.removeExcludedMesh(mesh);
  487. }
  488. /**
  489. * Gets the class name of the effect layer
  490. * @returns the string with the class name of the effect layer
  491. */
  492. public getClassName(): string {
  493. return "GlowLayer";
  494. }
  495. /**
  496. * Serializes this glow layer
  497. * @returns a serialized glow layer object
  498. */
  499. public serialize(): any {
  500. var serializationObject = SerializationHelper.Serialize(this);
  501. serializationObject.customType = "BABYLON.GlowLayer";
  502. var index;
  503. // Included meshes
  504. serializationObject.includedMeshes = [];
  505. if (this._includedOnlyMeshes.length) {
  506. for (index = 0; index < this._includedOnlyMeshes.length; index++) {
  507. var mesh = this._scene.getMeshByUniqueID(this._includedOnlyMeshes[index]);
  508. if (mesh) {
  509. serializationObject.includedMeshes.push(mesh.id);
  510. }
  511. }
  512. }
  513. // Excluded meshes
  514. serializationObject.excludedMeshes = [];
  515. if (this._excludedMeshes.length) {
  516. for (index = 0; index < this._excludedMeshes.length; index++) {
  517. var mesh = this._scene.getMeshByUniqueID(this._excludedMeshes[index]);
  518. if (mesh) {
  519. serializationObject.excludedMeshes.push(mesh.id);
  520. }
  521. }
  522. }
  523. return serializationObject;
  524. }
  525. /**
  526. * Creates a Glow Layer from parsed glow layer data
  527. * @param parsedGlowLayer defines glow layer data
  528. * @param scene defines the current scene
  529. * @param rootUrl defines the root URL containing the glow layer information
  530. * @returns a parsed Glow Layer
  531. */
  532. public static Parse(parsedGlowLayer: any, scene: Scene, rootUrl: string): GlowLayer {
  533. var gl = SerializationHelper.Parse(() => new GlowLayer(parsedGlowLayer.name, scene, parsedGlowLayer.options), parsedGlowLayer, scene, rootUrl);
  534. var index;
  535. // Excluded meshes
  536. for (index = 0; index < parsedGlowLayer.excludedMeshes.length; index++) {
  537. var mesh = scene.getMeshByID(parsedGlowLayer.excludedMeshes[index]);
  538. if (mesh) {
  539. gl.addExcludedMesh(<Mesh>mesh);
  540. }
  541. }
  542. // Included meshes
  543. for (index = 0; index < parsedGlowLayer.includedMeshes.length; index++) {
  544. var mesh = scene.getMeshByID(parsedGlowLayer.includedMeshes[index]);
  545. if (mesh) {
  546. gl.addIncludedOnlyMesh(<Mesh>mesh);
  547. }
  548. }
  549. return gl;
  550. }
  551. }
  552. _TypeStore.RegisteredTypes["BABYLON.GlowLayer"] = GlowLayer;