effectLayer.ts 29 KB

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