babylon.effectLayer.ts 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. module BABYLON {
  2. /**
  3. * Effect layer options. This helps customizing the behaviour
  4. * of the effect layer.
  5. */
  6. export interface IEffectLayerOptions {
  7. /**
  8. * Multiplication factor apply to the canvas size to compute the render target size
  9. * used to generated the objects (the smaller the faster).
  10. */
  11. mainTextureRatio: number;
  12. /**
  13. * Enforces a fixed size texture to ensure effect stability across devices.
  14. */
  15. mainTextureFixedSize?: number;
  16. /**
  17. * Alpha blending mode used to apply the blur. Default depends of the implementation.
  18. */
  19. alphaBlendingMode: number;
  20. /**
  21. * The camera attached to the layer.
  22. */
  23. camera: Nullable<Camera>;
  24. }
  25. /**
  26. * The effect layer Helps adding post process effect blended with the main pass.
  27. *
  28. * This can be for instance use to generate glow or higlight effects on the scene.
  29. *
  30. * The effect layer class can not be used directly and is intented to inherited from to be
  31. * customized per effects.
  32. */
  33. export abstract class EffectLayer {
  34. private _vertexBuffers: { [key: string]: Nullable<VertexBuffer> } = {};
  35. private _indexBuffer: Nullable<WebGLBuffer>;
  36. private _cachedDefines: string;
  37. private _effectLayerMapGenerationEffect: Effect;
  38. private _effectLayerOptions: IEffectLayerOptions;
  39. private _mergeEffect: Effect;
  40. protected _scene: Scene;
  41. protected _engine: Engine;
  42. protected _maxSize: number = 0;
  43. protected _mainTextureDesiredSize: ISize = { width: 0, height: 0 };
  44. protected _mainTexture: RenderTargetTexture;
  45. protected _shouldRender = true;
  46. protected _postProcesses: PostProcess[] = [];
  47. protected _textures: BaseTexture[] = [];
  48. protected _emissiveTextureAndColor: { texture: Nullable<BaseTexture>, color: Color4 } = { texture: null, color: new Color4() };
  49. /**
  50. * The name of the layer
  51. */
  52. @serialize()
  53. public name: string;
  54. /**
  55. * The clear color of the texture used to generate the glow map.
  56. */
  57. @serializeAsColor4()
  58. public neutralColor: Color4 = new Color4();
  59. /**
  60. * Specifies wether the highlight layer is enabled or not.
  61. */
  62. @serialize()
  63. public isEnabled: boolean = true;
  64. /**
  65. * Gets the camera attached to the layer.
  66. */
  67. @serializeAsCameraReference()
  68. public get camera(): Nullable<Camera> {
  69. return this._effectLayerOptions.camera;
  70. }
  71. /**
  72. * An event triggered when the effect layer has been disposed.
  73. */
  74. public onDisposeObservable = new Observable<EffectLayer>();
  75. /**
  76. * An event triggered when the effect layer is about rendering the main texture with the glowy parts.
  77. */
  78. public onBeforeRenderMainTextureObservable = new Observable<EffectLayer>();
  79. /**
  80. * An event triggered when the generated texture is being merged in the scene.
  81. */
  82. public onBeforeComposeObservable = new Observable<EffectLayer>();
  83. /**
  84. * An event triggered when the generated texture has been merged in the scene.
  85. */
  86. public onAfterComposeObservable = new Observable<EffectLayer>();
  87. /**
  88. * An event triggered when the efffect layer changes its size.
  89. */
  90. public onSizeChangedObservable = new Observable<EffectLayer>();
  91. /**
  92. * Instantiates a new effect Layer and references it in the scene.
  93. * @param name The name of the layer
  94. * @param scene The scene to use the layer in
  95. */
  96. constructor(
  97. /** The Friendly of the effect in the scene */
  98. name: string,
  99. scene: Scene) {
  100. this.name = name;
  101. this._scene = scene || Engine.LastCreatedScene;
  102. this._engine = scene.getEngine();
  103. this._maxSize = this._engine.getCaps().maxTextureSize;
  104. this._scene.effectLayers.push(this);
  105. // Generate Buffers
  106. this._generateIndexBuffer();
  107. this._genrateVertexBuffer();
  108. }
  109. /**
  110. * Get the effect name of the layer.
  111. * @return The effect name
  112. */
  113. public abstract getEffectName(): string;
  114. /**
  115. * Checks for the readiness of the element composing the layer.
  116. * @param subMesh the mesh to check for
  117. * @param useInstances specify wether or not to use instances to render the mesh
  118. * @return true if ready otherwise, false
  119. */
  120. public abstract isReady(subMesh: SubMesh, useInstances: boolean): boolean;
  121. /**
  122. * Returns wether or nood the layer needs stencil enabled during the mesh rendering.
  123. * @returns true if the effect requires stencil during the main canvas render pass.
  124. */
  125. public abstract needStencil(): boolean;
  126. /**
  127. * Create the merge effect. This is the shader use to blit the information back
  128. * to the main canvas at the end of the scene rendering.
  129. * @returns The effect containing the shader used to merge the effect on the main canvas
  130. */
  131. protected abstract _createMergeEffect(): Effect;
  132. /**
  133. * Creates the render target textures and post processes used in the effect layer.
  134. */
  135. protected abstract _createTextureAndPostProcesses(): void;
  136. /**
  137. * Implementation specific of rendering the generating effect on the main canvas.
  138. * @param effect The effect used to render through
  139. */
  140. protected abstract _internalRender(effect: Effect): void;
  141. /**
  142. * Sets the required values for both the emissive texture and and the main color.
  143. */
  144. protected abstract _setEmissiveTextureAndColor(mesh: Mesh, subMesh: SubMesh, material: Material): void;
  145. /**
  146. * Free any resources and references associated to a mesh.
  147. * Internal use
  148. * @param mesh The mesh to free.
  149. */
  150. public abstract _disposeMesh(mesh: Mesh): void;
  151. /**
  152. * Initializes the effect layer with the required options.
  153. * @param options Sets of none mandatory options to use with the layer (see IEffectLayerOptions for more information)
  154. */
  155. protected _init(options: Partial<IEffectLayerOptions>): void {
  156. // Adapt options
  157. this._effectLayerOptions = {
  158. mainTextureRatio: 0.5,
  159. alphaBlendingMode: Engine.ALPHA_COMBINE,
  160. camera: null,
  161. ...options,
  162. };
  163. this._setMainTextureSize();
  164. this._createMainTexture();
  165. this._createTextureAndPostProcesses();
  166. this._mergeEffect = this._createMergeEffect();
  167. }
  168. /**
  169. * Generates the index buffer of the full screen quad blending to the main canvas.
  170. */
  171. private _generateIndexBuffer(): void {
  172. // Indices
  173. var indices = [];
  174. indices.push(0);
  175. indices.push(1);
  176. indices.push(2);
  177. indices.push(0);
  178. indices.push(2);
  179. indices.push(3);
  180. this._indexBuffer = this._engine.createIndexBuffer(indices);
  181. }
  182. /**
  183. * Generates the vertex buffer of the full screen quad blending to the main canvas.
  184. */
  185. private _genrateVertexBuffer(): void {
  186. // VBO
  187. var vertices = [];
  188. vertices.push(1, 1);
  189. vertices.push(-1, 1);
  190. vertices.push(-1, -1);
  191. vertices.push(1, -1);
  192. var vertexBuffer = new VertexBuffer(this._engine, vertices, VertexBuffer.PositionKind, false, false, 2);
  193. this._vertexBuffers[VertexBuffer.PositionKind] = vertexBuffer;
  194. }
  195. /**
  196. * Sets the main texture desired size which is the closest power of two
  197. * of the engine canvas size.
  198. */
  199. private _setMainTextureSize(): void {
  200. if (this._effectLayerOptions.mainTextureFixedSize) {
  201. this._mainTextureDesiredSize.width = this._effectLayerOptions.mainTextureFixedSize;
  202. this._mainTextureDesiredSize.height = this._effectLayerOptions.mainTextureFixedSize;
  203. }
  204. else {
  205. this._mainTextureDesiredSize.width = this._engine.getRenderWidth() * this._effectLayerOptions.mainTextureRatio;
  206. this._mainTextureDesiredSize.height = this._engine.getRenderHeight() * this._effectLayerOptions.mainTextureRatio;
  207. this._mainTextureDesiredSize.width = this._engine.needPOTTextures ? Tools.GetExponentOfTwo(this._mainTextureDesiredSize.width, this._maxSize) : this._mainTextureDesiredSize.width;
  208. this._mainTextureDesiredSize.height = this._engine.needPOTTextures ? Tools.GetExponentOfTwo(this._mainTextureDesiredSize.height, this._maxSize) : this._mainTextureDesiredSize.height;
  209. }
  210. this._mainTextureDesiredSize.width = Math.floor(this._mainTextureDesiredSize.width);
  211. this._mainTextureDesiredSize.height = Math.floor(this._mainTextureDesiredSize.height);
  212. }
  213. /**
  214. * Creates the main texture for the effect layer.
  215. */
  216. protected _createMainTexture(): void {
  217. this._mainTexture = new RenderTargetTexture("HighlightLayerMainRTT",
  218. {
  219. width: this._mainTextureDesiredSize.width,
  220. height: this._mainTextureDesiredSize.height
  221. },
  222. this._scene,
  223. false,
  224. true,
  225. Engine.TEXTURETYPE_UNSIGNED_INT);
  226. this._mainTexture.activeCamera = this._effectLayerOptions.camera;
  227. this._mainTexture.wrapU = Texture.CLAMP_ADDRESSMODE;
  228. this._mainTexture.wrapV = Texture.CLAMP_ADDRESSMODE;
  229. this._mainTexture.anisotropicFilteringLevel = 1;
  230. this._mainTexture.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
  231. this._mainTexture.renderParticles = false;
  232. this._mainTexture.renderList = null;
  233. this._mainTexture.ignoreCameraViewport = true;
  234. // Custom render function
  235. this._mainTexture.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
  236. this.onBeforeRenderMainTextureObservable.notifyObservers(this);
  237. var index: number;
  238. let engine = this._scene.getEngine();
  239. if (depthOnlySubMeshes.length) {
  240. engine.setColorWrite(false);
  241. for (index = 0; index < depthOnlySubMeshes.length; index++) {
  242. this._renderSubMesh(depthOnlySubMeshes.data[index]);
  243. }
  244. engine.setColorWrite(true);
  245. }
  246. for (index = 0; index < opaqueSubMeshes.length; index++) {
  247. this._renderSubMesh(opaqueSubMeshes.data[index]);
  248. }
  249. for (index = 0; index < alphaTestSubMeshes.length; index++) {
  250. this._renderSubMesh(alphaTestSubMeshes.data[index]);
  251. }
  252. for (index = 0; index < transparentSubMeshes.length; index++) {
  253. this._renderSubMesh(transparentSubMeshes.data[index]);
  254. }
  255. };
  256. this._mainTexture.onClearObservable.add((engine: Engine) => {
  257. engine.clear(this.neutralColor, true, true, true);
  258. });
  259. }
  260. /**
  261. * Checks for the readiness of the element composing the layer.
  262. * @param subMesh the mesh to check for
  263. * @param useInstances specify wether or not to use instances to render the mesh
  264. * @param emissiveTexture the associated emissive texture used to generate the glow
  265. * @return true if ready otherwise, false
  266. */
  267. protected _isReady(subMesh: SubMesh, useInstances: boolean, emissiveTexture: Nullable<BaseTexture>): boolean {
  268. let material = subMesh.getMaterial();
  269. if (!material) {
  270. return false;
  271. }
  272. if (!material.isReady(subMesh.getMesh(), useInstances)) {
  273. return false;
  274. }
  275. var defines = [];
  276. var attribs = [VertexBuffer.PositionKind];
  277. var mesh = subMesh.getMesh();
  278. var uv1 = false;
  279. var uv2 = false;
  280. // Alpha test
  281. if (material && material.needAlphaTesting()) {
  282. var alphaTexture = material.getAlphaTestTexture();
  283. if (alphaTexture) {
  284. defines.push("#define ALPHATEST");
  285. if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind) &&
  286. alphaTexture.coordinatesIndex === 1) {
  287. defines.push("#define DIFFUSEUV2");
  288. uv2 = true;
  289. }
  290. else if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
  291. defines.push("#define DIFFUSEUV1");
  292. uv1 = true;
  293. }
  294. }
  295. }
  296. // Emissive
  297. if (emissiveTexture) {
  298. defines.push("#define EMISSIVE");
  299. if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind) &&
  300. emissiveTexture.coordinatesIndex === 1) {
  301. defines.push("#define EMISSIVEUV2");
  302. uv2 = true;
  303. }
  304. else if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
  305. defines.push("#define EMISSIVEUV1");
  306. uv1 = true;
  307. }
  308. }
  309. if (uv1) {
  310. attribs.push(VertexBuffer.UVKind);
  311. defines.push("#define UV1");
  312. }
  313. if (uv2) {
  314. attribs.push(VertexBuffer.UV2Kind);
  315. defines.push("#define UV2");
  316. }
  317. // Bones
  318. if (mesh.useBones && mesh.computeBonesUsingShaders) {
  319. attribs.push(VertexBuffer.MatricesIndicesKind);
  320. attribs.push(VertexBuffer.MatricesWeightsKind);
  321. if (mesh.numBoneInfluencers > 4) {
  322. attribs.push(VertexBuffer.MatricesIndicesExtraKind);
  323. attribs.push(VertexBuffer.MatricesWeightsExtraKind);
  324. }
  325. defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
  326. defines.push("#define BonesPerMesh " + (mesh.skeleton ? (mesh.skeleton.bones.length + 1) : 0));
  327. } else {
  328. defines.push("#define NUM_BONE_INFLUENCERS 0");
  329. }
  330. // Morph targets
  331. var manager = (<Mesh>mesh).morphTargetManager;
  332. let morphInfluencers = 0;
  333. if (manager) {
  334. if (manager.numInfluencers > 0) {
  335. defines.push("#define MORPHTARGETS");
  336. morphInfluencers = manager.numInfluencers;
  337. defines.push("#define NUM_MORPH_INFLUENCERS " + morphInfluencers);
  338. MaterialHelper.PrepareAttributesForMorphTargets(attribs, mesh, {"NUM_MORPH_INFLUENCERS": morphInfluencers });
  339. }
  340. }
  341. // Instances
  342. if (useInstances) {
  343. defines.push("#define INSTANCES");
  344. attribs.push("world0");
  345. attribs.push("world1");
  346. attribs.push("world2");
  347. attribs.push("world3");
  348. }
  349. // Get correct effect
  350. var join = defines.join("\n");
  351. if (this._cachedDefines !== join) {
  352. this._cachedDefines = join;
  353. this._effectLayerMapGenerationEffect = this._scene.getEngine().createEffect("glowMapGeneration",
  354. attribs,
  355. ["world", "mBones", "viewProjection", "diffuseMatrix", "color", "emissiveMatrix", "morphTargetInfluences"],
  356. ["diffuseSampler", "emissiveSampler"], join,
  357. undefined, undefined, undefined, { maxSimultaneousMorphTargets: morphInfluencers });
  358. }
  359. return this._effectLayerMapGenerationEffect.isReady();
  360. }
  361. /**
  362. * Renders the glowing part of the scene by blending the blurred glowing meshes on top of the rendered scene.
  363. */
  364. public render(): void {
  365. var currentEffect = this._mergeEffect;
  366. // Check
  367. if (!currentEffect.isReady())
  368. return;
  369. for (var i = 0; i < this._postProcesses.length; i++) {
  370. if (!this._postProcesses[i].isReady()) {
  371. return;
  372. }
  373. }
  374. var engine = this._scene.getEngine();
  375. this.onBeforeComposeObservable.notifyObservers(this);
  376. // Render
  377. engine.enableEffect(currentEffect);
  378. engine.setState(false);
  379. // VBOs
  380. engine.bindBuffers(this._vertexBuffers, this._indexBuffer, currentEffect);
  381. // Cache
  382. var previousAlphaMode = engine.getAlphaMode();
  383. // Go Blend.
  384. engine.setAlphaMode(this._effectLayerOptions.alphaBlendingMode);
  385. // Blends the map on the main canvas.
  386. this._internalRender(currentEffect);
  387. // Restore Alpha
  388. engine.setAlphaMode(previousAlphaMode);
  389. this.onAfterComposeObservable.notifyObservers(this);
  390. // Handle size changes.
  391. var size = this._mainTexture.getSize();
  392. this._setMainTextureSize();
  393. if (size.width !== this._mainTextureDesiredSize.width || size.height !== this._mainTextureDesiredSize.height) {
  394. // Recreate RTT and post processes on size change.
  395. this.onSizeChangedObservable.notifyObservers(this);
  396. this._disposeTextureAndPostProcesses();
  397. this._createMainTexture();
  398. this._createTextureAndPostProcesses();
  399. }
  400. }
  401. /**
  402. * Determine if a given mesh will be used in the current effect.
  403. * @param mesh mesh to test
  404. * @returns true if the mesh will be used
  405. */
  406. public hasMesh(mesh: AbstractMesh): boolean {
  407. return true;
  408. }
  409. /**
  410. * Returns true if the layer contains information to display, otherwise false.
  411. * @returns true if the glow layer should be rendered
  412. */
  413. public shouldRender(): boolean {
  414. return this.isEnabled && this._shouldRender;
  415. }
  416. /**
  417. * Returns true if the mesh should render, otherwise false.
  418. * @param mesh The mesh to render
  419. * @returns true if it should render otherwise false
  420. */
  421. protected _shouldRenderMesh(mesh: Mesh): boolean {
  422. return true;
  423. }
  424. /**
  425. * Returns true if the mesh should render, otherwise false.
  426. * @param mesh The mesh to render
  427. * @returns true if it should render otherwise false
  428. */
  429. protected _shouldRenderEmissiveTextureForMesh(mesh: Mesh): boolean {
  430. return true;
  431. }
  432. /**
  433. * Renders the submesh passed in parameter to the generation map.
  434. */
  435. protected _renderSubMesh(subMesh: SubMesh): void {
  436. if (!this.shouldRender()) {
  437. return;
  438. }
  439. var material = subMesh.getMaterial();
  440. var mesh = subMesh.getRenderingMesh();
  441. var scene = this._scene;
  442. var engine = scene.getEngine();
  443. if (!material) {
  444. return;
  445. }
  446. // Do not block in blend mode.
  447. if (material.needAlphaBlendingForMesh(mesh)) {
  448. return;
  449. }
  450. // Culling
  451. engine.setState(material.backFaceCulling);
  452. // Managing instances
  453. var batch = mesh._getInstancesRenderList(subMesh._id);
  454. if (batch.mustReturn) {
  455. return;
  456. }
  457. // Early Exit per mesh
  458. if (!this._shouldRenderMesh(mesh)) {
  459. return;
  460. }
  461. var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
  462. this._setEmissiveTextureAndColor(mesh, subMesh, material);
  463. if (this._isReady(subMesh, hardwareInstancedRendering, this._emissiveTextureAndColor.texture)) {
  464. engine.enableEffect(this._effectLayerMapGenerationEffect);
  465. mesh._bind(subMesh, this._effectLayerMapGenerationEffect, Material.TriangleFillMode);
  466. this._effectLayerMapGenerationEffect.setMatrix("viewProjection", scene.getTransformMatrix());
  467. this._effectLayerMapGenerationEffect.setFloat4("color",
  468. this._emissiveTextureAndColor.color.r,
  469. this._emissiveTextureAndColor.color.g,
  470. this._emissiveTextureAndColor.color.b,
  471. this._emissiveTextureAndColor.color.a);
  472. // Alpha test
  473. if (material && material.needAlphaTesting()) {
  474. var alphaTexture = material.getAlphaTestTexture();
  475. if (alphaTexture) {
  476. this._effectLayerMapGenerationEffect.setTexture("diffuseSampler", alphaTexture);
  477. let textureMatrix = alphaTexture.getTextureMatrix();
  478. if (textureMatrix) {
  479. this._effectLayerMapGenerationEffect.setMatrix("diffuseMatrix", textureMatrix);
  480. }
  481. }
  482. }
  483. // Glow emissive only
  484. if (this._emissiveTextureAndColor.texture) {
  485. this._effectLayerMapGenerationEffect.setTexture("emissiveSampler", this._emissiveTextureAndColor.texture);
  486. this._effectLayerMapGenerationEffect.setMatrix("emissiveMatrix", this._emissiveTextureAndColor.texture.getTextureMatrix());
  487. }
  488. // Bones
  489. if (mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
  490. this._effectLayerMapGenerationEffect.setMatrices("mBones", mesh.skeleton.getTransformMatrices(mesh));
  491. }
  492. // Morph targets
  493. MaterialHelper.BindMorphTargetParameters(mesh, this._effectLayerMapGenerationEffect);
  494. // Draw
  495. mesh._processRendering(subMesh, this._effectLayerMapGenerationEffect, Material.TriangleFillMode, batch, hardwareInstancedRendering,
  496. (isInstance, world) => this._effectLayerMapGenerationEffect.setMatrix("world", world));
  497. } else {
  498. // Need to reset refresh rate of the shadowMap
  499. this._mainTexture.resetRefreshCounter();
  500. }
  501. }
  502. /**
  503. * Rebuild the required buffers.
  504. * @ignore Internal use only.
  505. */
  506. public _rebuild(): void {
  507. let vb = this._vertexBuffers[VertexBuffer.PositionKind];
  508. if (vb) {
  509. vb._rebuild();
  510. }
  511. this._generateIndexBuffer();
  512. }
  513. /**
  514. * Dispose only the render target textures and post process.
  515. */
  516. private _disposeTextureAndPostProcesses(): void {
  517. this._mainTexture.dispose();
  518. for (var i = 0; i < this._postProcesses.length; i++) {
  519. if (this._postProcesses[i]) {
  520. this._postProcesses[i].dispose();
  521. }
  522. }
  523. this._postProcesses = [];
  524. for (var i = 0; i < this._textures.length; i++) {
  525. if (this._textures[i]) {
  526. this._textures[i].dispose();
  527. }
  528. }
  529. this._textures = [];
  530. }
  531. /**
  532. * Dispose the highlight layer and free resources.
  533. */
  534. public dispose(): void {
  535. var vertexBuffer = this._vertexBuffers[VertexBuffer.PositionKind];
  536. if (vertexBuffer) {
  537. vertexBuffer.dispose();
  538. this._vertexBuffers[VertexBuffer.PositionKind] = null;
  539. }
  540. if (this._indexBuffer) {
  541. this._scene.getEngine()._releaseBuffer(this._indexBuffer);
  542. this._indexBuffer = null;
  543. }
  544. // Clean textures and post processes
  545. this._disposeTextureAndPostProcesses();
  546. // Remove from scene
  547. var index = this._scene.effectLayers.indexOf(this, 0);
  548. if (index > -1) {
  549. this._scene.effectLayers.splice(index, 1);
  550. }
  551. // Callback
  552. this.onDisposeObservable.notifyObservers(this);
  553. this.onDisposeObservable.clear();
  554. this.onBeforeRenderMainTextureObservable.clear();
  555. this.onBeforeComposeObservable.clear();
  556. this.onAfterComposeObservable.clear();
  557. this.onSizeChangedObservable.clear();
  558. }
  559. /**
  560. * Gets the class name of the effect layer
  561. * @returns the string with the class name of the effect layer
  562. */
  563. public getClassName(): string {
  564. return "EffectLayer";
  565. }
  566. }
  567. }